From f89f09872bf7489d5e4c19c46a2ed51a8714cc41 Mon Sep 17 00:00:00 2001 From: TrebleSnake Date: Tue, 13 Oct 2015 17:23:52 +0300 Subject: Fix condition precedence --- .../impl/protocol/yahoo/ServerStoredContactListYahooImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java index e732b84..6bfb239 100644 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java @@ -1199,8 +1199,10 @@ public class ServerStoredContactListYahooImpl Contact srcContact = findContactById(ev.getFrom()); if(srcContact == null) + { if (logger.isTraceEnabled()) logger.trace("No contact found"); + } else handler.processAuthorizationResponse( new AuthorizationResponse( @@ -1215,8 +1217,10 @@ public class ServerStoredContactListYahooImpl Contact srcContact = findContactById(ev.getFrom()); if(srcContact == null) + { if (logger.isTraceEnabled()) logger.trace("No contact found"); + } else { handler.processAuthorizationResponse( -- cgit v1.1 From 378d3fc05f30c42eaeb396f9bcf2a8d6f2ad43b8 Mon Sep 17 00:00:00 2001 From: George Politis Date: Fri, 16 Oct 2015 11:40:01 -0500 Subject: Adds configuration for logging arbitrary packets. --- lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar | Bin 7705340 -> 7709743 bytes .../PacketLoggingConfigurationImpl.java | 4 ++++ .../packetlogging/PacketLoggingServiceImpl.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar index cf37b9e..b51dcb5 100644 Binary files a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar and b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar differ diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingConfigurationImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingConfigurationImpl.java index b26b11a..978c74c 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingConfigurationImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingConfigurationImpl.java @@ -60,6 +60,10 @@ public class PacketLoggingConfigurationImpl configService.getBoolean( PACKET_LOGGING_ICE4J_ENABLED_PROPERTY_NAME, isIce4JLoggingEnabled())); + super.setArbitraryLoggingEnabled( + configService.getBoolean( + PACKET_LOGGING_ARBITRARY_ENABLED_PROPERTY_NAME, + isArbitraryLoggingEnabled())); super.setLimit( configService.getLong( PACKET_LOGGING_FILE_SIZE_PROPERTY_NAME, diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 788e8db..1799dbf 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -321,6 +321,8 @@ public class PacketLoggingServiceImpl return cfg.isRTPLoggingEnabled(); case ICE4J: return cfg.isIce4JLoggingEnabled(); + case ARBITRARY: + return cfg.isArbitraryLoggingEnabled(); default: /* * It may seem like it was unnecessary to invoke -- cgit v1.1 From e0a28662b01960fa51d78629322a2f3322e34de5 Mon Sep 17 00:00:00 2001 From: George Politis Date: Fri, 16 Oct 2015 11:41:15 -0500 Subject: Uses an EvictingQueue instead of an ArrayList in the PacketLoggingServiceImpl. --- .../communicator/impl/packetlogging/PacketLoggingServiceImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 1799dbf..1954f99 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -20,6 +20,7 @@ package net.java.sip.communicator.impl.packetlogging; import java.io.*; import java.util.*; +import com.google.common.collect.*; import net.java.sip.communicator.util.*; import org.jitsi.service.fileaccess.*; @@ -769,7 +770,7 @@ public class PacketLoggingServiceImpl /** * List of packets queued to be written in the file. */ - private final List pktsToSave = new ArrayList(); + private final Queue pktsToSave = EvictingQueue.create(10); /** * Initializes a new SaverThread. @@ -805,7 +806,7 @@ public class PacketLoggingServiceImpl continue; } - pktToSave = pktsToSave.remove(0); + pktToSave = pktsToSave.poll(); } if(pktToSave != null) -- cgit v1.1 From 2f3adb9281dbd5fe1be91fc9151d2612c37f7441 Mon Sep 17 00:00:00 2001 From: George Politis Date: Fri, 16 Oct 2015 12:02:10 -0500 Subject: Adds Guava as a dependency to the jitsi-packetlogging module. --- m2/jitsi-packetlogging/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/m2/jitsi-packetlogging/pom.xml b/m2/jitsi-packetlogging/pom.xml index 5f0ce33..9ff7d47 100644 --- a/m2/jitsi-packetlogging/pom.xml +++ b/m2/jitsi-packetlogging/pom.xml @@ -23,6 +23,10 @@ libjitsi + com.google.guava + guava + + org.osgi org.osgi.core -- cgit v1.1 From f5dc6edede237288d6b09dddcabd1ed47f55c8c2 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 28 Oct 2015 00:44:50 +0100 Subject: Remove bundle start level conflict Fixes #162 Fixes #163 Fixes #172 The build process injects an additional bundle at start level 14. This conflicted with the start level for commons-codec, preventing Jitsi to start. Felix' bundle cache might have prevented the bug from appearing for people who had a previous version running successfully. --- lib/felix.client.run.properties | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index b1cc220..061b70a 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -48,8 +48,12 @@ felix.auto.start.10= \ # file:lib/bundle/servicebinder.jar \ # file:lib/bundle/tablelayout.jar -felix.auto.start.14= \ +felix.auto.start.13= \ reference:file:sc-bundles/commons-codec.jar + +#warning: felix.auto.start.14 is injected by the windows build +# for the clean-shutdown-bundle + felix.auto.start.15= \ reference:file:sc-bundles/zrtp4j.jar \ reference:file:sc-bundles/sdes4j.jar -- cgit v1.1 From e9ee16a7ba9255fc719eea7e02558fb4dfc2156e Mon Sep 17 00:00:00 2001 From: damencho Date: Thu, 5 Nov 2015 11:55:12 -0600 Subject: Adds option to set custom headers to the sip call. --- .../impl/protocol/sip/CallSipImpl.java | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java index fa0e08e..0471d1a 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java @@ -78,6 +78,24 @@ public class CallSipImpl public static final String DS_SHARING_HEADER = "X-Desktop-Share"; /** + * Custom header name prefix that can be added to the call instance. + * Several headers can be specified in the form of: + * EXTRA_HEADER_NAME.1=... + * EXTRA_HEADER_NAME.2=... + * Index starting from 1. + */ + public static final String EXTRA_HEADER_NAME = "EXTRA_HEADER_NAME"; + + /** + * Custom header value prefix that can be added to the call instance. + * Several headers can be specified in the form of: + * EXTRA_HEADER_VALUE.1=... + * EXTRA_HEADER_VALUE.2=... + * Index starting from 1. + */ + public static final String EXTRA_HEADER_VALUE = "EXTRA_HEADER_VALUE"; + + /** * When starting call we may have quality preferences we must use * for the call. */ @@ -706,6 +724,22 @@ public class CallSipImpl protected void processExtraHeaders(javax.sip.message.Message message) throws ParseException { + // If there are custom headers added to the call instance, add those + // headers + int extraHeaderIx = 1; + + Object name = getData(EXTRA_HEADER_NAME + "." + extraHeaderIx); + while(name != null) + { + Object value = getData(EXTRA_HEADER_VALUE + "." + extraHeaderIx); + + Header header = getProtocolProvider().getHeaderFactory() + .createHeader((String) name, (String) value); + message.setHeader(header); + + extraHeaderIx++; + name = getData(EXTRA_HEADER_NAME + "." + extraHeaderIx); + } } /** -- cgit v1.1 From 6b2be3be614874af89f91ec2dc02a1dc4e335aa9 Mon Sep 17 00:00:00 2001 From: George Politis Date: Thu, 5 Nov 2015 18:09:44 +0000 Subject: jitsi-packetlogging depends on jitsi-util. --- m2/jitsi-packetlogging/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/m2/jitsi-packetlogging/pom.xml b/m2/jitsi-packetlogging/pom.xml index 9ff7d47..bcd42f1 100644 --- a/m2/jitsi-packetlogging/pom.xml +++ b/m2/jitsi-packetlogging/pom.xml @@ -23,6 +23,10 @@ libjitsi + ${project.groupId} + jitsi-util + + com.google.guava guava -- cgit v1.1 From 075ad10a9ccacf5a4dcaa8cd7fe4fd851767f70f Mon Sep 17 00:00:00 2001 From: George Politis Date: Thu, 5 Nov 2015 18:12:15 +0000 Subject: Renames SimulcastLayer to SimulcastStream. --- .../jabber/extensions/colibri/ColibriConferenceIQ.java | 12 ++++++------ .../jabber/extensions/colibri/ColibriIQProvider.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java index 52368bf..34a46f6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java @@ -631,7 +631,7 @@ public class ColibriConferenceIQ * Videobridge to the endpoint associated with this video * Channel. */ - private Integer receivingSimulcastLayer; + private Integer receivingSimulcastStream; /** * The RTCP port of the channel represented by this instance. @@ -929,9 +929,9 @@ public class ColibriConferenceIQ * from Jitsi Videobridge to the endpoint associated with this video * Channel. */ - public Integer getReceivingSimulcastLayer() + public Integer getReceivingSimulcastStream() { - return receivingSimulcastLayer; + return receivingSimulcastStream; } /** @@ -1327,13 +1327,13 @@ public class ColibriConferenceIQ * Jitsi Videobridge to the endpoint associated with this video * Channel. * - * @param simulcastLayer the target quality of the simulcast substreams + * @param simulcastStream the target quality of the simulcast substreams * to be sent from Jitsi Videobridge to the endpoint associated with * this video Channel. */ - public void setReceivingSimulcastLayer(Integer simulcastLayer) + public void setReceivingSimulcastStream(Integer simulcastStream) { - this.receivingSimulcastLayer = simulcastLayer; + this.receivingSimulcastStream = simulcastStream; } /** diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 39e299f..bb579a4 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -476,16 +476,16 @@ public class ColibriIQProvider SimulcastMode.fromString(simulcastMode)); // receiving simulcast layer - String receivingSimulcastLayer + String receivingSimulcastStream = parser.getAttributeValue( "", ColibriConferenceIQ.Channel .RECEIVING_SIMULCAST_LAYER); - if ((receivingSimulcastLayer != null) - && (receivingSimulcastLayer.length() != 0)) - channel.setReceivingSimulcastLayer( - Integer.parseInt(receivingSimulcastLayer)); + if ((receivingSimulcastStream != null) + && (receivingSimulcastStream.length() != 0)) + channel.setReceivingSimulcastStream( + Integer.parseInt(receivingSimulcastStream)); // rtcpPort String rtcpPort -- cgit v1.1 From 2c307e06919ba28326ee68742eb2d5c399d27bcb Mon Sep 17 00:00:00 2001 From: George Politis Date: Thu, 5 Nov 2015 22:49:21 +0000 Subject: Updates the packetlogging manifest to import com.google.common.collect. --- .../java/sip/communicator/impl/packetlogging/packetlogging.manifest.mf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/packetlogging.manifest.mf b/src/net/java/sip/communicator/impl/packetlogging/packetlogging.manifest.mf index 374294f..2099f02 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/packetlogging.manifest.mf +++ b/src/net/java/sip/communicator/impl/packetlogging/packetlogging.manifest.mf @@ -16,4 +16,5 @@ Import-Package: org.osgi.framework, javax.swing, javax.swing.border, javax.swing.event, - javax.swing.text + javax.swing.text, + com.google.common.collect -- cgit v1.1 From 6d0a49965098e6cb67b4751d5079cbc22003f27a Mon Sep 17 00:00:00 2001 From: George Politis Date: Thu, 5 Nov 2015 22:53:43 +0000 Subject: Revert "Renames SimulcastLayer to SimulcastStream." This reverts commit 075ad10a9ccacf5a4dcaa8cd7fe4fd851767f70f. --- .../jabber/extensions/colibri/ColibriConferenceIQ.java | 12 ++++++------ .../jabber/extensions/colibri/ColibriIQProvider.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java index 34a46f6..52368bf 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java @@ -631,7 +631,7 @@ public class ColibriConferenceIQ * Videobridge to the endpoint associated with this video * Channel. */ - private Integer receivingSimulcastStream; + private Integer receivingSimulcastLayer; /** * The RTCP port of the channel represented by this instance. @@ -929,9 +929,9 @@ public class ColibriConferenceIQ * from Jitsi Videobridge to the endpoint associated with this video * Channel. */ - public Integer getReceivingSimulcastStream() + public Integer getReceivingSimulcastLayer() { - return receivingSimulcastStream; + return receivingSimulcastLayer; } /** @@ -1327,13 +1327,13 @@ public class ColibriConferenceIQ * Jitsi Videobridge to the endpoint associated with this video * Channel. * - * @param simulcastStream the target quality of the simulcast substreams + * @param simulcastLayer the target quality of the simulcast substreams * to be sent from Jitsi Videobridge to the endpoint associated with * this video Channel. */ - public void setReceivingSimulcastStream(Integer simulcastStream) + public void setReceivingSimulcastLayer(Integer simulcastLayer) { - this.receivingSimulcastStream = simulcastStream; + this.receivingSimulcastLayer = simulcastLayer; } /** diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index bb579a4..39e299f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -476,16 +476,16 @@ public class ColibriIQProvider SimulcastMode.fromString(simulcastMode)); // receiving simulcast layer - String receivingSimulcastStream + String receivingSimulcastLayer = parser.getAttributeValue( "", ColibriConferenceIQ.Channel .RECEIVING_SIMULCAST_LAYER); - if ((receivingSimulcastStream != null) - && (receivingSimulcastStream.length() != 0)) - channel.setReceivingSimulcastStream( - Integer.parseInt(receivingSimulcastStream)); + if ((receivingSimulcastLayer != null) + && (receivingSimulcastLayer.length() != 0)) + channel.setReceivingSimulcastLayer( + Integer.parseInt(receivingSimulcastLayer)); // rtcpPort String rtcpPort -- cgit v1.1 From 6fcbb76665397dae6d6395f5155c955e4e052863 Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Fri, 2 Oct 2015 07:41:43 +0200 Subject: Fixes the contacts 'call button' disappearing on multiresource contacts This changes the behaviour from "last connected resource" or "highest priority resource" to "most capable resource" regarding the display of buttons next to this contact. We now check every resource the contact has connected and we will consider the one with the most capabilities. This elimates the very frustrating scenario in which the call capabilites are disabled on a contact who connected additionally a non-jingle client. Note that there exists separate issue in which the contact logs off from only one resource, but gets displayed as completely offline. In that case the buttons are still displayed wrong, if the contact connects a non-jingle client on afterwards. --- .../impl/protocol/jabber/MobileIndicator.java | 8 ++- .../OperationSetContactCapabilitiesJabberImpl.java | 74 +++++++++++++++++++--- .../jabber/extensions/caps/EntityCapsManager.java | 34 +++++++++- .../extensions/caps/UserCapsNodeListener.java | 10 ++- 4 files changed, 110 insertions(+), 16 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java b/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java index 926848c..8c801c6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/MobileIndicator.java @@ -222,11 +222,13 @@ public class MobileIndicator /** * Caps for user has been changed. * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user for which we're notified is online */ @Override - public void userCapsNodeAdded(String user, String node, boolean online) + public void userCapsNodeAdded(String user, ArrayList fullJids, + String node, boolean online) { updateMobileIndicatorUsingCaps(user); } @@ -234,11 +236,13 @@ public class MobileIndicator /** * Caps for user has been changed. * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user for which we're notified is online */ @Override - public void userCapsNodeRemoved(String user, String node, boolean online) + public void userCapsNodeRemoved(String user, ArrayList fullJids, + String node, boolean online) { updateMobileIndicatorUsingCaps(user); } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index 0a6edfe..a1767dd 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -276,6 +276,41 @@ public class OperationSetContactCapabilitiesJabberImpl } /** + * Gets the largest set of OperationSets supported from a + * list of full JIDs. The returned OperationSets are considered + * by the associated protocol provider to capabilities possessed by the + * specified contact. + * + * @param fullJids a list of full JIDs in which to find the resource with + * the most capabilities. + * @return the Map listing the most OperationSets + * considered by the associated protocol provider to be supported by the + * specified contact (i.e. to be possessed as capabilities). + * Each supported OperationSet capability is represented by a + * Map.Entry with key equal to the OperationSet class + * name and value equal to the respective OperationSet instance + */ + protected Map getLargestSupportedOperationSet( + ArrayList fullJids) + { + Map supportedOperationSets = + new HashMap(); + if (fullJids!=null){ + for (String fullJid : fullJids) + { + Map newSupportedOperationSets= + getSupportedOperationSets(fullJid, true); + if (newSupportedOperationSets.size()> + supportedOperationSets.size()) + { + supportedOperationSets = newSupportedOperationSets; + } + } + } + return supportedOperationSets; + } + + /** * Gets the OperationSet corresponding to the specified * Class and supported by the specified Contact. If the * returned value is non-null, it indicates that the @@ -387,17 +422,19 @@ public class OperationSetContactCapabilitiesJabberImpl * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user is currently online * @see UserCapsNodeListener#userCapsNodeAdded(String, String, boolean) */ - public void userCapsNodeAdded(String user, String node, boolean online) + public void userCapsNodeAdded(String user, ArrayList fullJids, + String node, boolean online) { /* * It doesn't matter to us whether a caps node has been added or removed * for the specified user because we report all changes. */ - userCapsNodeRemoved(user, node, online); + userCapsNodeChanged(user, fullJids, node, online); } /** @@ -405,19 +442,39 @@ public class OperationSetContactCapabilitiesJabberImpl * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) + * @param node the entity caps node#ver + * @param online indicates if the user is currently online + * @see UserCapsNodeListener#userCapsNodeAdded(String, String, boolean) + */ + public void userCapsNodeRemoved(String user, ArrayList fullJids, + String node, boolean online) + { + /* + * It doesn't matter to us whether a caps node has been added or removed + * for the specified user because we report all changes. + */ + userCapsNodeChanged(user, fullJids, node, online); + } + + /** + * Notifies this listener that an EntityCapsManager has changed a + * record for a specific user about the caps node the user has. + * + * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the given user is online - * @see UserCapsNodeListener#userCapsNodeRemoved(String, String, boolean) */ - public void userCapsNodeRemoved(String user, String node, boolean online) + public void userCapsNodeChanged(String user, ArrayList fullJids, String node, boolean online) { OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); if (opsetPresence != null) { - String jid = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(jid); + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); // If the contact isn't null and is online we try to discover the // new set of operation sets and to notify interested parties. @@ -432,8 +489,7 @@ public class OperationSetContactCapabilitiesJabberImpl fireContactCapabilitiesEvent( contact, ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(user, - online)); + getLargestSupportedOperationSet(fullJids)); } else { @@ -443,7 +499,7 @@ public class OperationSetContactCapabilitiesJabberImpl fireContactCapabilitiesEvent( contact, ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(contact)); + getLargestSupportedOperationSet(fullJids)); } } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java index ebdcbb0..56b066f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java @@ -243,6 +243,7 @@ public class EntityCapsManager if ((user != null) && (node != null) && (hash != null) && (ver != null)) { Caps caps = userCaps.get(user); + String bareJid=StringUtils.parseBareAddress(user); if ((caps == null) || !caps.node.equals(node) @@ -270,7 +271,9 @@ public class EntityCapsManager String nodeVer = caps.getNodeVer(); for (UserCapsNodeListener listener : listeners) - listener.userCapsNodeAdded(user, nodeVer, online); + listener.userCapsNodeAdded(user, + getFullJidsByBareJid(bareJid), + nodeVer, online); } } } @@ -305,6 +308,8 @@ public class EntityCapsManager { Caps caps = null; String lastRemovedJid = null; + String bareJid=StringUtils.parseBareAddress( + contact.getAddress()); Iterator iter = userCaps.keySet().iterator(); while(iter.hasNext()) @@ -337,7 +342,9 @@ public class EntityCapsManager for (UserCapsNodeListener listener : listeners) listener.userCapsNodeRemoved( - lastRemovedJid, nodeVer, false); + lastRemovedJid, + getFullJidsByBareJid(bareJid), + nodeVer, false); } } } @@ -350,6 +357,7 @@ public class EntityCapsManager public void removeUserCapsNode(String user) { Caps caps = userCaps.remove(user); + String bareJid=StringUtils.parseBareAddress(user); // Fire userCapsNodeRemoved. if (caps != null) @@ -367,7 +375,9 @@ public class EntityCapsManager String nodeVer = caps.getNodeVer(); for (UserCapsNodeListener listener : listeners) - listener.userCapsNodeRemoved(user, nodeVer, false); + listener.userCapsNodeRemoved(user, + getFullJidsByBareJid(bareJid), + nodeVer, false); } } } @@ -404,6 +414,24 @@ public class EntityCapsManager { return userCaps.get(user); } + + /** + * Gets the full Jids (with resources) as Strings. + * + * @param the bare Jid + * @return the full Jids as an ArrayList user + */ + public ArrayList getFullJidsByBareJid(String bareJid) + { + ArrayList jids = new ArrayList(); + for(String jid: userCaps.keySet()) + { + if(bareJid.equals(StringUtils.parseBareAddress(jid))){ + jids.add(jid); + } + } + return jids; + } /** * Get the discover info given a user name. The discover info is returned if diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java index 5ee38b0..eda921f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.impl.protocol.jabber.extensions.caps; +import java.util.ArrayList; + /** * Represents a listener of events notifying about changes in the list of user * caps nodes of EntityCapsManager. @@ -30,18 +32,22 @@ public interface UserCapsNodeListener * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user for which we're notified is online */ - public void userCapsNodeAdded(String user, String node, boolean online); + public void userCapsNodeAdded(String user, ArrayList fullJids, + String node, boolean online); /** * Notifies this listener that an EntityCapsManager has removed a * record for a specific user about the caps node the user has. * * @param user the user (full JID) + * @param fullJids a list of all resources of the user (full JIDs) * @param node the entity caps node#ver * @param online indicates if the user for which we're notified is online */ - public void userCapsNodeRemoved(String user, String node, boolean online); + public void userCapsNodeRemoved(String user, ArrayList fullJids, + String node, boolean online); } -- cgit v1.1 From 45d8ee64c40fcb4d695c846e3fc4ab61fc9fbdad Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Sat, 31 Oct 2015 04:06:24 +0100 Subject: Option for new behaviour of detecting a contact's capabilities This reintroduces some old code in order to give the user the option to switch between those two behaviours. It also prevents the removal of all caps nodes (and thusly breaking the new detection) when a rogue offline presence event comes in. This is such an event in which a contact is falsely assumed as offline, if the preferred resource of two or more same prioritised resources goes offline. We are checking this by looking whether it is a "resourceChanged"-event. This should probably be changed again, after those offline presence updates have been fixed. --- resources/languages/resources.properties | 2 + .../OperationSetContactCapabilitiesJabberImpl.java | 160 ++++++++++++++------- .../protocol/jabber/ScServiceDiscoveryManager.java | 7 +- .../GeneralConfigPluginActivator.java | 24 ++++ .../plugin/generalconfig/XMPPConfigForm.java | 101 +++++++++++++ 5 files changed, 245 insertions(+), 49 deletions(-) create mode 100644 src/net/java/sip/communicator/plugin/generalconfig/XMPPConfigForm.java diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index cafbe93..63dbd17 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1069,6 +1069,8 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Remove special symbols before plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Convert letters in phone numbers plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=e.g. +1-800-MYPHONE -> +1-800-694663 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=Use all resources when detecting a contact's features plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Sampling rate: plugin.generalconfig.OPUS_BITRATE=Encoder average bitrate (kbps): diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index a1767dd..e74ace1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -26,7 +26,7 @@ import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.*; /** * Represents an OperationSet to query the OperationSets @@ -52,6 +52,19 @@ public class OperationSetContactCapabilitiesJabberImpl = Logger.getLogger(OperationSetContactCapabilitiesJabberImpl.class); /** + * The name of the property used to control whether to use + * all resources to show capabilities + */ + public static final String PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES = + "net.java.sip.communicator.XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES"; + + /** + * The default value for the capabilities setting + */ + public static final boolean USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT = + true; + + /** * The list of OperationSet capabilities presumed to be supported * by a Contact when it is offline. */ @@ -295,13 +308,14 @@ public class OperationSetContactCapabilitiesJabberImpl { Map supportedOperationSets = new HashMap(); - if (fullJids!=null){ + if (fullJids!=null) + { for (String fullJid : fullJids) { Map newSupportedOperationSets= getSupportedOperationSets(fullJid, true); if (newSupportedOperationSets.size()> - supportedOperationSets.size()) + supportedOperationSets.size()) { supportedOperationSets = newSupportedOperationSets; } @@ -466,40 +480,61 @@ public class OperationSetContactCapabilitiesJabberImpl * @param node the entity caps node#ver * @param online indicates if the given user is online */ - public void userCapsNodeChanged(String user, ArrayList fullJids, String node, boolean online) + public void userCapsNodeChanged(String user, ArrayList fullJids, + String node, boolean online) { OperationSetPresence opsetPresence - = parentProvider.getOperationSet(OperationSetPresence.class); - - if (opsetPresence != null) - { - String bareJid = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(bareJid); - - // If the contact isn't null and is online we try to discover the - // new set of operation sets and to notify interested parties. - // Otherwise we ignore the event. - if (contact != null) + = parentProvider.getOperationSet(OperationSetPresence.class); + if (opsetPresence != null) { + if(JabberActivator.getConfigurationService() + .getBoolean( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT)) { - if(online) + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); + if (contact != null) { - // when going online we have received a presence - // and make sure we discover this particular jid - // for getSupportedOperationSets fireContactCapabilitiesEvent( contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, getLargestSupportedOperationSet(fullJids)); } - else + } + else + { + String jid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(jid); + + // If the contact isn't null and is online we try to discover + // the new set of operation sets and to notify interested + // parties. Otherwise we ignore the event. + if (contact != null) { - // when offline, we use the contact, and selecting - // the most connected jid - // for getSupportedOperationSets - fireContactCapabilitiesEvent( - contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getLargestSupportedOperationSet(fullJids)); + if(online) + { + // when going online we have received a presence + // and make sure we discover this particular jid + // for getSupportedOperationSets + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(user, + online)); + } + else + { + // when offline, we use the contact, and selecting + // the most connected jid + // for getSupportedOperationSets + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(contact)); + } } } } @@ -516,7 +551,8 @@ public class OperationSetContactCapabilitiesJabberImpl { // If the user goes offline we ensure to remove the caps node. if (capsManager != null - && evt.getNewStatus().getStatus() < PresenceStatus.ONLINE_THRESHOLD) + && evt.getNewStatus().getStatus() < PresenceStatus.ONLINE_THRESHOLD + && !evt.isResourceChanged()) { capsManager.removeContactCapsNode(evt.getSourceContact()); } @@ -525,31 +561,59 @@ public class OperationSetContactCapabilitiesJabberImpl /** * Fires event that contact capabilities has changed. * @param user the user to search for its contact. + * @param fullJids a list of all resources of the user (full JIDs) */ - public void fireContactCapabilitiesChanged(String user) + public void fireContactCapabilitiesChanged(String user, + ArrayList fullJids) { - OperationSetPresence opsetPresence + if(!JabberActivator.getConfigurationService() + .getBoolean( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) + ||fullJids.isEmpty()) + { + OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); - if (opsetPresence != null) + if (opsetPresence != null) + { + String userID = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(userID); + + // this called by received discovery info for particular jid + // so we use its online and opsets for this particular jid + boolean online = false; + Presence presence = parentProvider.getConnection().getRoster() + .getPresence(user); + if(presence != null) + online = presence.isAvailable(); + + if(contact != null) + { + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getSupportedOperationSets(user, online)); + } + } + } + else { - String userID = StringUtils.parseBareAddress(user); - Contact contact = opsetPresence.findContactByID(userID); - - // this called by received discovery info for particular jid - // so we use its online and opsets for this particular jid - boolean online = false; - Presence presence = parentProvider.getConnection().getRoster() - .getPresence(user); - if(presence != null) - online = presence.isAvailable(); - - if(contact != null) + OperationSetPresence opsetPresence + = parentProvider.getOperationSet(OperationSetPresence.class); + if (opsetPresence != null) { - fireContactCapabilitiesEvent( - contact, - ContactCapabilitiesEvent.SUPPORTED_OPERATION_SETS_CHANGED, - getSupportedOperationSets(user, online)); + String bareJid = StringUtils.parseBareAddress(user); + Contact contact = opsetPresence.findContactByID(bareJid); + if(contact != null) + { + fireContactCapabilitiesEvent( + contact, + ContactCapabilitiesEvent. + SUPPORTED_OPERATION_SETS_CHANGED, + getLargestSupportedOperationSet(fullJids)); + } } } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java index 9fdbea5..4b3edab 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java @@ -27,6 +27,7 @@ import net.java.sip.communicator.util.*; import org.jivesoftware.smack.*; import org.jivesoftware.smack.filter.*; import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.util.*; import org.jivesoftware.smackx.*; import org.jivesoftware.smackx.packet.*; @@ -791,7 +792,11 @@ public class ScServiceDiscoveryManager // fire event if(fireEvent && capabilitiesOpSet != null) { - capabilitiesOpSet.fireContactCapabilitiesChanged(entityID); + capabilitiesOpSet.fireContactCapabilitiesChanged( + entityID, + capsManager.getFullJidsByBareJid( + StringUtils.parseBareAddress(entityID)) + ); } } catch(XMPPException ex) diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java index 2f345d7..7222d97 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java @@ -108,6 +108,14 @@ public class GeneralConfigPluginActivator "net.java.sip.communicator.plugin.generalconfig.sipconfig.DISABLED"; /** + * Indicates if the XMPP configuration form should be disabled, i.e. + * not visible to the user. + */ + private static final String XMPP_CONFIG_DISABLED_PROP + = + "net.java.sip.communicator.plugin.generalconfig.xmppconfig.DISABLED"; + + /** * Starts this bundle. */ @Override @@ -155,6 +163,22 @@ public class GeneralConfigPluginActivator 52, true), properties); } + if (!getConfigurationService() + .getBoolean(XMPP_CONFIG_DISABLED_PROP, false)) + { + // Registers the XMPP config panel as advanced configuration form. + properties.put( ConfigurationForm.FORM_TYPE, + ConfigurationForm.ADVANCED_TYPE); + bundleContext.registerService( + ConfigurationForm.class.getName(), + new LazyConfigurationForm( + XMPPConfigForm.class.getName(), + getClass().getClassLoader(), + null, + "plugin.generalconfig.XMPP_CONFIG", + 52, true), + properties); + } properties.put( ConfigurationForm.FORM_TYPE, ConfigurationForm.ADVANCED_TYPE); bundleContext.registerService( diff --git a/src/net/java/sip/communicator/plugin/generalconfig/XMPPConfigForm.java b/src/net/java/sip/communicator/plugin/generalconfig/XMPPConfigForm.java new file mode 100644 index 0000000..0113232 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/generalconfig/XMPPConfigForm.java @@ -0,0 +1,101 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.plugin.generalconfig; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import org.jitsi.service.configuration.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +/** + * Implementation of the configuration form. + * + * @author Timur Masar + */ +public class XMPPConfigForm +extends TransparentPanel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The name of the property used to control whether to use + * all resources to show capabilities + */ + public static final String PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES = + "net.java.sip.communicator.XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES"; + + /** + * The default value for the capabilities setting + */ + public static final boolean USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT = + true; + + /** + * The ConfigurationService to be used to access configuration + */ + private final ConfigurationService configurationService + = GeneralConfigPluginActivator.getConfigurationService(); + + /** + * Creates the form. + */ + public XMPPConfigForm() + { + super(new BorderLayout()); + Box box = Box.createVerticalBox(); + add(box, BorderLayout.NORTH); + + TransparentPanel contentPanel = new TransparentPanel(); + contentPanel.setLayout(new BorderLayout(10, 10)); + + box.add(contentPanel); + + TransparentPanel labelPanel + = new TransparentPanel(new GridLayout(0, 1, 2, 2)); + TransparentPanel valuePanel + = new TransparentPanel(new GridLayout(0, 1, 2, 2)); + + contentPanel.add(labelPanel, BorderLayout.CENTER); + contentPanel.add(valuePanel, BorderLayout.WEST); + + final JCheckBox useAllResourcesForCapabilitiesCheckbox = + new SIPCommCheckBox(Resources.getString( + "plugin.generalconfig.XMPP_USE_ALL_RESOURCES")); + + useAllResourcesForCapabilitiesCheckbox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + configurationService.setProperty( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + useAllResourcesForCapabilitiesCheckbox.isSelected()); + } + }); + useAllResourcesForCapabilitiesCheckbox.setSelected( + configurationService.getBoolean( + PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT)); + valuePanel.add(useAllResourcesForCapabilitiesCheckbox); + } +} -- cgit v1.1 From 79efc958b095fcf62cad8ac0306db220ec99ac8b Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Tue, 10 Nov 2015 02:55:41 +0100 Subject: Fixes offline messaging to contact which just went offline We should still use the old implementation for checking offline contacts capabilities. This will give us the 'offline capabilities' e.g. messaging offline contacts. --- .../protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java index e74ace1..59cc17c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetContactCapabilitiesJabberImpl.java @@ -489,7 +489,8 @@ public class OperationSetContactCapabilitiesJabberImpl if(JabberActivator.getConfigurationService() .getBoolean( PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, - USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT)) + USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) + && !fullJids.isEmpty()) { String bareJid = StringUtils.parseBareAddress(user); Contact contact = opsetPresence.findContactByID(bareJid); @@ -570,7 +571,7 @@ public class OperationSetContactCapabilitiesJabberImpl .getBoolean( PROP_XMPP_USE_ALL_RESOURCES_FOR_CAPABILITIES, USE_ALL_RESOURCES_FOR_CAPABILITIES_DEFAULT) - ||fullJids.isEmpty()) + || fullJids.isEmpty()) { OperationSetPresence opsetPresence = parentProvider.getOperationSet(OperationSetPresence.class); -- cgit v1.1 From 89528e58b6fb14ed59584c049f1ba81b5e319c3b Mon Sep 17 00:00:00 2001 From: mksh Date: Tue, 10 Nov 2015 17:51:35 +0200 Subject: Introduce SmackProxy for abstracting different Smack implementations (3 and 4) --- .../jabber/ProtocolProviderFactoryJabberImpl.java | 8 + .../jabber/SmackV3InteroperabilityLayer.java | 91 ++++++++++ .../jabber/extensions/AbstractPacketExtension.java | 1 + .../extensions/DefaultPacketExtensionProvider.java | 11 +- .../extensions/colibri/ColibriIQProvider.java | 84 +++++---- .../jabber/extensions/jingle/JingleIQ.java | 25 +-- .../jabber/extensions/jingle/JingleIQProvider.java | 196 +++++++++++---------- .../jabber/AbstractSmackInteroperabilityLayer.java | 139 +++++++++++++++ 8 files changed, 413 insertions(+), 142 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/SmackV3InteroperabilityLayer.java create mode 100644 src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java index 4f9fc5f..a2b5fd0 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java @@ -21,6 +21,7 @@ import java.util.*; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.jabber.*; import org.jivesoftware.smack.provider.*; import org.jivesoftware.smack.util.*; import org.osgi.framework.*; @@ -46,7 +47,14 @@ public class ProtocolProviderFactoryJabberImpl { try { + + // Set the extension provider manager for classes that use + // it directly ProviderManager.setInstance(new ProviderManagerExt()); + // Set the Smack interop implementation for the classes that need + // to support Smackv4 interoperation + AbstractSmackInteroperabilityLayer.setImplementationClass( + SmackV3InteroperabilityLayer.class); } catch(Throwable t) { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/SmackV3InteroperabilityLayer.java b/src/net/java/sip/communicator/impl/protocol/jabber/SmackV3InteroperabilityLayer.java new file mode 100644 index 0000000..d5af26f --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/SmackV3InteroperabilityLayer.java @@ -0,0 +1,91 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber; + +import net.java.sip.communicator.service.protocol.jabber.*; +import org.jivesoftware.smack.provider.*; + +/** + * Smack v3 interoperation layer + * + * @author Maksym Kulish + */ +public class SmackV3InteroperabilityLayer + extends AbstractSmackInteroperabilityLayer +{ + + /** + * A SmackV3 ProviderManager instance + */ + private ProviderManager providerManager = ProviderManager.getInstance(); + + /** + * A default constructor + */ + public SmackV3InteroperabilityLayer() {} + + /** + * Add PacketExtensionProvider to the list of known + * providers + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @param provider PacketExtensionProvider implementation to be + * used + */ + @Override + public void addExtensionProvider( + String elementName, String namespace, Object provider) + { + providerManager.addExtensionProvider(elementName, namespace, provider); + } + + /** + * Add IQProvider to the list of known + * providers + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @param provider IQProvider implementation to be + * used + */ + @Override + public void addIQProvider( + String elementName, String namespace, Object provider) + { + providerManager.addIQProvider(elementName, namespace, provider); + } + + /** + * Get the PacketExtensionProvider for given element name and XML + * namespace + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @return PacketExtensionProvider implementation to be + * used + */ + @Override + public PacketExtensionProvider getExtensionProvider( + String elementName, String namespace) + { + return (PacketExtensionProvider)providerManager + .getExtensionProvider(elementName, namespace); + } + +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java index e2da8bb..07e5211 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java @@ -32,6 +32,7 @@ import org.jivesoftware.smack.packet.*; * * @author Emil Ivov * @author Lyubomir Marinov + * */ public abstract class AbstractPacketExtension implements PacketExtension diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java index 1285581..778d086 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions; import java.util.logging.*; +import net.java.sip.communicator.service.protocol.jabber.*; import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.provider.*; import org.xmlpull.v1.*; @@ -41,6 +42,13 @@ public class DefaultPacketExtensionProvider .getLogger(DefaultPacketExtensionProvider.class.getName()); /** + * The AbstractSmackInteroperabilityLayer instance implementing + * necessary methods + */ + private AbstractSmackInteroperabilityLayer smackInteroperabilityLayer = + AbstractSmackInteroperabilityLayer.getInstance(); + + /** * The {@link Class} that the packets we will be parsing here belong to. */ private final Class packetClass; @@ -100,8 +108,7 @@ public class DefaultPacketExtensionProvider if (eventType == XmlPullParser.START_TAG) { - PacketExtensionProvider provider - = (PacketExtensionProvider)ProviderManager.getInstance() + PacketExtensionProvider provider = smackInteroperabilityLayer .getExtensionProvider( elementName, namespace ); if(provider == null) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 39e299f..0b1b14a 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -20,6 +20,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; +import net.java.sip.communicator.service.protocol.jabber.*; import org.jitsi.service.neomedia.*; import org.jitsi.util.*; import org.jivesoftware.smack.packet.*; @@ -36,89 +37,97 @@ import org.xmlpull.v1.*; public class ColibriIQProvider implements IQProvider { + + /** + * Smack interoperation layer + */ + AbstractSmackInteroperabilityLayer smackInteroperabilityLayer = + AbstractSmackInteroperabilityLayer.getInstance(); + /** Initializes a new ColibriIQProvider instance. */ public ColibriIQProvider() { - ProviderManager providerManager = ProviderManager.getInstance(); - - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( PayloadTypePacketExtension.ELEMENT_NAME, ColibriConferenceIQ.NAMESPACE, new DefaultPacketExtensionProvider( PayloadTypePacketExtension.class)); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( RtcpFbPacketExtension.ELEMENT_NAME, RtcpFbPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( RtcpFbPacketExtension.class)); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( RTPHdrExtPacketExtension.ELEMENT_NAME, ColibriConferenceIQ.NAMESPACE, new DefaultPacketExtensionProvider( RTPHdrExtPacketExtension.class)); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( SourcePacketExtension.ELEMENT_NAME, SourcePacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( SourcePacketExtension.class)); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( SourceGroupPacketExtension.ELEMENT_NAME, SourceGroupPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( SourceGroupPacketExtension.class)); PacketExtensionProvider parameterProvider - = new DefaultPacketExtensionProvider( - ParameterPacketExtension.class); + = new DefaultPacketExtensionProvider( + ParameterPacketExtension.class); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( ParameterPacketExtension.ELEMENT_NAME, ColibriConferenceIQ.NAMESPACE, parameterProvider); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( ParameterPacketExtension.ELEMENT_NAME, SourcePacketExtension.NAMESPACE, parameterProvider); // Shutdown IQ - providerManager.addIQProvider( + smackInteroperabilityLayer.addIQProvider( GracefulShutdownIQ.ELEMENT_NAME, GracefulShutdownIQ.NAMESPACE, this); // Shutdown extension PacketExtensionProvider shutdownProvider - = new DefaultPacketExtensionProvider - ( - ColibriConferenceIQ.GracefulShutdown.class); + = new DefaultPacketExtensionProvider + ( + ColibriConferenceIQ.GracefulShutdown.class); - providerManager.addExtensionProvider( - ColibriConferenceIQ.GracefulShutdown.ELEMENT_NAME, - ColibriConferenceIQ.GracefulShutdown.NAMESPACE, - shutdownProvider); + smackInteroperabilityLayer.addExtensionProvider( + ColibriConferenceIQ.GracefulShutdown.ELEMENT_NAME, + ColibriConferenceIQ.GracefulShutdown.NAMESPACE, + shutdownProvider); // ColibriStatsIQ - providerManager.addIQProvider( - ColibriStatsIQ.ELEMENT_NAME, - ColibriStatsIQ.NAMESPACE, - this); + smackInteroperabilityLayer.addIQProvider( + ColibriStatsIQ.ELEMENT_NAME, + ColibriStatsIQ.NAMESPACE, + this); // ColibriStatsExtension PacketExtensionProvider statsProvider - = new DefaultPacketExtensionProvider( - ColibriStatsExtension.class); + = new DefaultPacketExtensionProvider( + ColibriStatsExtension.class); - providerManager.addExtensionProvider( - ColibriStatsExtension.ELEMENT_NAME, - ColibriStatsExtension.NAMESPACE, - statsProvider); + smackInteroperabilityLayer.addExtensionProvider( + ColibriStatsExtension.ELEMENT_NAME, + ColibriStatsExtension.NAMESPACE, + statsProvider); // ColibriStatsExtension.Stat PacketExtensionProvider statProvider - = new DefaultPacketExtensionProvider( - ColibriStatsExtension.Stat.class); - - providerManager.addExtensionProvider( - ColibriStatsExtension.Stat.ELEMENT_NAME, - ColibriStatsExtension.NAMESPACE, - statProvider); + = new DefaultPacketExtensionProvider + ( + ColibriStatsExtension.Stat.class); + + smackInteroperabilityLayer.addExtensionProvider( + ColibriStatsExtension.Stat.ELEMENT_NAME, + ColibriStatsExtension.NAMESPACE, + statProvider); + + } private void addChildExtension( @@ -199,8 +208,7 @@ public class ColibriIQProvider throws Exception { PacketExtensionProvider extensionProvider - = (PacketExtensionProvider) - ProviderManager.getInstance().getExtensionProvider( + = smackInteroperabilityLayer.getExtensionProvider( name, namespace); PacketExtension extension; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java index 9183fa0..65b0849 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java @@ -21,6 +21,7 @@ import java.math.*; import java.security.*; import java.util.*; +import net.java.sip.communicator.service.protocol.jabber.*; import org.jivesoftware.smack.packet.*; /** @@ -62,7 +63,8 @@ public class JingleIQ extends IQ * The name of the argument that contains the session id. */ public static final String SID_ATTR_NAME = "sid"; - + + /** * The JingleAction that describes the purpose of this * jingle element. @@ -104,8 +106,8 @@ public class JingleIQ extends IQ * The list of "content" elements included in this IQ. */ private final List contentList - = new ArrayList(); - + = new ArrayList(); + /** * Returns the XML string of this Jingle IQ's "section" sub-element. * @@ -124,17 +126,18 @@ public class JingleIQ extends IQ if( initiator != null) bldr.append(" " + INITIATOR_ATTR_NAME - + "='" + getInitiator() + "'"); + + "='" + getInitiator() + "'"); if( responder != null) bldr.append(" " + RESPONDER_ATTR_NAME - + "='" + getResponder() + "'"); + + "='" + getResponder() + "'"); bldr.append(" " + SID_ATTR_NAME - + "='" + getSID() + "'"); - - String extensionsXML = getExtensionsXML(); + + "='" + getSID() + "'"); + CharSequence extensionsXMLSeq = getExtensionsXML(); + String extensionsXML = extensionsXMLSeq.toString(); + if ((contentList.size() == 0) && (reason == null) && (sessionInfo == null) @@ -348,7 +351,7 @@ public class JingleIQ extends IQ * otherwise. */ public boolean containsContentChildOfType( - Class contentType) + Class contentType) { if(getContentForType(contentType) != null) return true; @@ -369,14 +372,14 @@ public class JingleIQ extends IQ * found. */ public ContentPacketExtension getContentForType( - Class contentType) + Class contentType) { synchronized(contentList) { for(ContentPacketExtension content : contentList) { PacketExtension child - = content.getFirstChildOfType(contentType); + = content.getFirstChildOfType(contentType); if(child != null) return content; } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java index 11f909a..49934e5 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java @@ -20,6 +20,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet.*; +import net.java.sip.communicator.service.protocol.jabber.*; import org.jivesoftware.smack.provider.*; import org.xmlpull.v1.*; @@ -37,174 +38,187 @@ public class JingleIQProvider implements IQProvider */ public JingleIQProvider() { - ProviderManager providerManager = ProviderManager.getInstance(); + + AbstractSmackInteroperabilityLayer smackInteroperabilityLayer = + AbstractSmackInteroperabilityLayer.getInstance(); // provider - providerManager.addExtensionProvider( - RtpDescriptionPacketExtension.ELEMENT_NAME, - RtpDescriptionPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - ( - RtpDescriptionPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + RtpDescriptionPacketExtension.ELEMENT_NAME, + RtpDescriptionPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + RtpDescriptionPacketExtension.class)); // provider - providerManager.addExtensionProvider( - PayloadTypePacketExtension.ELEMENT_NAME, - RtpDescriptionPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - ( - PayloadTypePacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + PayloadTypePacketExtension.ELEMENT_NAME, + RtpDescriptionPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + PayloadTypePacketExtension.class)); // provider - providerManager.addExtensionProvider( - ParameterPacketExtension.ELEMENT_NAME, - RtpDescriptionPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (ParameterPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + ParameterPacketExtension.ELEMENT_NAME, + RtpDescriptionPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (ParameterPacketExtension.class)); // provider - providerManager.addExtensionProvider( - RTPHdrExtPacketExtension.ELEMENT_NAME, - RTPHdrExtPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (RTPHdrExtPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + RTPHdrExtPacketExtension.ELEMENT_NAME, + RTPHdrExtPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (RTPHdrExtPacketExtension.class)); // provider - providerManager.addExtensionProvider( - SctpMapExtension.ELEMENT_NAME, - SctpMapExtension.NAMESPACE, - new SctpMapExtensionProvider()); + smackInteroperabilityLayer.addExtensionProvider( + SctpMapExtension.ELEMENT_NAME, + SctpMapExtension.NAMESPACE, + new SctpMapExtensionProvider()); // provider - providerManager.addExtensionProvider( - EncryptionPacketExtension.ELEMENT_NAME, - RtpDescriptionPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (EncryptionPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + EncryptionPacketExtension.ELEMENT_NAME, + RtpDescriptionPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (EncryptionPacketExtension.class)); // provider - providerManager.addExtensionProvider( - ZrtpHashPacketExtension.ELEMENT_NAME, - ZrtpHashPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (ZrtpHashPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + ZrtpHashPacketExtension.ELEMENT_NAME, + ZrtpHashPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (ZrtpHashPacketExtension.class)); // provider - providerManager.addExtensionProvider( - CryptoPacketExtension.ELEMENT_NAME, - RtpDescriptionPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (CryptoPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + CryptoPacketExtension.ELEMENT_NAME, + RtpDescriptionPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (CryptoPacketExtension.class)); // provider - providerManager.addExtensionProvider( - BundlePacketExtension.ELEMENT_NAME, - BundlePacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (BundlePacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + BundlePacketExtension.ELEMENT_NAME, + BundlePacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + + (BundlePacketExtension.class)); // provider - providerManager.addExtensionProvider( - GroupPacketExtension.ELEMENT_NAME, - GroupPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider - (GroupPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + GroupPacketExtension.ELEMENT_NAME, + GroupPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + (GroupPacketExtension.class)); //ice-udp transport - providerManager.addExtensionProvider( - IceUdpTransportPacketExtension.ELEMENT_NAME, - IceUdpTransportPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - IceUdpTransportPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + IceUdpTransportPacketExtension.ELEMENT_NAME, + IceUdpTransportPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + IceUdpTransportPacketExtension.class)); // provider - providerManager.addExtensionProvider( - RawUdpTransportPacketExtension.ELEMENT_NAME, - RawUdpTransportPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - RawUdpTransportPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + RawUdpTransportPacketExtension.ELEMENT_NAME, + RawUdpTransportPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + RawUdpTransportPacketExtension.class)); //ice-udp provider - providerManager.addExtensionProvider( - CandidatePacketExtension.ELEMENT_NAME, - IceUdpTransportPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - CandidatePacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + CandidatePacketExtension.ELEMENT_NAME, + IceUdpTransportPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + CandidatePacketExtension.class)); //raw-udp provider - providerManager.addExtensionProvider( - CandidatePacketExtension.ELEMENT_NAME, - RawUdpTransportPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - CandidatePacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + CandidatePacketExtension.ELEMENT_NAME, + RawUdpTransportPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + CandidatePacketExtension.class)); //ice-udp provider - providerManager.addExtensionProvider( - RemoteCandidatePacketExtension.ELEMENT_NAME, - IceUdpTransportPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - RemoteCandidatePacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + RemoteCandidatePacketExtension.ELEMENT_NAME, + IceUdpTransportPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider + ( + RemoteCandidatePacketExtension.class)); //inputevt provider - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( InputEvtPacketExtension.ELEMENT_NAME, InputEvtPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( InputEvtPacketExtension.class)); //coin provider - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( CoinPacketExtension.ELEMENT_NAME, CoinPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( CoinPacketExtension.class)); // DTLS-SRTP - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( DtlsFingerprintPacketExtension.ELEMENT_NAME, DtlsFingerprintPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider - ( + ( DtlsFingerprintPacketExtension.class)); /* * XEP-0251: Jingle Session Transfer and * providers */ - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( TransferPacketExtension.ELEMENT_NAME, TransferPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( TransferPacketExtension.class)); - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( TransferredPacketExtension.ELEMENT_NAME, TransferredPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( TransferredPacketExtension.class)); //conference description provider - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( ConferenceDescriptionPacketExtension.CALLID_ELEM_NAME, ConferenceDescriptionPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( CallIdPacketExtension.class)); //rtcp-fb - providerManager.addExtensionProvider( - RtcpFbPacketExtension.ELEMENT_NAME, - RtcpFbPacketExtension.NAMESPACE, - new DefaultPacketExtensionProvider( - RtcpFbPacketExtension.class)); + smackInteroperabilityLayer.addExtensionProvider( + RtcpFbPacketExtension.ELEMENT_NAME, + RtcpFbPacketExtension.NAMESPACE, + new DefaultPacketExtensionProvider( + RtcpFbPacketExtension.class)); //rtcp-mux - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( RtcpmuxPacketExtension.ELEMENT_NAME, IceUdpTransportPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( RtcpmuxPacketExtension.class)); //ssrcInfo - providerManager.addExtensionProvider( + smackInteroperabilityLayer.addExtensionProvider( SSRCInfoPacketExtension.ELEMENT_NAME, SSRCInfoPacketExtension.NAMESPACE, new DefaultPacketExtensionProvider( diff --git a/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java b/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java new file mode 100644 index 0000000..051ce70 --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java @@ -0,0 +1,139 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.service.protocol.jabber; + +import net.java.sip.communicator.util.*; +import org.jivesoftware.smack.provider.*; + + +/** + * + * This class abstracts interactions within Smack XMPP library (mostly with + * its ProviderManager class). + * This exists because JingleIQProvider and ColibriIQProvider + * are in need to be used with Smack v4, where ProviderManager + * has a different interface. + * + * @author Maksym Kulish + */ +abstract public class AbstractSmackInteroperabilityLayer { + + /** + * The Logger used by the + * AbstractSmackInteroperabilityLayer class for + * reporting on improper implementations instantiation + */ + private static final Logger logger = Logger.getLogger( + AbstractSmackInteroperabilityLayer.class); + + /** + * The implementation class to be used within its Jitsi application + */ + private static Class + implementationClass; + + /** + * The instance of + */ + private static AbstractSmackInteroperabilityLayer proxyInstance; + + /** + * Get the instance of Smack interoperation layer implementation class + * + * @return Smack interoperation layer implementation class + */ + public static AbstractSmackInteroperabilityLayer getInstance() + { + if (proxyInstance == null) + { + try + { + proxyInstance = implementationClass.newInstance(); + } + catch (IllegalAccessException e) + { + // Never thrown within proper implementation + logger.fatal("Your AbstractSmackInteroperabilityLayer " + + "implementation " + + "cannot be accessed properly. " + + "Please fix the implementation"); + } + catch (InstantiationException e) + { + // Never thrown within proper implementation + logger.fatal("Your AbstractSmackInteroperabilityLayer " + + "implementation " + + "cannot be instantiated properly. " + + "Please fix the implementation"); + } + } + return proxyInstance; + } + + /** + * Set the Smack interoperation layer + * implementation class to be used within this Jitsi application + * @param implementationClass Smack interoperation layer + * implementation class + */ + public static void setImplementationClass( + Class implementationClass) + { + AbstractSmackInteroperabilityLayer.implementationClass + = implementationClass; + } + + + /** + * Add PacketExtensionProvider to the list of known + * providers + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @param provider PacketExtensionProvider implementation to be + * used + */ + abstract public void addExtensionProvider( + String elementName, String namespace, Object provider); + + /** + * Add IQProvider to the list of known + * providers + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @param provider IQProvider implementation to be + * used + */ + abstract public void addIQProvider( + String elementName, String namespace, Object provider); + + /** + * Get the PacketExtensionProvider for given element name and XML + * namespace + * + * @param elementName The element name where the matching is happening + * @param namespace The XML namespace used in that element + * @return PacketExtensionProvider implementation to be + * used + */ + abstract public PacketExtensionProvider getExtensionProvider( + String elementName, String namespace); + + +} -- cgit v1.1 From f71e227f0ff38cd3a528b8b1b85b148a1c3aa18f Mon Sep 17 00:00:00 2001 From: mksh Date: Wed, 11 Nov 2015 13:45:01 +0200 Subject: Typo fixes --- .../jabber/extensions/AbstractPacketExtension.java | 1 - .../jabber/extensions/colibri/ColibriIQProvider.java | 2 +- .../jabber/AbstractSmackInteroperabilityLayer.java | 14 ++++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java index 07e5211..e2da8bb 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java @@ -32,7 +32,6 @@ import org.jivesoftware.smack.packet.*; * * @author Emil Ivov * @author Lyubomir Marinov - * */ public abstract class AbstractPacketExtension implements PacketExtension diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 0b1b14a..016d9b7 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -41,7 +41,7 @@ public class ColibriIQProvider /** * Smack interoperation layer */ - AbstractSmackInteroperabilityLayer smackInteroperabilityLayer = + private AbstractSmackInteroperabilityLayer smackInteroperabilityLayer = AbstractSmackInteroperabilityLayer.getInstance(); /** Initializes a new ColibriIQProvider instance. */ diff --git a/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java b/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java index 051ce70..277da84 100644 --- a/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java +++ b/src/net/java/sip/communicator/service/protocol/jabber/AbstractSmackInteroperabilityLayer.java @@ -48,22 +48,24 @@ abstract public class AbstractSmackInteroperabilityLayer { implementationClass; /** - * The instance of + * The instance of Smack interoperability layer implementation class */ - private static AbstractSmackInteroperabilityLayer proxyInstance; + private static AbstractSmackInteroperabilityLayer + interopLayerInstance; /** - * Get the instance of Smack interoperation layer implementation class + * Get the instance of Smack interoperability layer implementation class * * @return Smack interoperation layer implementation class */ public static AbstractSmackInteroperabilityLayer getInstance() { - if (proxyInstance == null) + if (interopLayerInstance == null) { try { - proxyInstance = implementationClass.newInstance(); + interopLayerInstance = + implementationClass.newInstance(); } catch (IllegalAccessException e) { @@ -82,7 +84,7 @@ abstract public class AbstractSmackInteroperabilityLayer { "Please fix the implementation"); } } - return proxyInstance; + return interopLayerInstance; } /** -- cgit v1.1 From 5729665b1b8e13eaf419d58d80ccba2f226eaa86 Mon Sep 17 00:00:00 2001 From: Timur Masar Date: Tue, 10 Nov 2015 20:43:31 +0100 Subject: Fixing TreeSet's Comparator This fixes the Presence TreeSet's Comparator. If the comparator can't determine a greater or less than relationship, it will sort by the name of the resources lexicographically. A (mathematical) set is a collection of distinct objects. A TreeSet's compare function determines relation of two objects. It also determines equality and since this is a Set it would effectively replace the old one in the set, if the function returns 0. This method wasn't fully equals consistent, meaning different objects were deemed equal by the comparator. That lead to an inconsistency in the representation of presence objects and resources that contact has connected. The resources not represented in this TreeSet would no longer be able to let the contact appear as Online. --- .../jabber/OperationSetPersistentPresenceJabberImpl.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java index 69c168c..2d40ac1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java @@ -1528,6 +1528,19 @@ public class OperationSetPersistentPresenceJabberImpl o2, parentProvider).getStatus() - jabberStatusToPresenceStatus( o1, parentProvider).getStatus(); + // We have run out of "logical" ways to order + // the presences inside the TreeSet. We have + // make sure we are consinstent with equals. + // We do this by comparing the unique resource + // names. If this evaluates to 0 again, then we + // can safely assume this presence object + // represents the same resource and by that the + // same client. + if(res == 0) + { + res = o1.getFrom().compareTo( + o2.getFrom()); + } } return res; -- cgit v1.1 From eeba6ccbf9216e31a15de1b670c8e9f966c3bf1d Mon Sep 17 00:00:00 2001 From: mksh Date: Fri, 20 Nov 2015 19:04:17 +0200 Subject: Implemented program name property loading from logging.properties file and prepending it to each log message in case of existence --- .../java/sip/communicator/util/ScLogFormatter.java | 56 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/util/ScLogFormatter.java b/src/net/java/sip/communicator/util/ScLogFormatter.java index ad2129b..7ecb389 100644 --- a/src/net/java/sip/communicator/util/ScLogFormatter.java +++ b/src/net/java/sip/communicator/util/ScLogFormatter.java @@ -33,11 +33,43 @@ import java.util.logging.*; public class ScLogFormatter extends java.util.logging.Formatter { + + /** + * Program name logging property name + */ + private static final String PROGRAM_NAME_PROPERTY = ".programname"; + + + /** + * Line separator used by current platform + */ private static String lineSeparator = System.getProperty("line.separator"); + + /** + * Two digit DecimalFormat instance, used to format datetime + */ private static DecimalFormat twoDigFmt = new DecimalFormat("00"); + + /** + * Three digit DecimalFormat instance, used to format datetime + */ private static DecimalFormat threeDigFmt = new DecimalFormat("000"); /** + * The application name used to generate this log + */ + private static String programName; + + /** + * The default constructor for ScLogFormatter which loads + * program name property from logging.properties file, if it exists + */ + public ScLogFormatter() + { + loadProgramNameProperty(); + } + + /** * Format the given LogRecord. * @param record the log record to be formatted. * @return a formatted log record @@ -46,6 +78,15 @@ public class ScLogFormatter public synchronized String format(LogRecord record) { StringBuffer sb = new StringBuffer(); + + + if (programName != null) + { + // Program name + sb.append(programName); + + sb.append(' '); + } //current time Calendar cal = Calendar.getInstance(); @@ -146,7 +187,8 @@ public class ScLogFormatter } ix++; } - // Now search for the first frame before the SIP Communicator Logger class. + // Now search for the first frame + // before the SIP Communicator Logger class. while (ix < stack.length) { StackTraceElement frame = stack[ix]; @@ -164,4 +206,16 @@ public class ScLogFormatter return lineNumber; } + + /** + * Load the programname property to be used in logs to identify Jitsi-based + * application which produced the logs + */ + private void loadProgramNameProperty() + { + LogManager manager = LogManager.getLogManager(); + String cname = this.getClass().getName(); + programName = manager.getProperty(cname + PROGRAM_NAME_PROPERTY); + } + } -- cgit v1.1 From 7c42889e86694f0be88829b45fbcca876797f6c6 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Tue, 1 Dec 2015 10:56:37 -0600 Subject: Adds video muted extension used in jitsi-meet. --- .../extensions/jitsimeet/VideoMutedExtension.java | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java new file mode 100644 index 0000000..cf76d89 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java @@ -0,0 +1,70 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.*; + +/** + * Video muted extension that is included in users presence in Jitsi-meet + * conferences. It does carry the info about user's video muted status. + * + * @author Pawel Domas + */ +public class VideoMutedExtension + extends AbstractPacketExtension +{ + /** + * The namespace of this packet extension. + */ + public static final String NAMESPACE = "http://jitsi.org/jitmeet/video"; + + /** + * XML element name of this packet extension. + */ + public static final String ELEMENT_NAME = "videomuted"; + + /** + * Creates new instance of VideoMutedExtension. + */ + public VideoMutedExtension() + { + super(NAMESPACE, ELEMENT_NAME); + } + + /** + * Check whether or not user's video is in muted status. + * @return true if muted, false if unmuted or + * null if no valid info found in the extension body. + */ + public Boolean isVideoMuted() + { + return Boolean.valueOf(getText()); + } + + /** + * Sets user's video muted status. + * + * @param videoMuted true or false which indicates video + * muted status of the user. + */ + public void setVideoMuted(Boolean videoMuted) + { + setText( + String.valueOf(videoMuted)); + } +} -- cgit v1.1 From 293544d08c53c33e83ff4028dd15e8b08390f30a Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Wed, 9 Dec 2015 14:30:14 -0600 Subject: Adds a jibri packet extension. --- .../impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 2ea5c9c..355b4a1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -32,6 +32,7 @@ import net.java.sip.communicator.impl.protocol.jabber.extensions.carbon.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.coin.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.inputevt.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jibri.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.jingleinfo.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.keepalive.*; @@ -1732,6 +1733,12 @@ public class ProtocolProviderServiceJabberImpl ColibriConferenceIQ.NAMESPACE, new ColibriIQProvider()); + providerManager.addIQProvider( + JibriIq.ELEMENT_NAME, + JibriIq.NAMESPACE, + new JibriIqProvider() + ); + providerManager.addExtensionProvider( ConferenceDescriptionPacketExtension.ELEMENT_NAME, ConferenceDescriptionPacketExtension.NAMESPACE, -- cgit v1.1 From b3aea5feed318e83886f938d0f61980e661188ec Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Wed, 9 Dec 2015 14:37:48 -0600 Subject: Adds a jibri packet extension. --- .../protocol/jabber/extensions/jibri/JibriIq.java | 259 +++++++++++++++++++++ .../jabber/extensions/jibri/JibriIqProvider.java | 99 ++++++++ 2 files changed, 358 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java new file mode 100644 index 0000000..a58dab4 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -0,0 +1,259 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; + +import org.jitsi.util.*; + +import org.jivesoftware.smack.packet.*; + +import java.util.*; + +/** + * The IQ used to communicate with Jirecon recording container. + * + * @author lishunyang + * @author Pawel Domas + */ +public class JibriIq + extends IQ +{ + public static final String NAMESPACE = "http://jitsi.org/protocol/jibri"; + + public static final String ELEMENT_NAME = "jibri"; + + /** + * Attribute name of "action". + */ + public static final String ACTION_ATTR_NAME = "action"; + + /** + * Attribute name of "status". + */ + public static final String STATUS_ATTR_NAME = "status"; + + private Action action = Action.UNDEFINED; + private Status status = Status.UNDEFINED; + private String url = null; + + public String getStreamId() + { + return streamId; + } + + public void setStreamId(String streamId) + { + this.streamId = streamId; + } + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + private String streamId = null; + + @Override + public String getChildElementXML() + { + StringBuilder xml = new StringBuilder(); + + xml.append('<').append(ELEMENT_NAME); + xml.append(" xmlns='").append(NAMESPACE).append("' "); + + if (action != Action.UNDEFINED) + { + printStringAttribute(xml, ACTION_ATTR_NAME, action.toString()); + } + + if (status != Status.UNDEFINED) + { + printStringAttribute(xml, STATUS_ATTR_NAME, status.toString()); + } + + if (url != null) + { + printStringAttribute(xml, "url", url); + } + + if (streamId != null) + { + printStringAttribute(xml, "streamid", streamId); + } + + + Collection extensions = getExtensions(); + if (extensions.size() > 0) + { + xml.append(">"); + for (PacketExtension extension : extensions) + { + xml.append(extension.toXML()); + } + xml.append(""); + } + else + { + xml.append("/>"); + } + + return xml.toString(); + } + + private void printStringAttribute( + StringBuilder xml, String attrName, String attr) + { + if (!StringUtils.isNullOrEmpty(attr)) + xml.append(attrName).append("='") + .append(attr).append("' "); + } + + /** + * Sets the value of 'action' attribute. + * + * @param action the value to be set as 'action' attribute of this IQ. + */ + public void setAction(Action action) + { + this.action = action; + } + + /** + * Returns the value of 'action' attribute. + */ + public Action getAction() + { + return action; + } + + /** + * Sets the value of 'status' attribute. + */ + public void setStatus(Status status) + { + this.status = status; + } + + /** + * Returns the value of 'status' attribute. + */ + public Status getStatus() + { + return status; + } + + /** + * Enumerative value of attribute "action" in recording extension. + * + * @author lishunyang + * @author Pawel Domas + * + */ + public enum Action + { + START("start"), + STOP("stop"), + UNDEFINED("undefined"); + + private String name; + + Action(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + + /** + * Parses Action from given string. + * + * @param action the string representation of Action. + * + * @return Action value for given string or + * {@link #UNDEFINED} if given string does not + * reflect any of valid values. + */ + public static Action parse(String action) + { + if (StringUtils.isNullOrEmpty(action)) + return UNDEFINED; + + try + { + return Action.valueOf(action.toUpperCase()); + } + catch(IllegalArgumentException e) + { + return UNDEFINED; + } + } + } + + public enum Status + { + ON("on"), + OFF("off"), + PENDING("pending"), + UNDEFINED("undefined"); + + private String name; + + Status(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + + /** + * Parses Status from given string. + * + * @param status the string representation of Status. + * + * @return Status value for given string or + * {@link #UNDEFINED} if given string does not + * reflect any of valid values. + */ + public static Status parse(String status) + { + if (StringUtils.isNullOrEmpty(status)) + return UNDEFINED; + + try + { + return Status.valueOf(status.toUpperCase()); + } + catch(IllegalArgumentException e) + { + return UNDEFINED; + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java new file mode 100644 index 0000000..9c24ff9 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -0,0 +1,99 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.provider.*; + +import org.xmlpull.v1.*; + +public class JibriIqProvider + implements IQProvider +{ + /** + * {@inheritDoc} + */ + @Override + public IQ parseIQ(XmlPullParser parser) + throws Exception + { + String namespace = parser.getNamespace(); + + // Check the namespace + if (!JibriIq.NAMESPACE.equals(namespace)) + { + return null; + } + + String rootElement = parser.getName(); + + JibriIq iq; + + if (JibriIq.ELEMENT_NAME.equals(rootElement)) + { + iq = new JibriIq(); + + String action + = parser.getAttributeValue("", JibriIq.ACTION_ATTR_NAME); + String status + = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME); + + iq.setAction(JibriIq.Action.parse(action)); + + iq.setStatus(JibriIq.Status.parse(status)); + + String url = parser.getAttributeValue("", "url"); + String streamId = parser.getAttributeValue("", "streamid"); + if (url != null) + iq.setUrl(url); + if (streamId != null) + iq.setStreamId(streamId); + } + else + { + return null; + } + + boolean done = false; + + while (!done) + { + switch (parser.next()) + { + case XmlPullParser.END_TAG: + { + String name = parser.getName(); + + if (rootElement.equals(name)) + { + done = true; + } + break; + } + + case XmlPullParser.TEXT: + { + // Parse some text here + break; + } + } + } + + return iq; + } +} -- cgit v1.1 From 08fd8ef3e3ccb7e6daffbe4b79c29106d84e4ed2 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 9 Dec 2015 14:49:44 -0600 Subject: Adds JibriStatusPacketExtension --- .../extensions/jibri/JibriStatusPacketExt.java | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java new file mode 100644 index 0000000..475c3a8 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java @@ -0,0 +1,91 @@ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.*; +import org.jitsi.util.*; + +/** + * Status extension included in MUC presence by Jibri to indicate it's status. + * On of: + *
  • idle
  • - the instance is idle and can be used for recording + *
  • busy
  • - the instance is currently recording or doing something very + * important and should not be disturbed + * + * + */ +public class JibriStatusPacketExt + extends AbstractPacketExtension +{ + /** + * The namespace of this packet extension. + */ + private static final String NAMESPACE = JibriIq.NAMESPACE; + + /** + * XML element name of this packet extension. + */ + private static final String ELEMENT_NAME = "jibri-status"; + + private static final String STATUS_ATTRIBUTE = "status"; + + /** + * Creates new instance of VideoMutedExtension. + */ + public JibriStatusPacketExt() + { + super(NAMESPACE, ELEMENT_NAME); + } + + public Status getStatus() + { + return Status.parse(getAttributeAsString(STATUS_ATTRIBUTE)); + } + + public void setStatus(Status status) + { + setAttribute(STATUS_ATTRIBUTE, String.valueOf(status)); + } + + public enum Status + { + IDLE("idle"), + BUSY("busy"), + UNDEFINED("undefined"); + + private String name; + + Status(String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } + + /** + * Parses Status from given string. + * + * @param status the string representation of Status. + * + * @return Status value for given string or + * {@link #UNDEFINED} if given string does not + * reflect any of valid values. + */ + public static Status parse(String status) + { + if (StringUtils.isNullOrEmpty(status)) + return UNDEFINED; + + try + { + return Status.valueOf(status.toUpperCase()); + } + catch(IllegalArgumentException e) + { + return UNDEFINED; + } + } + } +} -- cgit v1.1 From 202fb1bc0716396370dd710715e8ac4fd1756167 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 9 Dec 2015 16:03:38 -0600 Subject: Makes some fields public and adds utility method to JibriStatusPacketExtension. --- .../jabber/extensions/jibri/JibriStatusPacketExt.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java index 475c3a8..ddab0a1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java @@ -2,6 +2,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; import org.jitsi.util.*; +import org.jivesoftware.smack.provider.*; /** * Status extension included in MUC presence by Jibri to indicate it's status. @@ -18,12 +19,12 @@ public class JibriStatusPacketExt /** * The namespace of this packet extension. */ - private static final String NAMESPACE = JibriIq.NAMESPACE; + public static final String NAMESPACE = JibriIq.NAMESPACE; /** * XML element name of this packet extension. */ - private static final String ELEMENT_NAME = "jibri-status"; + public static final String ELEMENT_NAME = "jibri-status"; private static final String STATUS_ATTRIBUTE = "status"; @@ -35,6 +36,16 @@ public class JibriStatusPacketExt super(NAMESPACE, ELEMENT_NAME); } + static public void registerExtensionProvider() + { + ProviderManager.getInstance().addExtensionProvider( + ELEMENT_NAME, + NAMESPACE, + new DefaultPacketExtensionProvider( + JibriStatusPacketExt.class) + ); + } + public Status getStatus() { return Status.parse(getAttributeAsString(STATUS_ATTRIBUTE)); -- cgit v1.1 From a4d0a466c58a0463673e46b036d1c075062e1c04 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 9 Dec 2015 16:09:57 -0600 Subject: Adds recording status Presence packet extension. --- .../jabber/extensions/jibri/RecordingStatus.java | 58 ++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java new file mode 100644 index 0000000..8d60218 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java @@ -0,0 +1,58 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.*; + +/** + * The packet extension added to Jicofo presence to broadcast current recording + * status to all conference participants. + * + */ +public class RecordingStatus + extends AbstractPacketExtension +{ + /** + * The namespace of this packet extension. + */ + public static final String NAMESPACE = JibriIq.NAMESPACE; + + /** + * XML element name of this packet extension. + */ + public static final String ELEMENT_NAME = "jibri-recording-status"; + + private static final String STATUS_ATTRIBUTE = "status"; + + public RecordingStatus() + { + super(NAMESPACE, ELEMENT_NAME); + } + + public JibriIq.Status getStatus() + { + String statusAttr = getAttributeAsString(STATUS_ATTRIBUTE); + + return JibriIq.Status.parse(statusAttr); + } + + public void setStatus(JibriIq.Status status) + { + setAttribute(STATUS_ATTRIBUTE, String.valueOf(status)); + } +} -- cgit v1.1 From 9c75e5680f8b85a6ad425e5fed3ff9beec05abe1 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 9 Dec 2015 16:12:34 -0600 Subject: Explains recording status --- .../impl/protocol/jabber/extensions/jibri/RecordingStatus.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java index 8d60218..8e6f452 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java @@ -23,6 +23,11 @@ import net.java.sip.communicator.impl.protocol.jabber.extensions.*; * The packet extension added to Jicofo presence to broadcast current recording * status to all conference participants. * + * Status meaning: + * {@link JibriIq.Status#UNDEFINED} - recording not available + * {@link JibriIq.Status#OFF} - recording stopped(available to start) + * {@link JibriIq.Status#PENDING} - starting recording + * {@link JibriIq.Status#ON} - recording in progress */ public class RecordingStatus extends AbstractPacketExtension -- cgit v1.1 From a03e075a41170c23c063c1aaf8ce37d0f7c51652 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Wed, 9 Dec 2015 17:01:51 -0600 Subject: Manually fixes formatting for the sake of readability and consistency. --- .../packetlogging/PacketLoggingServiceImpl.java | 34 ++++++++++------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 1954f99..6486398 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -314,24 +314,22 @@ public class PacketLoggingServiceImpl { switch(protocol) { - case SIP: - return cfg.isSipLoggingEnabled(); - case JABBER: - return cfg.isJabberLoggingEnabled(); - case RTP: - return cfg.isRTPLoggingEnabled(); - case ICE4J: - return cfg.isIce4JLoggingEnabled(); - case ARBITRARY: - return cfg.isArbitraryLoggingEnabled(); - default: - /* - * It may seem like it was unnecessary to invoke - * getConfiguration and isGlobalLoggingEnabled prior to - * checking that the specified protocol is supported but, - * actually, there are no other ProtocolName values. - */ - return false; + case SIP: + return cfg.isSipLoggingEnabled(); + case JABBER: + return cfg.isJabberLoggingEnabled(); + case RTP: + return cfg.isRTPLoggingEnabled(); + case ICE4J: + return cfg.isIce4JLoggingEnabled(); + case ARBITRARY: + return cfg.isArbitraryLoggingEnabled(); + default: + // It may seem like it was unnecessary to invoke + // getConfiguration and isGlobalLoggingEnabled prior to checking + // that the specified protocol is supported but, actually, there + // are no other ProtocolName values. + return false; } } else -- cgit v1.1 From 5ff04dbd6722d4f79efd191f41bbf17b978adc55 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 9 Dec 2015 17:02:12 -0600 Subject: Adds URL to RecordingStatus --- .../protocol/jabber/extensions/jibri/RecordingStatus.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java index 8e6f452..f456261 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java @@ -44,6 +44,8 @@ public class RecordingStatus private static final String STATUS_ATTRIBUTE = "status"; + private static final String URL_ATTRIBUTE = "url"; + public RecordingStatus() { super(NAMESPACE, ELEMENT_NAME); @@ -60,4 +62,14 @@ public class RecordingStatus { setAttribute(STATUS_ATTRIBUTE, String.valueOf(status)); } + + public String getUrl() + { + return getAttributeAsString(URL_ATTRIBUTE); + } + + public void setAttribute(String url) + { + setAttribute(URL_ATTRIBUTE, url); + } } -- cgit v1.1 From 943e93d5c58e61fc41bb3fa1d0c22c0713801cb3 Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Thu, 10 Dec 2015 08:35:38 -0600 Subject: Adds a follow-entity attribute. --- .../protocol/jabber/extensions/jibri/JibriIq.java | 19 +++++++++++++++++-- .../jabber/extensions/jibri/JibriIqProvider.java | 3 +++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index a58dab4..0e34fe6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -24,8 +24,6 @@ import org.jivesoftware.smack.packet.*; import java.util.*; /** - * The IQ used to communicate with Jirecon recording container. - * * @author lishunyang * @author Pawel Domas */ @@ -50,6 +48,18 @@ public class JibriIq private Status status = Status.UNDEFINED; private String url = null; + public String getFollowEntity() + { + return followEntity; + } + + public void setFollowEntity(String followEntity) + { + this.followEntity = followEntity; + } + + private String followEntity = null; + public String getStreamId() { return streamId; @@ -100,6 +110,11 @@ public class JibriIq printStringAttribute(xml, "streamid", streamId); } + if (followEntity != null) + { + printStringAttribute(xml, "follow-entity", followEntity); + } + Collection extensions = getExtensions(); if (extensions.size() > 0) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java index 9c24ff9..d4b08f6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -63,6 +63,9 @@ public class JibriIqProvider iq.setUrl(url); if (streamId != null) iq.setStreamId(streamId); + String followEntity = parser.getAttributeValue("", "follow-entity"); + if (followEntity != null) + iq.setFollowEntity(followEntity); } else { -- cgit v1.1 From 0ab59e812036f39ac1cf9e1aed1a87b92768cad6 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Fri, 11 Dec 2015 14:22:39 -0600 Subject: Adds ForceShutdown IQ. --- .../extensions/colibri/ColibriIQProvider.java | 14 ++- .../extensions/colibri/GracefulShutdownIQ.java | 40 ------ .../jabber/extensions/colibri/ShutdownIQ.java | 134 +++++++++++++++++++++ 3 files changed, 143 insertions(+), 45 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 016d9b7..cc6d0c9 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -87,8 +87,12 @@ public class ColibriIQProvider parameterProvider); // Shutdown IQ smackInteroperabilityLayer.addIQProvider( - GracefulShutdownIQ.ELEMENT_NAME, - GracefulShutdownIQ.NAMESPACE, + ShutdownIQ.GRACEFUL_ELEMENT_NAME, + ShutdownIQ.NAMESPACE, + this); + smackInteroperabilityLayer.addIQProvider( + ShutdownIQ.FORCE_ELEMENT_NAME, + ShutdownIQ.NAMESPACE, this); // Shutdown extension PacketExtensionProvider shutdownProvider @@ -810,12 +814,12 @@ public class ColibriIQProvider iq = conference; } - else if (GracefulShutdownIQ.ELEMENT_NAME.equals(parser.getName()) - && GracefulShutdownIQ.NAMESPACE.equals(namespace)) + else if (ShutdownIQ.NAMESPACE.equals(namespace) && + ShutdownIQ.isValidElementName(parser.getName())) { String rootElement = parser.getName(); - iq = new GracefulShutdownIQ(); + iq = ShutdownIQ.createShutdownIQ(rootElement); boolean done = false; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java deleted file mode 100644 index 9808b11..0000000 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; - -import org.jivesoftware.smack.packet.*; - -/** - * The IQ used to trigger the graceful shutdown mode of the videobridge which - * receives the stanza(given that source JID is authorized to start it). - * - * @author Pawel Domas - */ -public class GracefulShutdownIQ - extends IQ -{ - public static final String NAMESPACE = ColibriConferenceIQ.NAMESPACE; - - public static final String ELEMENT_NAME = "graceful-shutdown"; - - @Override - public String getChildElementXML() - { - return "<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "' />"; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java new file mode 100644 index 0000000..4df251b --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java @@ -0,0 +1,134 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; + +import org.jivesoftware.smack.packet.*; + +/** + * The IQ used to trigger the graceful shutdown mode of the videobridge or force + * shutdown the one which receives the stanza(given that source JID is + * authorized to do so). + * + * @author Pawel Domas + */ +public class ShutdownIQ + extends IQ +{ + /** + * XML namespace name for shutdown IQs. + */ + final static public String NAMESPACE = ColibriConferenceIQ.NAMESPACE; + + /** + * Force shutdown IQ element name. + */ + final static public String FORCE_ELEMENT_NAME = "force-shutdown"; + + /** + * Graceful shutdown IQ element name. + */ + final static public String GRACEFUL_ELEMENT_NAME = "graceful-shutdown"; + + /** + * The element name of this IQ. Either {@link #FORCE_ELEMENT_NAME} or + * {@link #GRACEFUL_ELEMENT_NAME}. + */ + private final String elementName; + + /** + * Checks if given element is a valid one for ShutdownIQ. + * + * @param elementName the name if XML element name inside of the IQ. + * + * @return true if given elementName is correct for + * ShutdownIQ. + */ + public static boolean isValidElementName(String elementName) + { + return GRACEFUL_ELEMENT_NAME.equals(elementName) + || FORCE_ELEMENT_NAME.equals(elementName); + } + + /** + * Creates shutdown IQ for given element name. + * + * @param elementName can be {@link #FORCE_ELEMENT_NAME} or + * {@link #GRACEFUL_ELEMENT_NAME} + * + * @return new ShutdownIQ instance for given element name. + * + * @throws IllegalArgumentException if given element name is neither + * {@link #FORCE_ELEMENT_NAME} nor {@link #GRACEFUL_ELEMENT_NAME}. + */ + public static ShutdownIQ createShutdownIQ(String elementName) + { + if (!isValidElementName(elementName)) + { + throw new IllegalArgumentException( + "Invalid element name: " + elementName); + } + + if (GRACEFUL_ELEMENT_NAME.equals(elementName)) + { + return createGracefulShutdownIQ(); + } + else + { + return createForceShutdownIQ(); + } + } + + /** + * Creates and returns new instance of graceful shutdown IQ. + */ + public static ShutdownIQ createGracefulShutdownIQ() + { + return new ShutdownIQ(GRACEFUL_ELEMENT_NAME); + } + + /** + * Creates and returns new instance of force shutdown IQ. + */ + public static ShutdownIQ createForceShutdownIQ() + { + return new ShutdownIQ(FORCE_ELEMENT_NAME); + } + + private ShutdownIQ(String elementName) + { + this.elementName = elementName; + } + + /** + * Returns true if this IQ instance is a "graceful shutdown" one. + * Otherwise it is a force shutdown IQ. + */ + public boolean isGracefulShutdown() + { + return elementName.equals(GRACEFUL_ELEMENT_NAME); + } + + /** + * {@inheritDoc} + */ + @Override + public String getChildElementXML() + { + return "<" + elementName + " xmlns='" + NAMESPACE + "' />"; + } +} -- cgit v1.1 From 999271c02f6de779e5de74645ab6e880b0bf8e27 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:40:50 -0600 Subject: Updates loadLibrary to be able to use native libraries from within the bundle. --- .../sysactivity/SystemActivityNotifications.java | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java index a6ff936..f4f6ede 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java @@ -1,23 +1,24 @@ /* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package net.java.sip.communicator.impl.sysactivity; -import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.Logger; +import org.jitsi.util.*; /** * @author Damian Minkov @@ -113,7 +114,8 @@ public class SystemActivityNotifications // Don't load native library on Android to prevent the exception if(!org.jitsi.util.OSUtils.IS_ANDROID) { - System.loadLibrary("sysactivitynotifications"); + JNIUtils.loadLibrary("sysactivitynotifications", + SystemActivityNotifications.class.getClassLoader()); ptr = allocAndInit(); if (ptr == -1) -- cgit v1.1 From e012e3e683d72ed833de47e5b3b1d5189de80bf6 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:41:17 -0600 Subject: Expands the Maven support to more bundles. --- m2/jitsi-certificate/pom.xml | 78 +++++++++++++++++++++ m2/jitsi-desktoputil/pom.xml | 57 +++++++++++++++ m2/jitsi-dns/pom.xml | 56 +++++++++++++++ m2/jitsi-globaldisplaydetails/pom.xml | 54 ++++++++++++++ m2/jitsi-muc/pom.xml | 52 ++++++++++++++ m2/jitsi-neomedia/pom.xml | 52 ++++++++++++++ m2/jitsi-notification-service/pom.xml | 52 ++++++++++++++ m2/jitsi-reconnect/pom.xml | 52 ++++++++++++++ m2/jitsi-sysactivity/pom.xml | 128 ++++++++++++++++++++++++++++++++++ m2/jitsi-systray-service/pom.xml | 52 ++++++++++++++ m2/jitsi-version/pom.xml | 57 +++++++++++++++ m2/pom.xml | 11 +++ 12 files changed, 701 insertions(+) create mode 100644 m2/jitsi-certificate/pom.xml create mode 100644 m2/jitsi-desktoputil/pom.xml create mode 100644 m2/jitsi-dns/pom.xml create mode 100644 m2/jitsi-globaldisplaydetails/pom.xml create mode 100644 m2/jitsi-muc/pom.xml create mode 100644 m2/jitsi-neomedia/pom.xml create mode 100644 m2/jitsi-notification-service/pom.xml create mode 100644 m2/jitsi-reconnect/pom.xml create mode 100644 m2/jitsi-sysactivity/pom.xml create mode 100644 m2/jitsi-systray-service/pom.xml create mode 100644 m2/jitsi-version/pom.xml diff --git a/m2/jitsi-certificate/pom.xml b/m2/jitsi-certificate/pom.xml new file mode 100644 index 0000000..a14f1ed --- /dev/null +++ b/m2/jitsi-certificate/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-certificate + jar + + jitsi-certificate + + + + org.bouncycastle + bcprov-jdk15on + + 1.51-jitsi-1 + + + org.apache.httpcomponents + httpclient + 4.4 + + + org.apache.httpcomponents + httpcore + 4.4 + + + org.apache.httpcomponents + httpmime + 4.4 + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/certificate/** + net/java/sip/communicator/impl/certificate/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/certificate/certificate.manifest.mf + + + net/java/sip/communicator/service/certificate/** + net/java/sip/communicator/impl/certificate/** + + + + + + diff --git a/m2/jitsi-desktoputil/pom.xml b/m2/jitsi-desktoputil/pom.xml new file mode 100644 index 0000000..701559c --- /dev/null +++ b/m2/jitsi-desktoputil/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-desktoputil + jar + + jitsi-desktoputil + + + + net.java.dev.laf-widget + laf-widget + 4.0 + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/plugin/desktoputil/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/plugin/desktoputil/desktoputil.manifest.mf + + + net/java/sip/communicator/plugin/desktoputil/** + + + + + + diff --git a/m2/jitsi-dns/pom.xml b/m2/jitsi-dns/pom.xml new file mode 100644 index 0000000..c8fc438 --- /dev/null +++ b/m2/jitsi-dns/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-dns + jar + + jitsi-dns + + + + dnsjava + dnsjava + + + + ${project.groupId} + jitsi-protocol + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/dns/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/dns/dns.manifest.mf + + + net/java/sip/communicator/impl/dns/** + + + + + + diff --git a/m2/jitsi-globaldisplaydetails/pom.xml b/m2/jitsi-globaldisplaydetails/pom.xml new file mode 100644 index 0000000..0e3a828 --- /dev/null +++ b/m2/jitsi-globaldisplaydetails/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-globaldisplaydetails + jar + + jitsi-globaldisplaydetails + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/globaldisplaydetails/** + net/java/sip/communicator/impl/globaldisplaydetails/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/globaldisplaydetails/globaldisplaydetails.manifest.mf + + + net/java/sip/communicator/service/globaldisplaydetails/** + net/java/sip/communicator/impl/globaldisplaydetails/** + + + + + + diff --git a/m2/jitsi-muc/pom.xml b/m2/jitsi-muc/pom.xml new file mode 100644 index 0000000..952ddd8 --- /dev/null +++ b/m2/jitsi-muc/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-muc + jar + + jitsi-muc + + + + ${project.groupId} + jitsi-protocol + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/muc/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/muc/muc.manifest.mf + + + net/java/sip/communicator/service/muc/** + + + + + + diff --git a/m2/jitsi-neomedia/pom.xml b/m2/jitsi-neomedia/pom.xml new file mode 100644 index 0000000..e63f8e0 --- /dev/null +++ b/m2/jitsi-neomedia/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-neomedia + jar + + jitsi-neomedia + + + + + ${project.groupId} + jitsi-util + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/neomedia/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf + + + net/java/sip/communicator/impl/neomedia/** + + + + + + diff --git a/m2/jitsi-notification-service/pom.xml b/m2/jitsi-notification-service/pom.xml new file mode 100644 index 0000000..7ad123e --- /dev/null +++ b/m2/jitsi-notification-service/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-notification-service + jar + + jitsi-notification-service + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/notification/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/service/notification/notification.manifest.mf + + + net/java/sip/communicator/service/notification/** + + + + + + diff --git a/m2/jitsi-reconnect/pom.xml b/m2/jitsi-reconnect/pom.xml new file mode 100644 index 0000000..8eaf4f1 --- /dev/null +++ b/m2/jitsi-reconnect/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-reconnect + jar + + jitsi-reconnect + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/plugin/reconnectplugin/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/plugin/reconnectplugin/reconnectplugin.manifest.mf + + + net/java/sip/communicator/plugin/reconnectplugin/** + + + + + + diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml new file mode 100644 index 0000000..2c62811 --- /dev/null +++ b/m2/jitsi-sysactivity/pom.xml @@ -0,0 +1,128 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-sysactivity + bundle + + jitsi-sysactivity + + + + org.freedesktop.dbus + dbus-java + 2.7 + + + org.abstractj.libmatthew + hexdump + 0.2.1 + + + org.abstractj.libmatthew + unix + 0.5.1 + + + org.abstractj.libmatthew + libunix + 0.5.1 + so + + + + ${project.groupId} + jitsi-util + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/sysactivity/** + net/java/sip/communicator/impl/sysactivity/** + + + + + org.apache.felix + maven-bundle-plugin + + + org.osgi.framework, + org.jitsi.service.version, + org.jitsi.service.configuration, + org.jitsi.util, + org.jitsi.service.resources, net.java.sip.communicator.service.resources, + net.java.sip.communicator.util + + net.java.sip.communicator.service.sysactivity, + net.java.sip.communicator.service.sysactivity.event + + net.java.sip.communicator.impl.sysactivity.* + net.java.sip.communicator.impl.sysactivity.SysActivityActivator + + darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64 + + + + + + + + + + + + + darwin + ../../lib/native/mac + + **/*sysactivitynotifications.* + + + + linux-x86 + ../../lib/native/linux + + **/*sysactivitynotifications.* + + + + linux-x86-64 + ../../lib/native/linux-64 + + **/*sysactivitynotifications.* + + + + win32-x86-64 + ../../lib/native/windows-64 + + **/*sysactivitynotifications.* + + + + win32-x86 + ../../lib/native/windows + + **/*sysactivitynotifications.* + + + + + + diff --git a/m2/jitsi-systray-service/pom.xml b/m2/jitsi-systray-service/pom.xml new file mode 100644 index 0000000..3965173 --- /dev/null +++ b/m2/jitsi-systray-service/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-systray-service + jar + + jitsi-systray-service + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/systray/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/service/systray/systray.manifest.mf + + + net/java/sip/communicator/service/systray/** + + + + + + diff --git a/m2/jitsi-version/pom.xml b/m2/jitsi-version/pom.xml new file mode 100644 index 0000000..6531000 --- /dev/null +++ b/m2/jitsi-version/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-version + jar + + jitsi-version + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/version/** + + + **/*.tmpl + **/version.impl.manifest.mf + **/SipCommunicatorVersionTask.java + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/version/version.impl.manifest.mf + + + net/java/sip/communicator/impl/version/** + + + + + + diff --git a/m2/pom.xml b/m2/pom.xml index e8fd64d..fcbb32c 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -19,19 +19,30 @@ https://jitsi.org + jitsi-certificate jitsi-configuration jitsi-contactlist jitsi-credentialsstorage + jitsi-desktoputil + jitsi-dns jitsi-dnsservice jitsi-fileaccess + jitsi-globaldisplaydetails + jitsi-muc + jitsi-neomedia jitsi-netaddr + jitsi-notification-service jitsi-packetlogging jitsi-protocol jitsi-protocol-jabber jitsi-protocol-media + jitsi-reconnect jitsi-resourcemanager + jitsi-sysactivity + jitsi-systray-service jitsi-ui-service jitsi-util + jitsi-version -- cgit v1.1 From 863c3dab1b3466cc6a6c47ad2a2316947b9e1cc0 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:59:55 -0600 Subject: Updates sysactivity mvn bundle, includes all native code, commented by mistake. --- m2/jitsi-sysactivity/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml index 2c62811..0f45f4d 100644 --- a/m2/jitsi-sysactivity/pom.xml +++ b/m2/jitsi-sysactivity/pom.xml @@ -75,11 +75,11 @@ net.java.sip.communicator.impl.sysactivity.* net.java.sip.communicator.impl.sysactivity.SysActivityActivator - darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64 - - - - + darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64, + linux-x86/libsysactivitynotifications.so;osname=Linux;processor=x86, + linux-x86-64/libsysactivitynotifications.so;osname=Linux;processor=x86-64, + win32-x86/sysactivitynotifications.dll;osname=Win32;processor=x86, + win32-x86-64/sysactivitynotifications.dll;osname=Win32;processor=x86-64 -- cgit v1.1 From b715a8c430728fc0630d98c18786663dc0f380c1 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:40:50 -0600 Subject: Updates loadLibrary to be able to use native libraries from within the bundle. --- .../sysactivity/SystemActivityNotifications.java | 38 ++++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java index a6ff936..f4f6ede 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java @@ -1,23 +1,24 @@ /* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package net.java.sip.communicator.impl.sysactivity; -import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.Logger; +import org.jitsi.util.*; /** * @author Damian Minkov @@ -113,7 +114,8 @@ public class SystemActivityNotifications // Don't load native library on Android to prevent the exception if(!org.jitsi.util.OSUtils.IS_ANDROID) { - System.loadLibrary("sysactivitynotifications"); + JNIUtils.loadLibrary("sysactivitynotifications", + SystemActivityNotifications.class.getClassLoader()); ptr = allocAndInit(); if (ptr == -1) -- cgit v1.1 From 65fc62b01ddf9b8974d43da2ef915e4717e5f11e Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:41:17 -0600 Subject: Expands the Maven support to more bundles. --- m2/jitsi-certificate/pom.xml | 78 +++++++++++++++++++++ m2/jitsi-desktoputil/pom.xml | 57 +++++++++++++++ m2/jitsi-dns/pom.xml | 56 +++++++++++++++ m2/jitsi-globaldisplaydetails/pom.xml | 54 ++++++++++++++ m2/jitsi-muc/pom.xml | 52 ++++++++++++++ m2/jitsi-neomedia/pom.xml | 52 ++++++++++++++ m2/jitsi-notification-service/pom.xml | 52 ++++++++++++++ m2/jitsi-reconnect/pom.xml | 52 ++++++++++++++ m2/jitsi-sysactivity/pom.xml | 128 ++++++++++++++++++++++++++++++++++ m2/jitsi-systray-service/pom.xml | 52 ++++++++++++++ m2/jitsi-version/pom.xml | 57 +++++++++++++++ m2/pom.xml | 11 +++ 12 files changed, 701 insertions(+) create mode 100644 m2/jitsi-certificate/pom.xml create mode 100644 m2/jitsi-desktoputil/pom.xml create mode 100644 m2/jitsi-dns/pom.xml create mode 100644 m2/jitsi-globaldisplaydetails/pom.xml create mode 100644 m2/jitsi-muc/pom.xml create mode 100644 m2/jitsi-neomedia/pom.xml create mode 100644 m2/jitsi-notification-service/pom.xml create mode 100644 m2/jitsi-reconnect/pom.xml create mode 100644 m2/jitsi-sysactivity/pom.xml create mode 100644 m2/jitsi-systray-service/pom.xml create mode 100644 m2/jitsi-version/pom.xml diff --git a/m2/jitsi-certificate/pom.xml b/m2/jitsi-certificate/pom.xml new file mode 100644 index 0000000..a14f1ed --- /dev/null +++ b/m2/jitsi-certificate/pom.xml @@ -0,0 +1,78 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-certificate + jar + + jitsi-certificate + + + + org.bouncycastle + bcprov-jdk15on + + 1.51-jitsi-1 + + + org.apache.httpcomponents + httpclient + 4.4 + + + org.apache.httpcomponents + httpcore + 4.4 + + + org.apache.httpcomponents + httpmime + 4.4 + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/certificate/** + net/java/sip/communicator/impl/certificate/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/certificate/certificate.manifest.mf + + + net/java/sip/communicator/service/certificate/** + net/java/sip/communicator/impl/certificate/** + + + + + + diff --git a/m2/jitsi-desktoputil/pom.xml b/m2/jitsi-desktoputil/pom.xml new file mode 100644 index 0000000..701559c --- /dev/null +++ b/m2/jitsi-desktoputil/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-desktoputil + jar + + jitsi-desktoputil + + + + net.java.dev.laf-widget + laf-widget + 4.0 + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/plugin/desktoputil/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/plugin/desktoputil/desktoputil.manifest.mf + + + net/java/sip/communicator/plugin/desktoputil/** + + + + + + diff --git a/m2/jitsi-dns/pom.xml b/m2/jitsi-dns/pom.xml new file mode 100644 index 0000000..c8fc438 --- /dev/null +++ b/m2/jitsi-dns/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-dns + jar + + jitsi-dns + + + + dnsjava + dnsjava + + + + ${project.groupId} + jitsi-protocol + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/dns/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/dns/dns.manifest.mf + + + net/java/sip/communicator/impl/dns/** + + + + + + diff --git a/m2/jitsi-globaldisplaydetails/pom.xml b/m2/jitsi-globaldisplaydetails/pom.xml new file mode 100644 index 0000000..0e3a828 --- /dev/null +++ b/m2/jitsi-globaldisplaydetails/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-globaldisplaydetails + jar + + jitsi-globaldisplaydetails + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/globaldisplaydetails/** + net/java/sip/communicator/impl/globaldisplaydetails/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/globaldisplaydetails/globaldisplaydetails.manifest.mf + + + net/java/sip/communicator/service/globaldisplaydetails/** + net/java/sip/communicator/impl/globaldisplaydetails/** + + + + + + diff --git a/m2/jitsi-muc/pom.xml b/m2/jitsi-muc/pom.xml new file mode 100644 index 0000000..952ddd8 --- /dev/null +++ b/m2/jitsi-muc/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-muc + jar + + jitsi-muc + + + + ${project.groupId} + jitsi-protocol + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/muc/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/muc/muc.manifest.mf + + + net/java/sip/communicator/service/muc/** + + + + + + diff --git a/m2/jitsi-neomedia/pom.xml b/m2/jitsi-neomedia/pom.xml new file mode 100644 index 0000000..e63f8e0 --- /dev/null +++ b/m2/jitsi-neomedia/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-neomedia + jar + + jitsi-neomedia + + + + + ${project.groupId} + jitsi-util + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/neomedia/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/neomedia/neomedia.manifest.mf + + + net/java/sip/communicator/impl/neomedia/** + + + + + + diff --git a/m2/jitsi-notification-service/pom.xml b/m2/jitsi-notification-service/pom.xml new file mode 100644 index 0000000..7ad123e --- /dev/null +++ b/m2/jitsi-notification-service/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-notification-service + jar + + jitsi-notification-service + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/notification/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/service/notification/notification.manifest.mf + + + net/java/sip/communicator/service/notification/** + + + + + + diff --git a/m2/jitsi-reconnect/pom.xml b/m2/jitsi-reconnect/pom.xml new file mode 100644 index 0000000..8eaf4f1 --- /dev/null +++ b/m2/jitsi-reconnect/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-reconnect + jar + + jitsi-reconnect + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/plugin/reconnectplugin/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/plugin/reconnectplugin/reconnectplugin.manifest.mf + + + net/java/sip/communicator/plugin/reconnectplugin/** + + + + + + diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml new file mode 100644 index 0000000..2c62811 --- /dev/null +++ b/m2/jitsi-sysactivity/pom.xml @@ -0,0 +1,128 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-sysactivity + bundle + + jitsi-sysactivity + + + + org.freedesktop.dbus + dbus-java + 2.7 + + + org.abstractj.libmatthew + hexdump + 0.2.1 + + + org.abstractj.libmatthew + unix + 0.5.1 + + + org.abstractj.libmatthew + libunix + 0.5.1 + so + + + + ${project.groupId} + jitsi-util + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/sysactivity/** + net/java/sip/communicator/impl/sysactivity/** + + + + + org.apache.felix + maven-bundle-plugin + + + org.osgi.framework, + org.jitsi.service.version, + org.jitsi.service.configuration, + org.jitsi.util, + org.jitsi.service.resources, net.java.sip.communicator.service.resources, + net.java.sip.communicator.util + + net.java.sip.communicator.service.sysactivity, + net.java.sip.communicator.service.sysactivity.event + + net.java.sip.communicator.impl.sysactivity.* + net.java.sip.communicator.impl.sysactivity.SysActivityActivator + + darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64 + + + + + + + + + + + + + darwin + ../../lib/native/mac + + **/*sysactivitynotifications.* + + + + linux-x86 + ../../lib/native/linux + + **/*sysactivitynotifications.* + + + + linux-x86-64 + ../../lib/native/linux-64 + + **/*sysactivitynotifications.* + + + + win32-x86-64 + ../../lib/native/windows-64 + + **/*sysactivitynotifications.* + + + + win32-x86 + ../../lib/native/windows + + **/*sysactivitynotifications.* + + + + + + diff --git a/m2/jitsi-systray-service/pom.xml b/m2/jitsi-systray-service/pom.xml new file mode 100644 index 0000000..3965173 --- /dev/null +++ b/m2/jitsi-systray-service/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-systray-service + jar + + jitsi-systray-service + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/systray/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/service/systray/systray.manifest.mf + + + net/java/sip/communicator/service/systray/** + + + + + + diff --git a/m2/jitsi-version/pom.xml b/m2/jitsi-version/pom.xml new file mode 100644 index 0000000..6531000 --- /dev/null +++ b/m2/jitsi-version/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-version + jar + + jitsi-version + + + + + ${project.groupId} + jitsi-configuration + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/version/** + + + **/*.tmpl + **/version.impl.manifest.mf + **/SipCommunicatorVersionTask.java + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/version/version.impl.manifest.mf + + + net/java/sip/communicator/impl/version/** + + + + + + diff --git a/m2/pom.xml b/m2/pom.xml index e8fd64d..fcbb32c 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -19,19 +19,30 @@ https://jitsi.org + jitsi-certificate jitsi-configuration jitsi-contactlist jitsi-credentialsstorage + jitsi-desktoputil + jitsi-dns jitsi-dnsservice jitsi-fileaccess + jitsi-globaldisplaydetails + jitsi-muc + jitsi-neomedia jitsi-netaddr + jitsi-notification-service jitsi-packetlogging jitsi-protocol jitsi-protocol-jabber jitsi-protocol-media + jitsi-reconnect jitsi-resourcemanager + jitsi-sysactivity + jitsi-systray-service jitsi-ui-service jitsi-util + jitsi-version -- cgit v1.1 From b8c2b0260851755ee28fc494d2553d0edfdc420a Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 22 Dec 2015 15:59:55 -0600 Subject: Updates sysactivity mvn bundle, includes all native code, commented by mistake. --- m2/jitsi-sysactivity/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml index 2c62811..0f45f4d 100644 --- a/m2/jitsi-sysactivity/pom.xml +++ b/m2/jitsi-sysactivity/pom.xml @@ -75,11 +75,11 @@ net.java.sip.communicator.impl.sysactivity.* net.java.sip.communicator.impl.sysactivity.SysActivityActivator - darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64 - - - - + darwin/libsysactivitynotifications.jnilib;osname=Mac OS X;processor=x86-64, + linux-x86/libsysactivitynotifications.so;osname=Linux;processor=x86, + linux-x86-64/libsysactivitynotifications.so;osname=Linux;processor=x86-64, + win32-x86/sysactivitynotifications.dll;osname=Win32;processor=x86, + win32-x86-64/sysactivitynotifications.dll;osname=Win32;processor=x86-64 -- cgit v1.1 From c3b0c0f5194c44fa4c1397ffe05fb1f77e1654ca Mon Sep 17 00:00:00 2001 From: "Thorsten.Klein" Date: Thu, 14 Jan 2016 17:43:33 +0100 Subject: Changed URL pattern for direct image links * URL doesn't necessarily start with 'www' --- .../impl/replacement/directimage/ReplacementServiceDirectImageImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java b/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java index 48bb362..f29a7ab 100644 --- a/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java +++ b/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java @@ -45,7 +45,7 @@ public class ReplacementServiceDirectImageImpl * The regex used to match the link in the message. */ public static final String URL_PATTERN = - "https?\\:\\/\\/(www\\.)*.*\\.(?:jpg|png|gif)"; + "https?\\:\\/\\/*.*\\.(?:jpg|png|gif)"; /** * Configuration label shown in the config form. -- cgit v1.1 From 061154bb62d51d15a77e43d836e45e0470e4864d Mon Sep 17 00:00:00 2001 From: Thorsten Klein Date: Fri, 15 Jan 2016 00:18:52 +0100 Subject: Fix the replacement for direct image links * URLs of the form https://my.example.com:12345/abc/def/file.jpg were not replaced somehow * simply changed the URL_PATTERN --- .../impl/replacement/directimage/ReplacementServiceDirectImageImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java b/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java index f29a7ab..3bdaaa4 100644 --- a/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java +++ b/src/net/java/sip/communicator/impl/replacement/directimage/ReplacementServiceDirectImageImpl.java @@ -45,7 +45,7 @@ public class ReplacementServiceDirectImageImpl * The regex used to match the link in the message. */ public static final String URL_PATTERN = - "https?\\:\\/\\/*.*\\.(?:jpg|png|gif)"; + "https?\\:\\/\\/.*\\.(?:jpg|png|gif)"; /** * Configuration label shown in the config form. -- cgit v1.1 From b59ada8348ec9048fce58801d58a6c76200382a4 Mon Sep 17 00:00:00 2001 From: damencho Date: Fri, 15 Jan 2016 14:35:02 -0600 Subject: Adds Portuguese Brazil. --- resources/config/spellcheck/parameters.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/config/spellcheck/parameters.xml b/resources/config/spellcheck/parameters.xml index 1d3e1e2..3c1cf87 100644 --- a/resources/config/spellcheck/parameters.xml +++ b/resources/config/spellcheck/parameters.xml @@ -117,6 +117,7 @@ + -- cgit v1.1 From 9cf1f1b7ac2a538b406f38103df9c0e28163207e Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Tue, 2 Feb 2016 14:57:29 -0600 Subject: Uses a fixed version of jitsi-universe. --- m2/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/m2/pom.xml b/m2/pom.xml index fcbb32c..f5dc422 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -7,8 +7,7 @@ org.jitsi jitsi-universe - 1.0-SNAPSHOT - ../../jitsi-universe/pom.xml + 1.0-20160202.203332-11 jitsi -- cgit v1.1 From a47efb5a94dad170d9bbec456c2945a844c2d926 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Wed, 6 Jan 2016 18:04:18 +0100 Subject: Cleanup jitsi-certificate pom (use jitsi-universe version) Signed-off-by: Etienne CHAMPETIER --- m2/jitsi-certificate/pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/m2/jitsi-certificate/pom.xml b/m2/jitsi-certificate/pom.xml index a14f1ed..4855162 100644 --- a/m2/jitsi-certificate/pom.xml +++ b/m2/jitsi-certificate/pom.xml @@ -20,26 +20,18 @@ org.bouncycastle bcprov-jdk15on - - 1.51-jitsi-1 org.apache.httpcomponents httpclient - 4.4 org.apache.httpcomponents httpcore - 4.4 org.apache.httpcomponents httpmime - 4.4 -- cgit v1.1 From 2c7f92cccd86e7430fb7928edc0e218163159e77 Mon Sep 17 00:00:00 2001 From: damencho Date: Wed, 3 Feb 2016 12:54:26 -0600 Subject: Adds property to disable printing timestamp in logs. --- .../java/sip/communicator/util/ScLogFormatter.java | 75 ++++++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/src/net/java/sip/communicator/util/ScLogFormatter.java b/src/net/java/sip/communicator/util/ScLogFormatter.java index 7ecb389..5d22db5 100644 --- a/src/net/java/sip/communicator/util/ScLogFormatter.java +++ b/src/net/java/sip/communicator/util/ScLogFormatter.java @@ -39,7 +39,12 @@ public class ScLogFormatter */ private static final String PROGRAM_NAME_PROPERTY = ".programname"; - + /** + * Disable timestamp logging property name. + */ + private static final String DISABLE_TIMESTAMP_PROPERTY + = ".disableTimestamp"; + /** * Line separator used by current platform */ @@ -61,12 +66,17 @@ public class ScLogFormatter private static String programName; /** + * Whether logger will add date to the logs, enabled by default. + */ + private static boolean timestampDisabled = false; + + /** * The default constructor for ScLogFormatter which loads * program name property from logging.properties file, if it exists */ public ScLogFormatter() { - loadProgramNameProperty(); + loadConfigProperties(); } /** @@ -88,23 +98,26 @@ public class ScLogFormatter sb.append(' '); } - //current time - Calendar cal = Calendar.getInstance(); - int year = cal.get(Calendar.YEAR); - int month = cal.get(Calendar.MONTH) + 1; - int day = cal.get(Calendar.DAY_OF_MONTH); - int hour = cal.get(Calendar.HOUR_OF_DAY); - int minutes = cal.get(Calendar.MINUTE); - int seconds = cal.get(Calendar.SECOND); - int millis = cal.get(Calendar.MILLISECOND); - - sb.append(year).append('-'); - sb.append(twoDigFmt.format(month)).append('-'); - sb.append(twoDigFmt.format(day)).append(' '); - sb.append(twoDigFmt.format(hour)).append(':'); - sb.append(twoDigFmt.format(minutes)).append(':'); - sb.append(twoDigFmt.format(seconds)).append('.'); - sb.append(threeDigFmt.format(millis)).append(' '); + if(!timestampDisabled) + { + //current time + Calendar cal = Calendar.getInstance(); + int year = cal.get(Calendar.YEAR); + int month = cal.get(Calendar.MONTH) + 1; + int day = cal.get(Calendar.DAY_OF_MONTH); + int hour = cal.get(Calendar.HOUR_OF_DAY); + int minutes = cal.get(Calendar.MINUTE); + int seconds = cal.get(Calendar.SECOND); + int millis = cal.get(Calendar.MILLISECOND); + + sb.append(year).append('-'); + sb.append(twoDigFmt.format(month)).append('-'); + sb.append(twoDigFmt.format(day)).append(' '); + sb.append(twoDigFmt.format(hour)).append(':'); + sb.append(twoDigFmt.format(minutes)).append(':'); + sb.append(twoDigFmt.format(seconds)).append('.'); + sb.append(threeDigFmt.format(millis)).append(' '); + } //log level sb.append(record.getLevel().getLocalizedName()); @@ -208,13 +221,33 @@ public class ScLogFormatter } /** + * Loads all config properties. + */ + private void loadConfigProperties() + { + loadProgramNameProperty(); + loadTimestampDisabledProperty(); + } + + /** + * Checks and loads timestamp disabled property if any. + */ + private static void loadTimestampDisabledProperty() + { + LogManager manager = LogManager.getLogManager(); + String cname = ScLogFormatter.class.getName(); + timestampDisabled = Boolean.parseBoolean( + manager.getProperty(cname + DISABLE_TIMESTAMP_PROPERTY)); + } + + /** * Load the programname property to be used in logs to identify Jitsi-based * application which produced the logs */ - private void loadProgramNameProperty() + private static void loadProgramNameProperty() { LogManager manager = LogManager.getLogManager(); - String cname = this.getClass().getName(); + String cname = ScLogFormatter.class.getName(); programName = manager.getProperty(cname + PROGRAM_NAME_PROPERTY); } -- cgit v1.1 From 8aa44efb2955ec1e7c03102cc0f917eae979704c Mon Sep 17 00:00:00 2001 From: damencho Date: Mon, 15 Feb 2016 12:08:55 -0500 Subject: Adds a property that can set autojoin by default on newly created rooms. --- .../impl/gui/main/chatroomslist/ChatRoomTableDialog.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomTableDialog.java b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomTableDialog.java index 0efb860..28f3e08 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomTableDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomTableDialog.java @@ -55,6 +55,13 @@ public class ChatRoomTableDialog "REMOVE_ROOM_ON_FIRST_JOIN_FAILED"; /** + * Whether we should make rooms autojoin by default. + */ + private static final String ENABLE_ROOM_AUTO_JOIN_ON_CREATION + = "net.java.sip.communicator.impl.gui.main.chatroomslist." + + "ENABLE_ROOM_AUTO_JOIN_ON_CREATION"; + + /** * The global/shared ChatRoomTableDialog currently showing. */ private static ChatRoomTableDialog chatRoomTableDialog; @@ -425,6 +432,12 @@ public class ChatRoomTableDialog chatRoomWrapper.getChatRoomID(), chatRoomWrapper.getChatRoomID(), chatRoomWrapper.getChatRoomName()); + + if(GuiActivator.getConfigurationService() + .getBoolean(ENABLE_ROOM_AUTO_JOIN_ON_CREATION, false)) + { + chatRoomWrapper.setAutoJoin(true); + } } String nickName = nicknameField.getText().trim(); -- cgit v1.1 From 5880a1a802e17519c251fbc2c4952b450d30ce22 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 17 Feb 2016 11:20:01 -0600 Subject: Adds HealthCheck IQ. --- .../extensions/colibri/ColibriIQProvider.java | 32 +++++++++++++++ .../jabber/extensions/colibri/HealthCheckIQ.java | 48 ++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index cc6d0c9..fe2a243 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -912,6 +912,38 @@ public class ColibriIQProvider } } } + else if (HealthCheckIQ.ELEMENT_NAME.equals(parser.getName()) + && HealthCheckIQ.NAMESPACE.equals(namespace)) + { + String rootElement = parser.getName(); + + iq = new HealthCheckIQ(); + + boolean done = false; + + while (!done) + { + switch (parser.next()) + { + case XmlPullParser.END_TAG: + { + String name = parser.getName(); + + if (rootElement.equals(name)) + { + done = true; + } + break; + } + + case XmlPullParser.TEXT: + { + // Parse some text here + break; + } + } + } + } else iq = null; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java new file mode 100644 index 0000000..1ce8a6f --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java @@ -0,0 +1,48 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; + +import org.jivesoftware.smack.packet.*; + +/** + * The health check IQ used to trigger health checks on the Jitsi Videobridge. + * + * @author Pawel Domas + */ +public class HealthCheckIQ + extends IQ +{ + /** + * Health check IQ element name. + */ + final static public String ELEMENT_NAME = "healthcheck"; + + /** + * XML namespace name for health check IQs. + */ + final static public String NAMESPACE = ColibriConferenceIQ.NAMESPACE; + + /** + * {@inheritDoc} + */ + @Override + public String getChildElementXML() + { + return "<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "' />"; + } +} -- cgit v1.1 From eecda70640791b035361fcda1cf15bbf57099e83 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 17 Feb 2016 11:52:05 -0600 Subject: Removes unused case statements from ColibriIQ parsing code. --- .../jabber/extensions/colibri/ColibriIQProvider.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index fe2a243..0507c1c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -837,12 +837,6 @@ public class ColibriIQProvider } break; } - - case XmlPullParser.TEXT: - { - // Parse some text here - break; - } } } } @@ -903,12 +897,6 @@ public class ColibriIQProvider } break; } - - case XmlPullParser.TEXT: - { - // Parse some text here - break; - } } } } @@ -935,12 +923,6 @@ public class ColibriIQProvider } break; } - - case XmlPullParser.TEXT: - { - // Parse some text here - break; - } } } } -- cgit v1.1 From 7ce859cdf5e892fcc3dda75a70b9a50fbf1550f3 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Mon, 22 Feb 2016 14:14:05 -0600 Subject: Adds URN_XMPP_IQ_VERSION constant. --- .../impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 2ea5c9c..f0b3fd1 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -152,6 +152,14 @@ public class ProtocolProviderServiceJabberImpl public static final String URN_IETF_RFC_3264 = "urn:ietf:rfc:3264"; /** + * http://xmpp.org/extensions/xep-0092.html Software Version. + * + */ + // Used in JVB + @SuppressWarnings("unused") + public static final String URN_XMPP_IQ_VERSION = "jabber:iq:version"; + + /** * Jingle's Discovery Info URN for "XEP-0294: Jingle RTP Header Extensions * Negotiation" support. */ -- cgit v1.1 From e9bd5ed5e3b94177198303dae8ef27c3fc8ab3eb Mon Sep 17 00:00:00 2001 From: paweldomas Date: Mon, 22 Feb 2016 14:33:05 -0600 Subject: Moves HealthCheckIQ to separate IQ provider. --- .../extensions/colibri/ColibriIQProvider.java | 26 ------ .../jabber/extensions/colibri/HealthCheckIQ.java | 48 ----------- .../jabber/extensions/health/HealthCheckIQ.java | 49 +++++++++++ .../extensions/health/HealthCheckIQProvider.java | 94 ++++++++++++++++++++++ 4 files changed, 143 insertions(+), 74 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 0507c1c..4298b3f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -900,32 +900,6 @@ public class ColibriIQProvider } } } - else if (HealthCheckIQ.ELEMENT_NAME.equals(parser.getName()) - && HealthCheckIQ.NAMESPACE.equals(namespace)) - { - String rootElement = parser.getName(); - - iq = new HealthCheckIQ(); - - boolean done = false; - - while (!done) - { - switch (parser.next()) - { - case XmlPullParser.END_TAG: - { - String name = parser.getName(); - - if (rootElement.equals(name)) - { - done = true; - } - break; - } - } - } - } else iq = null; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java deleted file mode 100644 index 1ce8a6f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/HealthCheckIQ.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; - -import org.jivesoftware.smack.packet.*; - -/** - * The health check IQ used to trigger health checks on the Jitsi Videobridge. - * - * @author Pawel Domas - */ -public class HealthCheckIQ - extends IQ -{ - /** - * Health check IQ element name. - */ - final static public String ELEMENT_NAME = "healthcheck"; - - /** - * XML namespace name for health check IQs. - */ - final static public String NAMESPACE = ColibriConferenceIQ.NAMESPACE; - - /** - * {@inheritDoc} - */ - @Override - public String getChildElementXML() - { - return "<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "' />"; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java new file mode 100644 index 0000000..661bb1b --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java @@ -0,0 +1,49 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.health; + +import org.jivesoftware.smack.packet.*; + +/** + * The health check IQ used to trigger health checks on the Jitsi Videobridge. + * + * @author Pawel Domas + */ +public class HealthCheckIQ + extends IQ +{ + /** + * Health check IQ element name. + */ + final static public String ELEMENT_NAME = "healthcheck"; + + /** + * XML namespace name for health check IQs. + */ + final static public String NAMESPACE + = "http://jitsi.org/protocol/healthcheck"; + + /** + * {@inheritDoc} + */ + @Override + public String getChildElementXML() + { + return "<" + ELEMENT_NAME + " xmlns='" + NAMESPACE + "' />"; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java new file mode 100644 index 0000000..9c2903d --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java @@ -0,0 +1,94 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.health; + +import net.java.sip.communicator.service.protocol.jabber.*; + +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.provider.*; + +import org.xmlpull.v1.*; + +/** + * The IQProvider for {@link HealthCheckIQ}. + * + * @author Pawel Domas + */ +public class HealthCheckIQProvider + implements IQProvider +{ + /** + * Registers HealthCheckIQProvider as an IQProvider + * in {@link AbstractSmackInteroperabilityLayer}. + */ + public static void registerIQProvider() + { + AbstractSmackInteroperabilityLayer smackInteropLayer = + AbstractSmackInteroperabilityLayer.getInstance(); + + // ColibriStatsIQ + smackInteropLayer.addIQProvider( + HealthCheckIQ.ELEMENT_NAME, + HealthCheckIQ.NAMESPACE, + new HealthCheckIQProvider()); + } + + /** + * Parses HealthCheckIQ. + * + * {@inheritDoc} + */ + @Override + public IQ parseIQ(XmlPullParser parser) + throws Exception + { + String namespace = parser.getNamespace(); + IQ iq; + + if (HealthCheckIQ.ELEMENT_NAME.equals(parser.getName()) + && HealthCheckIQ.NAMESPACE.equals(namespace)) + { + String rootElement = parser.getName(); + + iq = new HealthCheckIQ(); + + boolean done = false; + + while (!done) + { + switch (parser.next()) + { + case XmlPullParser.END_TAG: + { + String name = parser.getName(); + + if (rootElement.equals(name)) + { + done = true; + } + break; + } + } + } + } + else + iq = null; + + return iq; + } +} -- cgit v1.1 From 655874e96ea0b28ade82d212cb00f3a76751e288 Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Tue, 23 Feb 2016 14:36:54 -0600 Subject: Converts CRLF line endings to LF, as suggested by @champtar. The conversion was done with the script provided by @champtar on a linux machine: find -name '*.java' | xargs file | grep 'CRLF, LF' | cut -d ':' -f1 | xargs -n1 dos2unix --- .../impl/dns/ConfigurableDnssecResolver.java | 754 ++--- .../sip/communicator/impl/dns/SecureMessage.java | 176 +- .../communicator/impl/dns/SecureResolveMode.java | 76 +- .../java/sip/communicator/impl/dns/UnboundApi.java | 446 +-- .../communicator/impl/dns/UnboundException.java | 52 +- .../sip/communicator/impl/dns/UnboundResolver.java | 788 ++--- .../sip/communicator/impl/dns/UnboundResult.java | 224 +- .../main/account/AccountsConfigurationPanel.java | 552 ++-- .../impl/gui/main/call/CallDialog.java | 1234 ++++---- .../impl/gui/main/call/CallTransferHandler.java | 548 ++-- .../impl/gui/main/call/FullScreenLayout.java | 348 +-- .../impl/gui/main/call/SecurityPanel.java | 230 +- .../impl/gui/main/call/TransferCallDialog.java | 276 +- .../call/conference/ConferenceInviteDialog.java | 1136 +++---- .../call/conference/VideoConferenceCallPanel.java | 2786 ++++++++--------- .../gui/main/chat/ChatSessionChangeListener.java | 60 +- .../main/chat/conference/ChatContactListModel.java | 466 +-- .../chat/conference/ConferenceChatManager.java | 2776 ++++++++--------- .../chatroomslist/ServerChatRoomsChoiceDialog.java | 190 +- .../impl/gui/main/contactlist/PresenceFilter.java | 702 ++--- .../main/menus/MacOSXPreferencesRegistration.java | 56 +- .../gui/main/menus/MacOSXQuitRegistration.java | 132 +- .../impl/gui/utils/PluginContainer.java | 632 ++-- .../sip/communicator/impl/hid/HIDServiceImpl.java | 442 +-- .../impl/ldap/LdapSSLSocketFactoryDelegate.java | 146 +- .../impl/muc/BaseChatRoomSourceContact.java | 278 +- .../sip/communicator/impl/muc/ChatRoomQuery.java | 1080 +++---- .../impl/muc/ChatRoomSourceContact.java | 222 +- .../impl/muc/MUCCustomContactActionService.java | 1686 +++++----- .../sip/communicator/impl/muc/MUCServiceImpl.java | 2230 ++++++------- .../communicator/impl/muc/ServerChatRoomQuery.java | 658 ++-- .../neomedia/DeviceConfigurationComboBoxModel.java | 908 +++--- .../neomedia/EncodingConfigurationTableModel.java | 540 ++-- .../communicator/impl/osdependent/SystemTray.java | 398 +-- .../communicator/impl/osdependent/TrayIcon.java | 792 ++--- .../impl/protocol/jabber/CallPeerJabberImpl.java | 3290 ++++++++++---------- ...perationSetTelephonyConferencingJabberImpl.java | 1166 +++---- .../jabber/OperationSetVideoBridgeImpl.java | 560 ++-- .../protocol/jabber/RawUdpTransportManager.java | 1054 +++---- .../jabber/TransportManagerJabberImpl.java | 1922 ++++++------ .../extensions/colibri/ColibriStreamConnector.java | 144 +- .../jingle/CandidatePacketExtension.java | 878 +++--- .../protocol/sip/net/ManualProxyConnection.java | 226 +- .../impl/sysactivity/DBusNetworkManager.java | 262 +- .../sysactivity/NetworkManagerListenerImpl.java | 324 +- .../impl/sysactivity/SysActivityActivator.java | 198 +- .../SystemActivityNotificationsServiceImpl.java | 1274 ++++---- .../plugin/accountinfo/AccountInfoActivator.java | 322 +- .../plugin/accountinfo/AccountInfoPanel.java | 694 ++--- .../communicator/plugin/accountinfo/Resources.java | 126 +- .../communicator/plugin/addrbook/PtrCallback.java | 42 +- .../msoutlook/DefaultMailClientMessageDialog.java | 184 +- .../msoutlook/MsOutlookMAPIHResultException.java | 216 +- .../communicator/plugin/branding/AboutWindow.java | 942 +++--- .../branding/AboutWindowPluginComponent.java | 174 +- .../communicator/plugin/branding/Constants.java | 126 +- .../plugin/branding/JitsiWarningWindow.java | 374 +-- .../plugin/branding/MacOSXAboutRegistration.java | 64 +- .../plugin/branding/StyledHTMLEditorPane.java | 124 +- .../plugin/certconfig/CertConfigEntryDialog.java | 1142 +++---- .../plugin/certconfig/CertConfigPanel.java | 530 ++-- .../plugin/certconfig/CertConfigTableModel.java | 194 +- .../contactinfo/ContactInfoContactPanel.java | 392 +-- .../contactinfo/ContactInfoDetailsPanel.java | 1352 ++++---- .../plugin/contactinfo/ContactInfoDialog.java | 172 +- .../plugin/contactinfo/ContactInfoMenuItem.java | 326 +- .../communicator/plugin/contactinfo/Resources.java | 154 +- .../plugin/desktoputil/ColoredDefaultText.java | 80 +- .../plugin/desktoputil/SIPCommCheckBox.java | 86 +- .../plugin/desktoputil/SIPCommRadioButton.java | 86 +- .../chat/ChatRoomDestroyReasonDialog.java | 346 +- .../chat/ChatRoomJoinOptionsDialog.java | 344 +- .../FacebookAccRegWizzActivator.java | 394 +-- .../FacebookAccountRegistrationWizard.java | 568 ++-- .../generalconfig/autoaway/AutoAwayWatcher.java | 920 +++--- .../plugin/generalconfig/autoaway/Preferences.java | 262 +- .../GoogleTalkAccRegWizzActivator.java | 322 +- .../GoogleTalkAccountRegistrationWizard.java | 504 +-- .../iptelaccregwizz/IptelAccRegWizzActivator.java | 304 +- .../IptelAccountRegistrationWizard.java | 406 +-- .../globalchooser/GlobalShortcutDialog.java | 974 +++--- .../communicator/plugin/otr/OtrConfigurator.java | 338 +- .../communicator/plugin/otr/ScOtrKeyManager.java | 82 +- .../plugin/otr/ScOtrKeyManagerImpl.java | 618 ++-- .../plugin/otr/ScOtrKeyManagerListener.java | 26 +- .../sip/communicator/plugin/otr/ScSessionID.java | 162 +- .../PhoneNumberContactSource.java | 154 +- .../plugin/profiler4j/SettingsWindowMenuEntry.java | 112 +- .../InitialAccountRegistrationFrame.java | 1468 ++++----- .../plugin/simpleaccreg/Resources.java | 180 +- .../Sip2SipAccRegWizzActivator.java | 240 +- .../Sip2SipAccountRegistrationWizard.java | 506 +-- .../spellcheck/SpellCheckerConfigDialog.java | 842 ++--- .../plugin/thunderbird/ThunderbirdActivator.java | 336 +- .../thunderbird/ThunderbirdContactQuery.java | 530 ++-- .../update/CheckForUpdatesMenuItemComponent.java | 150 +- .../plugin/update/UpdateActivator.java | 608 ++-- .../certificate/CertificateConfigEntry.java | 340 +- .../service/certificate/CertificateMatcher.java | 44 +- .../service/certificate/CertificateService.java | 526 ++-- .../service/certificate/KeyStoreType.java | 124 +- .../contactsource/AbstractContactQuery.java | 568 ++-- .../service/contactsource/AsyncContactQuery.java | 816 ++--- .../contactsource/AsyncContactSourceService.java | 136 +- .../contactsource/GenericSourceContact.java | 586 ++-- .../communicator/service/dns/DnssecException.java | 50 +- .../service/dns/DnssecRuntimeException.java | 60 +- .../communicator/service/gui/AlertUIService.java | 246 +- .../service/gui/ChatLinkClickedListener.java | 38 +- .../service/gui/LazyConfigurationForm.java | 436 +-- .../service/gui/internal/GuiServiceActivator.java | 152 +- .../service/muc/ChatRoomPresenceStatus.java | 140 +- .../sip/communicator/service/muc/MUCService.java | 792 ++--- .../notification/CommandNotificationAction.java | 74 +- .../service/notification/NotificationAction.java | 192 +- .../service/notification/NotificationData.java | 298 +- .../PopupMessageNotificationAction.java | 212 +- .../notification/SoundNotificationAction.java | 356 +-- .../service/protocol/AccountManagerUtils.java | 332 +- .../service/protocol/CallConference.java | 1858 +++++------ .../protocol/OperationSetSecureSDesTelephony.java | 26 +- .../protocol/OperationSetSecureZrtpTelephony.java | 26 +- .../service/protocol/PhoneNumberI18nService.java | 94 +- .../protocol/ProtocolProviderActivator.java | 586 ++-- .../service/protocol/ProtocolProviderFactory.java | 2600 ++++++++-------- .../protocol/event/AccountManagerEvent.java | 168 +- .../protocol/event/AccountManagerListener.java | 52 +- .../protocol/media/MediaAwareCallConference.java | 1242 ++++---- .../service/protocol/media/MediaAwareCallPeer.java | 2490 +++++++-------- .../service/protocol/media/TransportManager.java | 1736 +++++------ .../communicator/service/resources/ImageID.java | 40 +- .../resources/ResourceManagementServiceUtils.java | 144 +- .../sysactivity/SystemActivityChangeListener.java | 52 +- .../SystemActivityNotificationsService.java | 138 +- .../sysactivity/event/SystemActivityEvent.java | 268 +- .../java/sip/communicator/util/GenericBuffer.java | 230 +- .../util/account/AccountStatusUtils.java | 386 +-- .../communicator/util/account/AccountUtils.java | 606 ++-- .../communicator/util/account/LoginManager.java | 1150 +++---- .../communicator/util/account/LoginRenderer.java | 182 +- 140 files changed, 37754 insertions(+), 37754 deletions(-) diff --git a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java index af8d465..93bc71e 100644 --- a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java +++ b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,379 +15,379 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.service.notification.*; -import net.java.sip.communicator.util.Logger; -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; -import org.jitsi.util.*; -import org.xbill.DNS.*; - -/** - * Resolver that wraps a DNSSEC capable resolver and handles validation - * failures according to the user's settings. - * - * @author Ingo Bauersachs - */ -public class ConfigurableDnssecResolver - extends UnboundResolver -{ - private final static Logger logger - = Logger.getLogger(ConfigurableDnssecResolver.class); - - /** - * Name of the property that defines the default DNSSEC validation - * behavior. - */ - public final static String PNAME_DNSSEC_VALIDATION_MODE - = "net.java.sip.communicator.util.dns.DNSSEC_VALIDATION_MODE"; - - /** - * Default value of {@link #PNAME_DNSSEC_VALIDATION_MODE} - */ - public final static String PNAME_BASE_DNSSEC_PIN - = "net.java.sip.communicator.util.dns.pin"; - - final static String EVENT_TYPE = "DNSSEC_NOTIFICATION"; - - private ConfigurationService config - = DnsUtilActivator.getConfigurationService(); - private ResourceManagementService R - = DnsUtilActivator.getResources(); - private Map lastNotifications - = new HashMap(); - - /** - * Creates a new instance of this class. Tries to use the system's - * default forwarders. - */ - public ConfigurableDnssecResolver() - { - super(); - reset(); - Lookup.setDefaultResolver(this); - - DnsUtilActivator.getNotificationService(). - registerDefaultNotificationForEvent( - ConfigurableDnssecResolver.EVENT_TYPE, - NotificationAction.ACTION_POPUP_MESSAGE, - null, null); - } - - /** - * Inspects a DNS answer message and handles validation results according to - * the user's preferences. - * - * @throws DnssecRuntimeException when the validation failed and the user - * did not choose to ignore it. - */ - @Override - protected void validateMessage(SecureMessage msg) - throws DnssecRuntimeException - { - //--------------------------------------------------------------------- - // || 1 | 2 | 3 | 4 | 5 - //--------------------------------------------------------------------- - // Sec. | Bog. || Ign. | Sec.Only | Sec.Or.Unsig | Warn.Bog | WarnAll - //--------------------------------------------------------------------- - //a) 1 | 0 || ok | ok | ok | ok | ok - //b) 0 | 1 || ok | nok | nok | ask | ask - //c) 0 | 0 || ok | nok | ok | ok | ask - //--------------------------------------------------------------------- - - String fqdn = msg.getQuestion().getName().toString(); - String type = Type.string(msg.getQuestion().getType()); - String propName = createPropNameUnsigned(fqdn, type); - SecureResolveMode defaultAction = Enum.valueOf(SecureResolveMode.class, - config.getString( - PNAME_DNSSEC_VALIDATION_MODE, - SecureResolveMode.WarnIfBogus.name() - ) - ); - SecureResolveMode pinned = Enum.valueOf(SecureResolveMode.class, - config.getString( - propName, - defaultAction.name() - ) - ); - - //create default entry - if(pinned == defaultAction) - config.setProperty(propName, pinned.name()); - - //check domain policy - - //[abc]1, a[2-5] - if(pinned == SecureResolveMode.IgnoreDnssec || msg.isSecure()) - return; - - if( - //b2, c2 - (pinned == SecureResolveMode.SecureOnly && !msg.isSecure()) - || - //b3 - (pinned == SecureResolveMode.SecureOrUnsigned && msg.isBogus()) - ) - { - String text = getExceptionMessage(msg); - Date last = lastNotifications.get(text); - if(last == null - //wait at least 5 minutes before showing the same info again - || last.before(new Date(new Date().getTime() - 1000*60*5))) - { - DnsUtilActivator.getNotificationService().fireNotification( - EVENT_TYPE, - R.getI18NString("util.dns.INSECURE_ANSWER_TITLE"), - text, - null); - lastNotifications.put(text, new Date()); - } - throw new DnssecRuntimeException(text); - } - - //c3 - if(pinned == SecureResolveMode.SecureOrUnsigned && !msg.isBogus()) - return; - - //c4 - if(pinned == SecureResolveMode.WarnIfBogus && !msg.isBogus()) - return; - - //b4, b5, c5 - String reason = msg.isBogus() - ? R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_BOGUS", - new String[]{fqdn, msg.getBogusReason()}) - : R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_UNSIGNED", - new String[]{type, fqdn}); - DnssecDialog dlg = new DnssecDialog(fqdn, reason); - dlg.setVisible(true); - DnssecDialogResult result = dlg.getResult(); - switch(result) - { - case Accept: - break; - case Deny: - throw new DnssecRuntimeException(getExceptionMessage(msg)); - case AlwaysAccept: - if(msg.isBogus()) - config.setProperty(propName, - SecureResolveMode.IgnoreDnssec.name()); - else - config.setProperty(propName, - SecureResolveMode.WarnIfBogus.name()); - break; - case AlwaysDeny: - config.setProperty(propName, SecureResolveMode.SecureOnly); - throw new DnssecRuntimeException(getExceptionMessage(msg)); - } - } - - /** - * Defines the return code from the DNSSEC verification dialog. - */ - private enum DnssecDialogResult - { - /** The DNS result shall be accepted. */ - Accept, - /** The result shall be rejected. */ - Deny, - /** The result shall be accepted permanently. */ - AlwaysAccept, - /** - * The result shall be rejected automatically unless it is valid - * according to DNSSEC. - */ - AlwaysDeny - } - - /** - * Dialog to ask and warn the user if he wants to continue to accept an - * invalid dnssec result. - */ - private class DnssecDialog extends SIPCommDialog implements ActionListener - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - //UI controls - private JPanel pnlAdvanced; - private JPanel pnlStandard; - private final String domain; - private final String reason; - private JButton cmdAck; - private JButton cmdShowDetails; - - //state - private DnssecDialogResult result = DnssecDialogResult.Deny; - - /** - * Creates a new instance of this class. - * @param domain The FQDN of the domain that failed. - * @param reason String describing why the validation failed. - */ - public DnssecDialog(String domain, String reason) - { - super(false); - setModal(true); - this.domain = domain; - this.reason = reason; - initComponents(); - } - - /** - * Creates the UI controls - */ - private void initComponents() - { - setLayout(new BorderLayout(15, 15)); - setTitle(R.getI18NString("util.dns.INSECURE_ANSWER_TITLE")); - - // warning text - JLabel imgWarning = - new JLabel(R.getImage("service.gui.icons.WARNING_ICON")); - imgWarning.setBorder(BorderFactory - .createEmptyBorder(10, 10, 10, 10)); - add(imgWarning, BorderLayout.WEST); - JLabel lblWarning = new JLabel( - R.getI18NString("util.dns.DNSSEC_WARNING", new String[]{ - R.getSettingsString("service.gui.APPLICATION_NAME"), - domain - }) - ); - add(lblWarning, BorderLayout.CENTER); - - //standard panel (deny option) - cmdAck = new JButton(R.getI18NString("service.gui.OK")); - cmdAck.addActionListener(this); - - cmdShowDetails = new JButton( - R.getI18NString("util.dns.DNSSEC_ADVANCED_OPTIONS")); - cmdShowDetails.addActionListener(this); - - pnlStandard = new TransparentPanel(new BorderLayout()); - pnlStandard.setBorder(BorderFactory - .createEmptyBorder(10, 10, 10, 10)); - pnlStandard.add(cmdShowDetails, BorderLayout.WEST); - pnlStandard.add(cmdAck, BorderLayout.EAST); - add(pnlStandard, BorderLayout.SOUTH); - - //advanced panel - pnlAdvanced = new TransparentPanel(new BorderLayout()); - JPanel pnlAdvancedButtons = new TransparentPanel( - new FlowLayout(FlowLayout.RIGHT)); - pnlAdvancedButtons.setBorder(BorderFactory - .createEmptyBorder(10, 10, 10, 10)); - pnlAdvanced.add(pnlAdvancedButtons, BorderLayout.EAST); - for(DnssecDialogResult r : DnssecDialogResult.values()) - { - JButton cmd = new JButton(R.getI18NString( - "net.java.sip.communicator.util.dns." - + "ConfigurableDnssecResolver$DnssecDialogResult." - + r.name())); - cmd.setActionCommand(r.name()); - cmd.addActionListener(this); - pnlAdvancedButtons.add(cmd); - } - JLabel lblReason = new JLabel(reason); - lblReason.setBorder(BorderFactory - .createEmptyBorder(10, 10, 10, 10)); - pnlAdvanced.add(lblReason, BorderLayout.NORTH); - } - - /** - * Handles the events coming from the buttons. - */ - public void actionPerformed(ActionEvent e) - { - if(e.getSource() == cmdAck) - { - result = DnssecDialogResult.Deny; - dispose(); - } - else if(e.getSource() == cmdShowDetails) - { - getContentPane().remove(pnlStandard); - add(pnlAdvanced, BorderLayout.SOUTH); - pack(); - } - else - { - result = Enum.valueOf(DnssecDialogResult.class, - e.getActionCommand()); - dispose(); - } - } - - /** - * Gets the option that user has chosen. - * @return the option that user has chosen. - */ - public DnssecDialogResult getResult() - { - return result; - } - } - - private String getExceptionMessage(SecureMessage msg) - { - return msg.getBogusReason() == null - ? R.getI18NString( - "util.dns.INSECURE_ANSWER_MESSAGE_NO_REASON", - new String[]{msg.getQuestion().getName().toString()} - ) - : R.getI18NString( - "util.dns.INSECURE_ANSWER_MESSAGE_REASON", - new String[]{msg.getQuestion().getName().toString(), - //TODO parse bogus reason text and translate - msg.getBogusReason()} - ); - } - - private String createPropNameUnsigned(String fqdn, String type) - { - return PNAME_BASE_DNSSEC_PIN + "." + fqdn.replace(".", "__"); - } - - /** - * Reloads the configuration of forwarders and trust anchors. - */ - @Override - public void reset() - { - String forwarders = DnsUtilActivator.getConfigurationService() - .getString(DnsUtilActivator.PNAME_DNSSEC_NAMESERVERS); - if(!StringUtils.isNullOrEmpty(forwarders, true)) - { - if(logger.isTraceEnabled()) - { - logger.trace("Setting DNSSEC forwarders to: " - + Arrays.toString(forwarders.split(","))); - } - super.setForwarders(forwarders.split(",")); - } - - for(int i = 1;;i++) - { - String anchor = DnsUtilActivator.getResources().getSettingsString( - "net.java.sip.communicator.util.dns.DS_ROOT." + i); - if(anchor == null) - break; - clearTrustAnchors(); - addTrustAnchor(anchor); - if(logger.isTraceEnabled()) - logger.trace("Loaded trust anchor " + anchor); - } - } -} +package net.java.sip.communicator.impl.dns; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.dns.*; +import net.java.sip.communicator.service.notification.*; +import net.java.sip.communicator.util.Logger; +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; +import org.jitsi.util.*; +import org.xbill.DNS.*; + +/** + * Resolver that wraps a DNSSEC capable resolver and handles validation + * failures according to the user's settings. + * + * @author Ingo Bauersachs + */ +public class ConfigurableDnssecResolver + extends UnboundResolver +{ + private final static Logger logger + = Logger.getLogger(ConfigurableDnssecResolver.class); + + /** + * Name of the property that defines the default DNSSEC validation + * behavior. + */ + public final static String PNAME_DNSSEC_VALIDATION_MODE + = "net.java.sip.communicator.util.dns.DNSSEC_VALIDATION_MODE"; + + /** + * Default value of {@link #PNAME_DNSSEC_VALIDATION_MODE} + */ + public final static String PNAME_BASE_DNSSEC_PIN + = "net.java.sip.communicator.util.dns.pin"; + + final static String EVENT_TYPE = "DNSSEC_NOTIFICATION"; + + private ConfigurationService config + = DnsUtilActivator.getConfigurationService(); + private ResourceManagementService R + = DnsUtilActivator.getResources(); + private Map lastNotifications + = new HashMap(); + + /** + * Creates a new instance of this class. Tries to use the system's + * default forwarders. + */ + public ConfigurableDnssecResolver() + { + super(); + reset(); + Lookup.setDefaultResolver(this); + + DnsUtilActivator.getNotificationService(). + registerDefaultNotificationForEvent( + ConfigurableDnssecResolver.EVENT_TYPE, + NotificationAction.ACTION_POPUP_MESSAGE, + null, null); + } + + /** + * Inspects a DNS answer message and handles validation results according to + * the user's preferences. + * + * @throws DnssecRuntimeException when the validation failed and the user + * did not choose to ignore it. + */ + @Override + protected void validateMessage(SecureMessage msg) + throws DnssecRuntimeException + { + //--------------------------------------------------------------------- + // || 1 | 2 | 3 | 4 | 5 + //--------------------------------------------------------------------- + // Sec. | Bog. || Ign. | Sec.Only | Sec.Or.Unsig | Warn.Bog | WarnAll + //--------------------------------------------------------------------- + //a) 1 | 0 || ok | ok | ok | ok | ok + //b) 0 | 1 || ok | nok | nok | ask | ask + //c) 0 | 0 || ok | nok | ok | ok | ask + //--------------------------------------------------------------------- + + String fqdn = msg.getQuestion().getName().toString(); + String type = Type.string(msg.getQuestion().getType()); + String propName = createPropNameUnsigned(fqdn, type); + SecureResolveMode defaultAction = Enum.valueOf(SecureResolveMode.class, + config.getString( + PNAME_DNSSEC_VALIDATION_MODE, + SecureResolveMode.WarnIfBogus.name() + ) + ); + SecureResolveMode pinned = Enum.valueOf(SecureResolveMode.class, + config.getString( + propName, + defaultAction.name() + ) + ); + + //create default entry + if(pinned == defaultAction) + config.setProperty(propName, pinned.name()); + + //check domain policy + + //[abc]1, a[2-5] + if(pinned == SecureResolveMode.IgnoreDnssec || msg.isSecure()) + return; + + if( + //b2, c2 + (pinned == SecureResolveMode.SecureOnly && !msg.isSecure()) + || + //b3 + (pinned == SecureResolveMode.SecureOrUnsigned && msg.isBogus()) + ) + { + String text = getExceptionMessage(msg); + Date last = lastNotifications.get(text); + if(last == null + //wait at least 5 minutes before showing the same info again + || last.before(new Date(new Date().getTime() - 1000*60*5))) + { + DnsUtilActivator.getNotificationService().fireNotification( + EVENT_TYPE, + R.getI18NString("util.dns.INSECURE_ANSWER_TITLE"), + text, + null); + lastNotifications.put(text, new Date()); + } + throw new DnssecRuntimeException(text); + } + + //c3 + if(pinned == SecureResolveMode.SecureOrUnsigned && !msg.isBogus()) + return; + + //c4 + if(pinned == SecureResolveMode.WarnIfBogus && !msg.isBogus()) + return; + + //b4, b5, c5 + String reason = msg.isBogus() + ? R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_BOGUS", + new String[]{fqdn, msg.getBogusReason()}) + : R.getI18NString("util.dns.DNSSEC_ADVANCED_REASON_UNSIGNED", + new String[]{type, fqdn}); + DnssecDialog dlg = new DnssecDialog(fqdn, reason); + dlg.setVisible(true); + DnssecDialogResult result = dlg.getResult(); + switch(result) + { + case Accept: + break; + case Deny: + throw new DnssecRuntimeException(getExceptionMessage(msg)); + case AlwaysAccept: + if(msg.isBogus()) + config.setProperty(propName, + SecureResolveMode.IgnoreDnssec.name()); + else + config.setProperty(propName, + SecureResolveMode.WarnIfBogus.name()); + break; + case AlwaysDeny: + config.setProperty(propName, SecureResolveMode.SecureOnly); + throw new DnssecRuntimeException(getExceptionMessage(msg)); + } + } + + /** + * Defines the return code from the DNSSEC verification dialog. + */ + private enum DnssecDialogResult + { + /** The DNS result shall be accepted. */ + Accept, + /** The result shall be rejected. */ + Deny, + /** The result shall be accepted permanently. */ + AlwaysAccept, + /** + * The result shall be rejected automatically unless it is valid + * according to DNSSEC. + */ + AlwaysDeny + } + + /** + * Dialog to ask and warn the user if he wants to continue to accept an + * invalid dnssec result. + */ + private class DnssecDialog extends SIPCommDialog implements ActionListener + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + //UI controls + private JPanel pnlAdvanced; + private JPanel pnlStandard; + private final String domain; + private final String reason; + private JButton cmdAck; + private JButton cmdShowDetails; + + //state + private DnssecDialogResult result = DnssecDialogResult.Deny; + + /** + * Creates a new instance of this class. + * @param domain The FQDN of the domain that failed. + * @param reason String describing why the validation failed. + */ + public DnssecDialog(String domain, String reason) + { + super(false); + setModal(true); + this.domain = domain; + this.reason = reason; + initComponents(); + } + + /** + * Creates the UI controls + */ + private void initComponents() + { + setLayout(new BorderLayout(15, 15)); + setTitle(R.getI18NString("util.dns.INSECURE_ANSWER_TITLE")); + + // warning text + JLabel imgWarning = + new JLabel(R.getImage("service.gui.icons.WARNING_ICON")); + imgWarning.setBorder(BorderFactory + .createEmptyBorder(10, 10, 10, 10)); + add(imgWarning, BorderLayout.WEST); + JLabel lblWarning = new JLabel( + R.getI18NString("util.dns.DNSSEC_WARNING", new String[]{ + R.getSettingsString("service.gui.APPLICATION_NAME"), + domain + }) + ); + add(lblWarning, BorderLayout.CENTER); + + //standard panel (deny option) + cmdAck = new JButton(R.getI18NString("service.gui.OK")); + cmdAck.addActionListener(this); + + cmdShowDetails = new JButton( + R.getI18NString("util.dns.DNSSEC_ADVANCED_OPTIONS")); + cmdShowDetails.addActionListener(this); + + pnlStandard = new TransparentPanel(new BorderLayout()); + pnlStandard.setBorder(BorderFactory + .createEmptyBorder(10, 10, 10, 10)); + pnlStandard.add(cmdShowDetails, BorderLayout.WEST); + pnlStandard.add(cmdAck, BorderLayout.EAST); + add(pnlStandard, BorderLayout.SOUTH); + + //advanced panel + pnlAdvanced = new TransparentPanel(new BorderLayout()); + JPanel pnlAdvancedButtons = new TransparentPanel( + new FlowLayout(FlowLayout.RIGHT)); + pnlAdvancedButtons.setBorder(BorderFactory + .createEmptyBorder(10, 10, 10, 10)); + pnlAdvanced.add(pnlAdvancedButtons, BorderLayout.EAST); + for(DnssecDialogResult r : DnssecDialogResult.values()) + { + JButton cmd = new JButton(R.getI18NString( + "net.java.sip.communicator.util.dns." + + "ConfigurableDnssecResolver$DnssecDialogResult." + + r.name())); + cmd.setActionCommand(r.name()); + cmd.addActionListener(this); + pnlAdvancedButtons.add(cmd); + } + JLabel lblReason = new JLabel(reason); + lblReason.setBorder(BorderFactory + .createEmptyBorder(10, 10, 10, 10)); + pnlAdvanced.add(lblReason, BorderLayout.NORTH); + } + + /** + * Handles the events coming from the buttons. + */ + public void actionPerformed(ActionEvent e) + { + if(e.getSource() == cmdAck) + { + result = DnssecDialogResult.Deny; + dispose(); + } + else if(e.getSource() == cmdShowDetails) + { + getContentPane().remove(pnlStandard); + add(pnlAdvanced, BorderLayout.SOUTH); + pack(); + } + else + { + result = Enum.valueOf(DnssecDialogResult.class, + e.getActionCommand()); + dispose(); + } + } + + /** + * Gets the option that user has chosen. + * @return the option that user has chosen. + */ + public DnssecDialogResult getResult() + { + return result; + } + } + + private String getExceptionMessage(SecureMessage msg) + { + return msg.getBogusReason() == null + ? R.getI18NString( + "util.dns.INSECURE_ANSWER_MESSAGE_NO_REASON", + new String[]{msg.getQuestion().getName().toString()} + ) + : R.getI18NString( + "util.dns.INSECURE_ANSWER_MESSAGE_REASON", + new String[]{msg.getQuestion().getName().toString(), + //TODO parse bogus reason text and translate + msg.getBogusReason()} + ); + } + + private String createPropNameUnsigned(String fqdn, String type) + { + return PNAME_BASE_DNSSEC_PIN + "." + fqdn.replace(".", "__"); + } + + /** + * Reloads the configuration of forwarders and trust anchors. + */ + @Override + public void reset() + { + String forwarders = DnsUtilActivator.getConfigurationService() + .getString(DnsUtilActivator.PNAME_DNSSEC_NAMESERVERS); + if(!StringUtils.isNullOrEmpty(forwarders, true)) + { + if(logger.isTraceEnabled()) + { + logger.trace("Setting DNSSEC forwarders to: " + + Arrays.toString(forwarders.split(","))); + } + super.setForwarders(forwarders.split(",")); + } + + for(int i = 1;;i++) + { + String anchor = DnsUtilActivator.getResources().getSettingsString( + "net.java.sip.communicator.util.dns.DS_ROOT." + i); + if(anchor == null) + break; + clearTrustAnchors(); + addTrustAnchor(anchor); + if(logger.isTraceEnabled()) + logger.trace("Loaded trust anchor " + anchor); + } + } +} diff --git a/src/net/java/sip/communicator/impl/dns/SecureMessage.java b/src/net/java/sip/communicator/impl/dns/SecureMessage.java index 7fe9b68..b2fa0d4 100644 --- a/src/net/java/sip/communicator/impl/dns/SecureMessage.java +++ b/src/net/java/sip/communicator/impl/dns/SecureMessage.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,90 +15,90 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -import java.io.*; - -import org.xbill.DNS.*; - -/** - * DNS Message that adds DNSSEC validation information. - * - * @author Ingo Bauersachs - */ -public class SecureMessage - extends Message -{ - private boolean secure; - private boolean bogus; - private String bogusReason; - - /** - * Creates a new instance of this class based on data received from an - * Unbound resolve. - * - * @param msg The answer of the Unbound resolver. - * @throws IOException - */ - public SecureMessage(UnboundResult msg) throws IOException - { - super(msg.answerPacket); - secure = msg.secure; - bogus = msg.bogus; - bogusReason = msg.whyBogus; - } - - /** - * Indicates whether the answer is secure. - * @return True, if the result is validated securely. - */ - public boolean isSecure() - { - return secure; - } - - /** - * Indicates if there was a validation failure. - * - * @return If the result was not secure (secure == false), and this result - * is due to a security failure, bogus is true. - */ - public boolean isBogus() - { - return bogus; - } - - /** - * If the result is bogus this contains a string that describes the failure. - * - * @return string that describes the failure. - */ - public String getBogusReason() - { - return bogusReason; - } - - /** - * Converts the Message to a String. The fields secure, bogus and whyBogus - * are append as a comment. - */ - @Override - public String toString() - { - StringBuilder s = new StringBuilder(super.toString()); - s.append('\n'); - s.append(";; Secure: "); - s.append(secure); - s.append('\n'); - s.append(";; Bogus: "); - s.append(bogus); - s.append('\n'); - if(bogus) - { - s.append(";; Reason: "); - s.append(bogusReason); - s.append('\n'); - } - return s.toString(); - } -} +package net.java.sip.communicator.impl.dns; + +import java.io.*; + +import org.xbill.DNS.*; + +/** + * DNS Message that adds DNSSEC validation information. + * + * @author Ingo Bauersachs + */ +public class SecureMessage + extends Message +{ + private boolean secure; + private boolean bogus; + private String bogusReason; + + /** + * Creates a new instance of this class based on data received from an + * Unbound resolve. + * + * @param msg The answer of the Unbound resolver. + * @throws IOException + */ + public SecureMessage(UnboundResult msg) throws IOException + { + super(msg.answerPacket); + secure = msg.secure; + bogus = msg.bogus; + bogusReason = msg.whyBogus; + } + + /** + * Indicates whether the answer is secure. + * @return True, if the result is validated securely. + */ + public boolean isSecure() + { + return secure; + } + + /** + * Indicates if there was a validation failure. + * + * @return If the result was not secure (secure == false), and this result + * is due to a security failure, bogus is true. + */ + public boolean isBogus() + { + return bogus; + } + + /** + * If the result is bogus this contains a string that describes the failure. + * + * @return string that describes the failure. + */ + public String getBogusReason() + { + return bogusReason; + } + + /** + * Converts the Message to a String. The fields secure, bogus and whyBogus + * are append as a comment. + */ + @Override + public String toString() + { + StringBuilder s = new StringBuilder(super.toString()); + s.append('\n'); + s.append(";; Secure: "); + s.append(secure); + s.append('\n'); + s.append(";; Bogus: "); + s.append(bogus); + s.append('\n'); + if(bogus) + { + s.append(";; Reason: "); + s.append(bogusReason); + s.append('\n'); + } + return s.toString(); + } +} diff --git a/src/net/java/sip/communicator/impl/dns/SecureResolveMode.java b/src/net/java/sip/communicator/impl/dns/SecureResolveMode.java index 8c99836..b74f1c6 100644 --- a/src/net/java/sip/communicator/impl/dns/SecureResolveMode.java +++ b/src/net/java/sip/communicator/impl/dns/SecureResolveMode.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,40 +15,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -/** - * Defines how DNSSEC validation errors should be handled. - * - * @author Ingo Bauersachs - */ -public enum SecureResolveMode -{ - /** - * Any DNSSEC data is completely ignored. - */ - IgnoreDnssec, - - /** - * The result of a query is only returned if it validated successfully. - */ - SecureOnly, - - /** - * The result of a query is returned if it validated successfully or when - * the zone is unsigned. - */ - SecureOrUnsigned, - - /** - * If the result of a query is bogus (manipulated, incorrect), the user is - * to be asked how to proceed. - */ - WarnIfBogus, - - /** - * If the result of a query is bogus (manipulated, incorrect) or if the zone - * is unsigned, the user is to be asked how to proceed. - */ - WarnIfBogusOrUnsigned -} +package net.java.sip.communicator.impl.dns; + +/** + * Defines how DNSSEC validation errors should be handled. + * + * @author Ingo Bauersachs + */ +public enum SecureResolveMode +{ + /** + * Any DNSSEC data is completely ignored. + */ + IgnoreDnssec, + + /** + * The result of a query is only returned if it validated successfully. + */ + SecureOnly, + + /** + * The result of a query is returned if it validated successfully or when + * the zone is unsigned. + */ + SecureOrUnsigned, + + /** + * If the result of a query is bogus (manipulated, incorrect), the user is + * to be asked how to proceed. + */ + WarnIfBogus, + + /** + * If the result of a query is bogus (manipulated, incorrect) or if the zone + * is unsigned, the user is to be asked how to proceed. + */ + WarnIfBogusOrUnsigned +} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundApi.java b/src/net/java/sip/communicator/impl/dns/UnboundApi.java index 6f35a8b..9a628c0 100644 --- a/src/net/java/sip/communicator/impl/dns/UnboundApi.java +++ b/src/net/java/sip/communicator/impl/dns/UnboundApi.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,225 +15,225 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -/** - * Wrapper for the JUnbound JNI wrapper. - *

    - * The JavaDoc of these methods is directly copied from libunbound, licensed as - * follows: - *

    - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @author Ingo Bauersachs - */ -public class UnboundApi -{ - private static boolean isAvailable; - private static final Object syncRoot = new Object(); - - static - { - tryLoadUnbound(); - } - - /** - * Attempts to load the Unbound native library. When successful, - * {@link #isAvailable()} returns true. - */ - public static void tryLoadUnbound() - { - synchronized(syncRoot) - { - try - { - System.loadLibrary("junbound"); - isAvailable = true; - } - catch(UnsatisfiedLinkError e) - { - isAvailable = false; - } - } - } - - /** - * Indicates whether the Unbound library is loaded. - * @return True when the JNI wrapper could be loaded, false otherwise. - */ - public static boolean isAvailable() - { - return isAvailable; - } - - /** - * Set debug verbosity for the context. Output is directed to stderr. Higher - * debug level gives more output. - * - * @param context context. - * @param level The debug level. - */ - public static native void setDebugLevel(long context, int level); - - /** - * Create a resolving and validation context. - * @return a new context. default initialization. returns NULL on error. - */ - public static native long createContext(); - - /** - * Destroy a validation context and free all its resources. Outstanding - * async queries are killed and callbacks are not called for them. - * - * @param context context to delete - */ - public static native void deleteContext(long context); - - /** - * Set machine to forward DNS queries to, the caching resolver to use. - *

    - * IP4 or IP6 address. Forwards all DNS requests to that machine, which is - * expected to run a recursive resolver. If the proxy is not DNSSEC-capable, - * validation may fail. Can be called several times, in that case the - * addresses are used as backup servers. - * - * @param context context. At this time it is only possible to set - * configuration before the first resolve is done. - * @param server address, IP4 or IP6 in string format. If the server is - * NULL, forwarding is disabled. - */ - public static native void setForwarder(long context, String server); - - /** - * Add a trust anchor to the given context. - *

    - * The trust anchor is a string, on one line, that holds a valid DNSKEY or - * DS RR. - * - * @param context context. At this time it is only possible to add trusted - * keys before the first resolve is done. - * @param anchor string, with zone-format RR on one line. [domainname] [TTL - * optional] [type] [class optional] [rdata contents] - */ - public static native void addTrustAnchor(long context, String anchor); - - /** - * Perform resolution and validation of the target name. - * - * @param context context. The context is finalized, and can no longer - * accept config changes. - * @param name domain name in text format (a zero terminated text string). - * @param rrtype type of RR in host order, 1 is A (address). - * @param rrclass class of RR in host order, 1 is IN (for internet). - * @return the result data is returned in a newly allocated result - * structure. May be NULL on return, return value is set to an error - * in that case (out of memory). - * @throws UnboundException when an error occurred. - */ - public static native UnboundResult resolve(long context, String name, - int rrtype, int rrclass) throws UnboundException; - - /** - * Perform resolution and validation of the target name. - *

    - * Asynchronous, after a while, the callback will be called with your data - * and the result. - * - * @param context context. If no thread or process has been created yet to - * perform the work in the background, it is created now. The - * context is finalized, and can no longer accept config changes. - * @param name domain name in text format (a string). - * @param rrtype type of RR in host order, 1 is A. - * @param rrclass class of RR in host order, 1 is IN (for internet). - * @param data this data is your own data (you can pass null), and is passed - * on to the callback function. - * @param cb this is called on completion of the resolution. - * @return an identifier number is returned for the query as it is in - * progress. It can be used to cancel the query. - * @throws UnboundException when an error occurred. - */ - public static native int resolveAsync(long context, String name, - int rrtype, int rrclass, Object data, UnboundCallback cb) - throws UnboundException; - - /** - * Cancel an async query in progress. Its callback will not be called. - * - * @param context context. - * @param asyncId which query to cancel. - * @throws UnboundException This routine can error if the async_id passed - * does not exist or has already been delivered. If another - * thread is processing results at the same time, the result may - * be delivered at the same time and the cancel fails with an - * error. Also the cancel can fail due to a system error, no - * memory or socket failures. - */ - public static native void cancelAsync(long context, int asyncId) - throws UnboundException; - - /** - * Convert error value to a human readable string. - * - * @param code error code from one of the Unbound functions. - * @return text string of the error code. - */ - public static native String errorCodeToString(int code); - - /** - * Wait for a context to finish with results. Call this routine to continue - * processing results from the validating resolver. After the wait, there - * are no more outstanding asynchronous queries. - * - * @param context context. - * @throws UnboundException when an error occurred. - */ - public static native void processAsync(long context) - throws UnboundException; - - /** - * Interface for the async resolve callback. - */ - public interface UnboundCallback - { - /** - * Called on completion of the async resolution. - * - * @param data the same object as passed to - * {@link UnboundApi#resolveAsync(long, String, int, int, - * Object, UnboundCallback)} - * @param err 0 when a result has been found, an Unbound error code - * otherwise - * @param result a newly allocated result structure. The result may be - * null, in that case err is set. - */ - public void UnboundResolveCallback(Object data, int err, - UnboundResult result); - } -} +package net.java.sip.communicator.impl.dns; + +/** + * Wrapper for the JUnbound JNI wrapper. + *

    + * The JavaDoc of these methods is directly copied from libunbound, licensed as + * follows: + *

    + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Ingo Bauersachs + */ +public class UnboundApi +{ + private static boolean isAvailable; + private static final Object syncRoot = new Object(); + + static + { + tryLoadUnbound(); + } + + /** + * Attempts to load the Unbound native library. When successful, + * {@link #isAvailable()} returns true. + */ + public static void tryLoadUnbound() + { + synchronized(syncRoot) + { + try + { + System.loadLibrary("junbound"); + isAvailable = true; + } + catch(UnsatisfiedLinkError e) + { + isAvailable = false; + } + } + } + + /** + * Indicates whether the Unbound library is loaded. + * @return True when the JNI wrapper could be loaded, false otherwise. + */ + public static boolean isAvailable() + { + return isAvailable; + } + + /** + * Set debug verbosity for the context. Output is directed to stderr. Higher + * debug level gives more output. + * + * @param context context. + * @param level The debug level. + */ + public static native void setDebugLevel(long context, int level); + + /** + * Create a resolving and validation context. + * @return a new context. default initialization. returns NULL on error. + */ + public static native long createContext(); + + /** + * Destroy a validation context and free all its resources. Outstanding + * async queries are killed and callbacks are not called for them. + * + * @param context context to delete + */ + public static native void deleteContext(long context); + + /** + * Set machine to forward DNS queries to, the caching resolver to use. + *

    + * IP4 or IP6 address. Forwards all DNS requests to that machine, which is + * expected to run a recursive resolver. If the proxy is not DNSSEC-capable, + * validation may fail. Can be called several times, in that case the + * addresses are used as backup servers. + * + * @param context context. At this time it is only possible to set + * configuration before the first resolve is done. + * @param server address, IP4 or IP6 in string format. If the server is + * NULL, forwarding is disabled. + */ + public static native void setForwarder(long context, String server); + + /** + * Add a trust anchor to the given context. + *

    + * The trust anchor is a string, on one line, that holds a valid DNSKEY or + * DS RR. + * + * @param context context. At this time it is only possible to add trusted + * keys before the first resolve is done. + * @param anchor string, with zone-format RR on one line. [domainname] [TTL + * optional] [type] [class optional] [rdata contents] + */ + public static native void addTrustAnchor(long context, String anchor); + + /** + * Perform resolution and validation of the target name. + * + * @param context context. The context is finalized, and can no longer + * accept config changes. + * @param name domain name in text format (a zero terminated text string). + * @param rrtype type of RR in host order, 1 is A (address). + * @param rrclass class of RR in host order, 1 is IN (for internet). + * @return the result data is returned in a newly allocated result + * structure. May be NULL on return, return value is set to an error + * in that case (out of memory). + * @throws UnboundException when an error occurred. + */ + public static native UnboundResult resolve(long context, String name, + int rrtype, int rrclass) throws UnboundException; + + /** + * Perform resolution and validation of the target name. + *

    + * Asynchronous, after a while, the callback will be called with your data + * and the result. + * + * @param context context. If no thread or process has been created yet to + * perform the work in the background, it is created now. The + * context is finalized, and can no longer accept config changes. + * @param name domain name in text format (a string). + * @param rrtype type of RR in host order, 1 is A. + * @param rrclass class of RR in host order, 1 is IN (for internet). + * @param data this data is your own data (you can pass null), and is passed + * on to the callback function. + * @param cb this is called on completion of the resolution. + * @return an identifier number is returned for the query as it is in + * progress. It can be used to cancel the query. + * @throws UnboundException when an error occurred. + */ + public static native int resolveAsync(long context, String name, + int rrtype, int rrclass, Object data, UnboundCallback cb) + throws UnboundException; + + /** + * Cancel an async query in progress. Its callback will not be called. + * + * @param context context. + * @param asyncId which query to cancel. + * @throws UnboundException This routine can error if the async_id passed + * does not exist or has already been delivered. If another + * thread is processing results at the same time, the result may + * be delivered at the same time and the cancel fails with an + * error. Also the cancel can fail due to a system error, no + * memory or socket failures. + */ + public static native void cancelAsync(long context, int asyncId) + throws UnboundException; + + /** + * Convert error value to a human readable string. + * + * @param code error code from one of the Unbound functions. + * @return text string of the error code. + */ + public static native String errorCodeToString(int code); + + /** + * Wait for a context to finish with results. Call this routine to continue + * processing results from the validating resolver. After the wait, there + * are no more outstanding asynchronous queries. + * + * @param context context. + * @throws UnboundException when an error occurred. + */ + public static native void processAsync(long context) + throws UnboundException; + + /** + * Interface for the async resolve callback. + */ + public interface UnboundCallback + { + /** + * Called on completion of the async resolution. + * + * @param data the same object as passed to + * {@link UnboundApi#resolveAsync(long, String, int, int, + * Object, UnboundCallback)} + * @param err 0 when a result has been found, an Unbound error code + * otherwise + * @param result a newly allocated result structure. The result may be + * null, in that case err is set. + */ + public void UnboundResolveCallback(Object data, int err, + UnboundResult result); + } +} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundException.java b/src/net/java/sip/communicator/impl/dns/UnboundException.java index 3eb2a04..a27a607 100644 --- a/src/net/java/sip/communicator/impl/dns/UnboundException.java +++ b/src/net/java/sip/communicator/impl/dns/UnboundException.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,28 +15,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -/** - * Exception that is being thrown when native Unbound code resulted in an error. - * - * @author Ingo Bauersachs - */ -public class UnboundException - extends Exception -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates a new instance of this class. - * - * @param message the detail message. - */ - public UnboundException(String message) - { - super(message); - } -} +package net.java.sip.communicator.impl.dns; + +/** + * Exception that is being thrown when native Unbound code resulted in an error. + * + * @author Ingo Bauersachs + */ +public class UnboundException + extends Exception +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Creates a new instance of this class. + * + * @param message the detail message. + */ + public UnboundException(String message) + { + super(message); + } +} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundResolver.java b/src/net/java/sip/communicator/impl/dns/UnboundResolver.java index 309e58e..3f3d8c9 100644 --- a/src/net/java/sip/communicator/impl/dns/UnboundResolver.java +++ b/src/net/java/sip/communicator/impl/dns/UnboundResolver.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,396 +15,396 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; - -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.util.*; - -import org.xbill.DNS.*; - -/** - * Implementation of the {@link Resolver} interface, wrapping the native NLnet - * Labs Unbound resolver. Only the basic methods for queries are supported. - * - * @author Ingo Bauersachs - */ -public class UnboundResolver - implements CustomResolver -{ - private final static Logger logger = - Logger.getLogger(UnboundResolver.class); - - /** - * Helper class to synchronize on asynchronous queries. - */ - private static class CallbackData - { - /** - * The resolver consumer that wishes to be informed when the request - * completed. - */ - ResolverListener listener; - - /** - * The unbound session context. - */ - long context; - - /** - * The ID of the unbound async query. - */ - int asyncId; - - /** - * Java synchronization on top of unbound. - */ - CountDownLatch sync = new CountDownLatch(1); - } - - /** - * Timeout for DNS queries. - */ - private int timeout = 10000; - - /** - * The recursive DNS servers answering our queries. - */ - private String[] forwarders; - - /** - * DNSSEC trust anchors for signed zones (usually for the root zone). - */ - private List trustAnchors = new LinkedList(); - - /** - * Pool that executes our queries. - */ - private ExecutorService threadPool; - - /** - * Creates a new instance of this class. - */ - public UnboundResolver() - { - threadPool = Executors.newCachedThreadPool(); - } - - /** - * Sets a list of forwarders to use instead of the system default. - * - * @param forwarders list of servers to use for our queries. - */ - public void setForwarders(String[] forwarders) - { - this.forwarders = forwarders; - } - - /** - * Clears any existing trust anchors previously added. - */ - public void clearTrustAnchors() - { - trustAnchors.clear(); - } - - /** - * Adds a DNSSEC trust anchor validation of the DNSKEYs. - * - * @param anchor trust anchor in the form of - * "'zone' IN DS 'key tag' 'algorithm' 'digest type' 'digest'" - */ - public void addTrustAnchor(String anchor) - { - trustAnchors.add(anchor); - } - - /** - * {@inheritDoc} - */ - public SecureMessage send(final Message query) throws IOException - { - Future future = threadPool.submit( - new Callable() - { - public SecureMessage call() throws Exception - { - if(logger.isDebugEnabled()) - logger.debug(query); - - SecureMessage secureMessage = null; - final long context = prepareContext(); - try - { - UnboundResult result = UnboundApi.resolve( - context, - query.getQuestion().getName().toString(), - query.getQuestion().getType(), - query.getQuestion().getDClass() - ); - secureMessage = new SecureMessage(result); - validateMessage(secureMessage); - } - finally - { - UnboundApi.deleteContext(context); - if(logger.isDebugEnabled() && secureMessage != null) - logger.debug(secureMessage); - } - - return secureMessage; - } - }); - try - { - return future.get(timeout, TimeUnit.SECONDS); - } - catch (InterruptedException e) - { - logger.error(e); - throw new IOException(e.getMessage()); - } - catch (ExecutionException e) - { - if(e.getCause() instanceof DnssecRuntimeException) - throw new DnssecRuntimeException(e.getCause().getMessage()); - logger.error(e); - throw new IOException(e.getMessage()); - } - catch (TimeoutException e) - { - throw new SocketTimeoutException(e.getMessage()); - } - } - - /** - * Method to allow overriders to inspect the message. This class' - * implementation does nothing. - * - * @param msg The message to inspect. - * @throws DnssecRuntimeException if the inspector does not want the code to - * continue normal processing of the answer. - */ - protected void validateMessage(SecureMessage msg) - throws DnssecRuntimeException - { - } - - /** - * Prepares a unbound session context initialized with forwarders and trust - * anchors. - * - * @return The context id - */ - private long prepareContext() - { - final long context = UnboundApi.createContext(); - if(logger.isTraceEnabled()) - UnboundApi.setDebugLevel(context, 100); - for(String fwd : forwarders == null - ? ResolverConfig.getCurrentConfig().servers() - : forwarders) - { - fwd = fwd.trim(); - if(NetworkUtils.isValidIPAddress(fwd)) - { - if(fwd.startsWith("[")) - fwd = fwd.substring(1, fwd.length() - 1); - UnboundApi.setForwarder(context, fwd); - } - } - for(String anchor : trustAnchors) - { - UnboundApi.addTrustAnchor(context, anchor); - } - return context; - } - - /** - * Cleans up an Unbound session context. - * - * @param cbData The helper object of the asynchronous call. - * @param cancelAsync Whether an outstanding asynchronous unbound query - * should be canceled. - */ - private static synchronized void deleteContext(CallbackData cbData, - boolean cancelAsync) - { - if(cbData.context == 0) - return; - - if(cancelAsync) - { - try - { - UnboundApi.cancelAsync(cbData.context, cbData.asyncId); - } - catch (UnboundException ignore) - {} - } - UnboundApi.deleteContext(cbData.context); - cbData.context = 0; - } - - /* - * (non-Javadoc) - * - * @see org.xbill.DNS.Resolver#sendAsync(org.xbill.DNS.Message, - * org.xbill.DNS.ResolverListener) - */ - public CallbackData sendAsync(Message query, ResolverListener listener) - { - if(listener == null) - throw new IllegalArgumentException("listener cannot be null"); - - final long context = prepareContext(); - final CallbackData cbData = new CallbackData(); - cbData.listener = listener; - cbData.context = context; - int asyncId; - try - { - asyncId = UnboundApi.resolveAsync( - context, - query.getQuestion().getName().toString(), - query.getQuestion().getType(), - query.getQuestion().getDClass(), - cbData, - new UnboundApi.UnboundCallback() - { - public void UnboundResolveCallback(Object data, int err, - UnboundResult result) - { - CallbackData cbData = (CallbackData)data; - deleteContext(cbData, false); - - ResolverListener l = cbData.listener; - if(err == 0) - { - try - { - l.receiveMessage(data, - new SecureMessage(result)); - } - catch (IOException e) - { - l.handleException(data, e); - } - } - else - l.handleException(data, - new Exception( - UnboundApi.errorCodeToString(err))); - - cbData.sync.countDown(); - } - } - ); - } - catch (UnboundException e) - { - listener.handleException(null, e); - return null; - } - cbData.asyncId = asyncId; - threadPool.execute(new Runnable() - { - public void run() - { - try - { - UnboundApi.processAsync(context); - } - catch(UnboundException ex) - { - cbData.listener.handleException(this, ex); - deleteContext(cbData, false); - cbData.sync.countDown(); - } - } - }); - return cbData; - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setEDNS(int level) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - @SuppressWarnings("rawtypes") - public void setEDNS(int level, int payloadSize, int flags, List options) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setIgnoreTruncation(boolean flag) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setPort(int port) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setTCP(boolean flag) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setTSIGKey(TSIG key) - { - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see org.xbill.DNS.Resolver#setTimeout(int) - */ - public void setTimeout(int secs) - { - timeout = secs * 1000; - } - - /* (non-Javadoc) - * @see org.xbill.DNS.Resolver#setTimeout(int, int) - */ - public void setTimeout(int secs, int msecs) - { - timeout = secs * 1000 + msecs; - } - - /** - * Does nothing. - */ - public void reset() - { - } -} +package net.java.sip.communicator.impl.dns; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.concurrent.*; + +import net.java.sip.communicator.service.dns.*; +import net.java.sip.communicator.util.*; + +import org.xbill.DNS.*; + +/** + * Implementation of the {@link Resolver} interface, wrapping the native NLnet + * Labs Unbound resolver. Only the basic methods for queries are supported. + * + * @author Ingo Bauersachs + */ +public class UnboundResolver + implements CustomResolver +{ + private final static Logger logger = + Logger.getLogger(UnboundResolver.class); + + /** + * Helper class to synchronize on asynchronous queries. + */ + private static class CallbackData + { + /** + * The resolver consumer that wishes to be informed when the request + * completed. + */ + ResolverListener listener; + + /** + * The unbound session context. + */ + long context; + + /** + * The ID of the unbound async query. + */ + int asyncId; + + /** + * Java synchronization on top of unbound. + */ + CountDownLatch sync = new CountDownLatch(1); + } + + /** + * Timeout for DNS queries. + */ + private int timeout = 10000; + + /** + * The recursive DNS servers answering our queries. + */ + private String[] forwarders; + + /** + * DNSSEC trust anchors for signed zones (usually for the root zone). + */ + private List trustAnchors = new LinkedList(); + + /** + * Pool that executes our queries. + */ + private ExecutorService threadPool; + + /** + * Creates a new instance of this class. + */ + public UnboundResolver() + { + threadPool = Executors.newCachedThreadPool(); + } + + /** + * Sets a list of forwarders to use instead of the system default. + * + * @param forwarders list of servers to use for our queries. + */ + public void setForwarders(String[] forwarders) + { + this.forwarders = forwarders; + } + + /** + * Clears any existing trust anchors previously added. + */ + public void clearTrustAnchors() + { + trustAnchors.clear(); + } + + /** + * Adds a DNSSEC trust anchor validation of the DNSKEYs. + * + * @param anchor trust anchor in the form of + * "'zone' IN DS 'key tag' 'algorithm' 'digest type' 'digest'" + */ + public void addTrustAnchor(String anchor) + { + trustAnchors.add(anchor); + } + + /** + * {@inheritDoc} + */ + public SecureMessage send(final Message query) throws IOException + { + Future future = threadPool.submit( + new Callable() + { + public SecureMessage call() throws Exception + { + if(logger.isDebugEnabled()) + logger.debug(query); + + SecureMessage secureMessage = null; + final long context = prepareContext(); + try + { + UnboundResult result = UnboundApi.resolve( + context, + query.getQuestion().getName().toString(), + query.getQuestion().getType(), + query.getQuestion().getDClass() + ); + secureMessage = new SecureMessage(result); + validateMessage(secureMessage); + } + finally + { + UnboundApi.deleteContext(context); + if(logger.isDebugEnabled() && secureMessage != null) + logger.debug(secureMessage); + } + + return secureMessage; + } + }); + try + { + return future.get(timeout, TimeUnit.SECONDS); + } + catch (InterruptedException e) + { + logger.error(e); + throw new IOException(e.getMessage()); + } + catch (ExecutionException e) + { + if(e.getCause() instanceof DnssecRuntimeException) + throw new DnssecRuntimeException(e.getCause().getMessage()); + logger.error(e); + throw new IOException(e.getMessage()); + } + catch (TimeoutException e) + { + throw new SocketTimeoutException(e.getMessage()); + } + } + + /** + * Method to allow overriders to inspect the message. This class' + * implementation does nothing. + * + * @param msg The message to inspect. + * @throws DnssecRuntimeException if the inspector does not want the code to + * continue normal processing of the answer. + */ + protected void validateMessage(SecureMessage msg) + throws DnssecRuntimeException + { + } + + /** + * Prepares a unbound session context initialized with forwarders and trust + * anchors. + * + * @return The context id + */ + private long prepareContext() + { + final long context = UnboundApi.createContext(); + if(logger.isTraceEnabled()) + UnboundApi.setDebugLevel(context, 100); + for(String fwd : forwarders == null + ? ResolverConfig.getCurrentConfig().servers() + : forwarders) + { + fwd = fwd.trim(); + if(NetworkUtils.isValidIPAddress(fwd)) + { + if(fwd.startsWith("[")) + fwd = fwd.substring(1, fwd.length() - 1); + UnboundApi.setForwarder(context, fwd); + } + } + for(String anchor : trustAnchors) + { + UnboundApi.addTrustAnchor(context, anchor); + } + return context; + } + + /** + * Cleans up an Unbound session context. + * + * @param cbData The helper object of the asynchronous call. + * @param cancelAsync Whether an outstanding asynchronous unbound query + * should be canceled. + */ + private static synchronized void deleteContext(CallbackData cbData, + boolean cancelAsync) + { + if(cbData.context == 0) + return; + + if(cancelAsync) + { + try + { + UnboundApi.cancelAsync(cbData.context, cbData.asyncId); + } + catch (UnboundException ignore) + {} + } + UnboundApi.deleteContext(cbData.context); + cbData.context = 0; + } + + /* + * (non-Javadoc) + * + * @see org.xbill.DNS.Resolver#sendAsync(org.xbill.DNS.Message, + * org.xbill.DNS.ResolverListener) + */ + public CallbackData sendAsync(Message query, ResolverListener listener) + { + if(listener == null) + throw new IllegalArgumentException("listener cannot be null"); + + final long context = prepareContext(); + final CallbackData cbData = new CallbackData(); + cbData.listener = listener; + cbData.context = context; + int asyncId; + try + { + asyncId = UnboundApi.resolveAsync( + context, + query.getQuestion().getName().toString(), + query.getQuestion().getType(), + query.getQuestion().getDClass(), + cbData, + new UnboundApi.UnboundCallback() + { + public void UnboundResolveCallback(Object data, int err, + UnboundResult result) + { + CallbackData cbData = (CallbackData)data; + deleteContext(cbData, false); + + ResolverListener l = cbData.listener; + if(err == 0) + { + try + { + l.receiveMessage(data, + new SecureMessage(result)); + } + catch (IOException e) + { + l.handleException(data, e); + } + } + else + l.handleException(data, + new Exception( + UnboundApi.errorCodeToString(err))); + + cbData.sync.countDown(); + } + } + ); + } + catch (UnboundException e) + { + listener.handleException(null, e); + return null; + } + cbData.asyncId = asyncId; + threadPool.execute(new Runnable() + { + public void run() + { + try + { + UnboundApi.processAsync(context); + } + catch(UnboundException ex) + { + cbData.listener.handleException(this, ex); + deleteContext(cbData, false); + cbData.sync.countDown(); + } + } + }); + return cbData; + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + public void setEDNS(int level) + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + @SuppressWarnings("rawtypes") + public void setEDNS(int level, int payloadSize, int flags, List options) + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + public void setIgnoreTruncation(boolean flag) + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + public void setPort(int port) + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + public void setTCP(boolean flag) + { + throw new UnsupportedOperationException(); + } + + /** + * Not supported. + * @throws UnsupportedOperationException + */ + public void setTSIGKey(TSIG key) + { + throw new UnsupportedOperationException(); + } + + /* (non-Javadoc) + * @see org.xbill.DNS.Resolver#setTimeout(int) + */ + public void setTimeout(int secs) + { + timeout = secs * 1000; + } + + /* (non-Javadoc) + * @see org.xbill.DNS.Resolver#setTimeout(int, int) + */ + public void setTimeout(int secs, int msecs) + { + timeout = secs * 1000 + msecs; + } + + /** + * Does nothing. + */ + public void reset() + { + } +} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundResult.java b/src/net/java/sip/communicator/impl/dns/UnboundResult.java index 85167d0..ef5d1ec 100644 --- a/src/net/java/sip/communicator/impl/dns/UnboundResult.java +++ b/src/net/java/sip/communicator/impl/dns/UnboundResult.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,114 +15,114 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.dns; - -/** - * Class that contains the answer to query processed by the native Unbound - * resolver. Corresponds to the ub_result data structure. - * - * The fields {@link #data} and {@link #canonname} are not filled. - *

    - * The JavaDoc of these fields is directly copied from libunbound, licensed as - * follows: - *

    - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * @author Ingo Bauersachs - */ -public class UnboundResult -{ - /** - * The original question, name text string. - */ - String qname; - - /** - * the type asked for - */ - int qtype; - - /** - * the type asked for - */ - int qclass; - - - /** - * a list of network order DNS rdata items, terminated with a NULL pointer, - * so that data[0] is the first result entry, data[1] the second, and the - * last entry is NULL. - */ - byte[][] data; - - /** - * canonical name for the result (the final cname). - */ - String canonname; - - /** - * DNS RCODE for the result. - */ - int rcode; - - /** - * The DNS answer packet. - */ - byte[] answerPacket; - - - /** - * If there is any data, this is true. - */ - boolean haveData; - - /** - * If there was no data, and the domain did not exist, this is true. - */ - boolean nxDomain; - - /** - * True, if the result is validated securely. - */ - boolean secure; - - /** - * If the result was not secure ({@link #secure} == false), and this result - * is due to a security failure, bogus is true. - */ - boolean bogus; - - /** - * If the result is bogus this contains a string (zero terminated) that - * describes the failure. - */ - String whyBogus; -} +package net.java.sip.communicator.impl.dns; + +/** + * Class that contains the answer to query processed by the native Unbound + * resolver. Corresponds to the ub_result data structure. + * + * The fields {@link #data} and {@link #canonname} are not filled. + *

    + * The JavaDoc of these fields is directly copied from libunbound, licensed as + * follows: + *

    + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * @author Ingo Bauersachs + */ +public class UnboundResult +{ + /** + * The original question, name text string. + */ + String qname; + + /** + * the type asked for + */ + int qtype; + + /** + * the type asked for + */ + int qclass; + + + /** + * a list of network order DNS rdata items, terminated with a NULL pointer, + * so that data[0] is the first result entry, data[1] the second, and the + * last entry is NULL. + */ + byte[][] data; + + /** + * canonical name for the result (the final cname). + */ + String canonname; + + /** + * DNS RCODE for the result. + */ + int rcode; + + /** + * The DNS answer packet. + */ + byte[] answerPacket; + + + /** + * If there is any data, this is true. + */ + boolean haveData; + + /** + * If there was no data, and the domain did not exist, this is true. + */ + boolean nxDomain; + + /** + * True, if the result is validated securely. + */ + boolean secure; + + /** + * If the result was not secure ({@link #secure} == false), and this result + * is due to a security failure, bogus is true. + */ + boolean bogus; + + /** + * If the result is bogus this contains a string (zero terminated) that + * describes the failure. + */ + String whyBogus; +} diff --git a/src/net/java/sip/communicator/impl/gui/main/account/AccountsConfigurationPanel.java b/src/net/java/sip/communicator/impl/gui/main/account/AccountsConfigurationPanel.java index 9511310..a85ffc3 100644 --- a/src/net/java/sip/communicator/impl/gui/main/account/AccountsConfigurationPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/account/AccountsConfigurationPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,278 +15,278 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.account; - -import java.awt.*; -import java.awt.event.*; -import java.beans.*; -import java.util.List; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.account.*; - -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; - -/** - * The AccountsConfigurationPanel is the panel containing the accounts - * list and according buttons shown in the options form. - * - * @author Yana Stamcheva - * @author Lubomir Marinov - */ -public class AccountsConfigurationPanel - extends TransparentPanel - implements ActionListener, - ListSelectionListener, - PropertyChangeListener -{ - private final AccountList accountList; - - private final JButton newButton = - new JButton(GuiActivator.getResources().getI18NString( - "service.gui.ADD")); - - private final JButton editButton = - new JButton(GuiActivator.getResources().getI18NString( - "service.gui.EDIT")); - - private final JButton removeButton = - new JButton(GuiActivator.getResources().getI18NString( - "service.gui.DELETE")); - - /** - * Creates and initializes this account configuration panel. - */ - public AccountsConfigurationPanel() - { - super(new BorderLayout()); - - accountList = new AccountList(this); - - /* - * It seems that we can only delete one account at a time because our - * confirmation dialog asks for one account. - */ - accountList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - this.setPreferredSize(new Dimension(500, 400)); - - JScrollPane accountListPane = new JScrollPane(); - - accountListPane.getViewport().add(accountList); - accountListPane.getVerticalScrollBar().setUnitIncrement(30); - - this.add(accountListPane, BorderLayout.CENTER); - - JPanel buttonsPanel = - new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); - - newButton.addActionListener(this); - editButton.addActionListener(this); - removeButton.addActionListener(this); - - this.newButton.setMnemonic(GuiActivator.getResources().getI18nMnemonic( - "service.gui.ADD")); - this.editButton - .setMnemonic(GuiActivator.getResources().getI18nMnemonic( - "service.gui.EDIT")); - this.removeButton - .setMnemonic(GuiActivator.getResources().getI18nMnemonic( - "service.gui.DELETE")); - - buttonsPanel.add(newButton); - - buttonsPanel.add(editButton); - - buttonsPanel.add(removeButton); - - this.add(buttonsPanel, BorderLayout.SOUTH); - - accountList.addListSelectionListener(this); - accountList.addPropertyChangeListener( - AccountList.ACCOUNT_STATE_CHANGED, this); - updateButtons(); - } - - /** - * Handles the ActionEvent triggered when user clicks on on the - * buttons. Shows the account registration wizard when user clicks on "New". - * - * @param evt the action event that has just occurred. - */ - public void actionPerformed(ActionEvent evt) - { - Object sourceButton = evt.getSource(); - - if (sourceButton.equals(newButton)) - { - NewAccountDialog.showNewAccountDialog(); - } - else if (sourceButton.equals(removeButton)) - { - Account account = accountList.getSelectedAccount(); - - if (account == null) - return; - - AccountID accountID = account.getAccountID(); - - ProtocolProviderFactory providerFactory = - AccountUtils.getProtocolProviderFactory( - accountID.getProtocolName()); - - if (providerFactory != null) - { - int result = JOptionPane.showConfirmDialog( - this, - GuiActivator.getResources() - .getI18NString("service.gui.REMOVE_ACCOUNT_MESSAGE"), - GuiActivator.getResources().getI18NString( - "service.gui.REMOVE_ACCOUNT"), - JOptionPane.YES_NO_OPTION); - - if (result == JOptionPane.YES_OPTION) - { - ConfigurationService configService - = GuiActivator.getConfigurationService(); - String prefix - = "net.java.sip.communicator.impl.gui.accounts"; - List accounts - = configService.getPropertyNamesByPrefix(prefix, true); - - for (String accountRootPropName : accounts) - { - String accountUID - = configService.getString(accountRootPropName); - - if (accountUID.equals(accountID.getAccountUniqueID())) - { - configService.setProperty(accountRootPropName, null); - break; - } - } - boolean isUninstalled - = providerFactory.uninstallAccount(accountID); - - if (isUninstalled) - { - accountList.ensureAccountRemoved(accountID); - - // Notify the corresponding wizard that the account - // would be removed. - AccountRegWizardContainerImpl wizardContainer - = (AccountRegWizardContainerImpl) GuiActivator - .getUIService().getAccountRegWizardContainer(); - - ProtocolProviderService protocolProvider = - account.getProtocolProvider(); - AccountRegistrationWizard wizard = - wizardContainer.getProtocolWizard(protocolProvider); - - if (wizard != null) - wizard.accountRemoved(protocolProvider); - } - } - } - } - else if (sourceButton.equals(editButton)) - { - Account account = accountList.getSelectedAccount(); - - if (account == null) - return; - - AccountRegWizardContainerImpl wizard = - (AccountRegWizardContainerImpl) GuiActivator.getUIService() - .getAccountRegWizardContainer(); - - AccountRegistrationWizard protocolWizard = - wizard.getProtocolWizard(account.getProtocolProvider()); - - ResourceManagementService resources = GuiActivator.getResources(); - if (protocolWizard != null) - { - wizard.setTitle(resources.getI18NString( - "service.gui.ACCOUNT_REGISTRATION_WIZARD")); - - wizard.modifyAccount(account.getProtocolProvider()); - wizard.showDialog(false); - } - else - { - // There is no wizard for this account - just show an error - // dialog: - String title = resources.getI18NString("service.gui.ERROR"); - String message = - resources.getI18NString("service.gui.EDIT_NOT_SUPPORTED"); - ErrorDialog dialog = new ErrorDialog(null, title, message); - dialog.setVisible(true); - } - } - } - - /** - * Returns the edit button. - * - * @return the edit button - */ - public JButton getEditButton() - { - return editButton; - } - - /** - * Updates enabled states of the buttons of this - * AccountsConfigurationPanel to reflect their applicability to the - * current selection in accountList. - */ - private void updateButtons() - { - if(!SwingUtilities.isEventDispatchThread()) - { - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - updateButtons(); - } - }); - return; - } - - Account account = accountList.getSelectedAccount(); - boolean enabled = (account != null); - - editButton.setEnabled(enabled && account.isEnabled()); - removeButton.setEnabled(enabled); - } - - /** - * Implements ListSelectionListener#valueChanged(ListSelectionEvent). - * @param e the ListSelectionEvent that notified us - */ - public void valueChanged(ListSelectionEvent e) - { - if (!e.getValueIsAdjusting()) - updateButtons(); - } - - /** - * This method gets called when a property is changed. - * - * @param evt A PropertyChangeEvent object describing the event source - * and the property that has changed. - */ - public void propertyChange(PropertyChangeEvent evt) - { - // update buttons whenever an account changes its state - updateButtons(); - } -} +package net.java.sip.communicator.impl.gui.main.account; + +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import java.util.List; + +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.account.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; + +/** + * The AccountsConfigurationPanel is the panel containing the accounts + * list and according buttons shown in the options form. + * + * @author Yana Stamcheva + * @author Lubomir Marinov + */ +public class AccountsConfigurationPanel + extends TransparentPanel + implements ActionListener, + ListSelectionListener, + PropertyChangeListener +{ + private final AccountList accountList; + + private final JButton newButton = + new JButton(GuiActivator.getResources().getI18NString( + "service.gui.ADD")); + + private final JButton editButton = + new JButton(GuiActivator.getResources().getI18NString( + "service.gui.EDIT")); + + private final JButton removeButton = + new JButton(GuiActivator.getResources().getI18NString( + "service.gui.DELETE")); + + /** + * Creates and initializes this account configuration panel. + */ + public AccountsConfigurationPanel() + { + super(new BorderLayout()); + + accountList = new AccountList(this); + + /* + * It seems that we can only delete one account at a time because our + * confirmation dialog asks for one account. + */ + accountList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + this.setPreferredSize(new Dimension(500, 400)); + + JScrollPane accountListPane = new JScrollPane(); + + accountListPane.getViewport().add(accountList); + accountListPane.getVerticalScrollBar().setUnitIncrement(30); + + this.add(accountListPane, BorderLayout.CENTER); + + JPanel buttonsPanel = + new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); + + newButton.addActionListener(this); + editButton.addActionListener(this); + removeButton.addActionListener(this); + + this.newButton.setMnemonic(GuiActivator.getResources().getI18nMnemonic( + "service.gui.ADD")); + this.editButton + .setMnemonic(GuiActivator.getResources().getI18nMnemonic( + "service.gui.EDIT")); + this.removeButton + .setMnemonic(GuiActivator.getResources().getI18nMnemonic( + "service.gui.DELETE")); + + buttonsPanel.add(newButton); + + buttonsPanel.add(editButton); + + buttonsPanel.add(removeButton); + + this.add(buttonsPanel, BorderLayout.SOUTH); + + accountList.addListSelectionListener(this); + accountList.addPropertyChangeListener( + AccountList.ACCOUNT_STATE_CHANGED, this); + updateButtons(); + } + + /** + * Handles the ActionEvent triggered when user clicks on on the + * buttons. Shows the account registration wizard when user clicks on "New". + * + * @param evt the action event that has just occurred. + */ + public void actionPerformed(ActionEvent evt) + { + Object sourceButton = evt.getSource(); + + if (sourceButton.equals(newButton)) + { + NewAccountDialog.showNewAccountDialog(); + } + else if (sourceButton.equals(removeButton)) + { + Account account = accountList.getSelectedAccount(); + + if (account == null) + return; + + AccountID accountID = account.getAccountID(); + + ProtocolProviderFactory providerFactory = + AccountUtils.getProtocolProviderFactory( + accountID.getProtocolName()); + + if (providerFactory != null) + { + int result = JOptionPane.showConfirmDialog( + this, + GuiActivator.getResources() + .getI18NString("service.gui.REMOVE_ACCOUNT_MESSAGE"), + GuiActivator.getResources().getI18NString( + "service.gui.REMOVE_ACCOUNT"), + JOptionPane.YES_NO_OPTION); + + if (result == JOptionPane.YES_OPTION) + { + ConfigurationService configService + = GuiActivator.getConfigurationService(); + String prefix + = "net.java.sip.communicator.impl.gui.accounts"; + List accounts + = configService.getPropertyNamesByPrefix(prefix, true); + + for (String accountRootPropName : accounts) + { + String accountUID + = configService.getString(accountRootPropName); + + if (accountUID.equals(accountID.getAccountUniqueID())) + { + configService.setProperty(accountRootPropName, null); + break; + } + } + boolean isUninstalled + = providerFactory.uninstallAccount(accountID); + + if (isUninstalled) + { + accountList.ensureAccountRemoved(accountID); + + // Notify the corresponding wizard that the account + // would be removed. + AccountRegWizardContainerImpl wizardContainer + = (AccountRegWizardContainerImpl) GuiActivator + .getUIService().getAccountRegWizardContainer(); + + ProtocolProviderService protocolProvider = + account.getProtocolProvider(); + AccountRegistrationWizard wizard = + wizardContainer.getProtocolWizard(protocolProvider); + + if (wizard != null) + wizard.accountRemoved(protocolProvider); + } + } + } + } + else if (sourceButton.equals(editButton)) + { + Account account = accountList.getSelectedAccount(); + + if (account == null) + return; + + AccountRegWizardContainerImpl wizard = + (AccountRegWizardContainerImpl) GuiActivator.getUIService() + .getAccountRegWizardContainer(); + + AccountRegistrationWizard protocolWizard = + wizard.getProtocolWizard(account.getProtocolProvider()); + + ResourceManagementService resources = GuiActivator.getResources(); + if (protocolWizard != null) + { + wizard.setTitle(resources.getI18NString( + "service.gui.ACCOUNT_REGISTRATION_WIZARD")); + + wizard.modifyAccount(account.getProtocolProvider()); + wizard.showDialog(false); + } + else + { + // There is no wizard for this account - just show an error + // dialog: + String title = resources.getI18NString("service.gui.ERROR"); + String message = + resources.getI18NString("service.gui.EDIT_NOT_SUPPORTED"); + ErrorDialog dialog = new ErrorDialog(null, title, message); + dialog.setVisible(true); + } + } + } + + /** + * Returns the edit button. + * + * @return the edit button + */ + public JButton getEditButton() + { + return editButton; + } + + /** + * Updates enabled states of the buttons of this + * AccountsConfigurationPanel to reflect their applicability to the + * current selection in accountList. + */ + private void updateButtons() + { + if(!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + updateButtons(); + } + }); + return; + } + + Account account = accountList.getSelectedAccount(); + boolean enabled = (account != null); + + editButton.setEnabled(enabled && account.isEnabled()); + removeButton.setEnabled(enabled); + } + + /** + * Implements ListSelectionListener#valueChanged(ListSelectionEvent). + * @param e the ListSelectionEvent that notified us + */ + public void valueChanged(ListSelectionEvent e) + { + if (!e.getValueIsAdjusting()) + updateButtons(); + } + + /** + * This method gets called when a property is changed. + * + * @param evt A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent evt) + { + // update buttons whenever an account changes its state + updateButtons(); + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java index 697a3fc..de63f79 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,619 +15,619 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * The dialog created for a given call. - * - * @author Yana Stamcheva - * @author Adam Netocny - * @author Lyubomir Marinov - */ -public class CallDialog - extends SIPCommFrame - implements CallContainer, - CallTitleListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Enabling force minimized mode will always open call dialog minimized. - * The call dialog still can be shown, but by default it will be minimized. - */ - private static final String FORCE_MINIMIZED_MODE - = "net.java.sip.communicator.impl.gui.main.call.FORCE_MINIMIZED_MODE"; - - /** - * Finds a Container which is an ancestor of a specific - * Component, has a set preferredSize and is closest to - * the specified Component up the ancestor hierarchy. - * - * @param component the Component whose ancestor hierarchy is to be - * searched upwards - * @return a Container, if any, which is an ancestor of the - * specified component, has a set preferredSize and is - * closest to the specified component up the ancestor hierarchy - */ - private static Container findClosestAncestorWithSetPreferredSize( - Component component) - { - if ((component instanceof Container) && component.isPreferredSizeSet()) - return (Container) component; - else - { - Container parent; - - while ((parent = component.getParent()) != null) - { - if (parent.isPreferredSizeSet()) - return parent; - else - component = parent; - } - return null; - } - } - - /** - * The panel, where all call components are added. - */ - private CallPanel callPanel; - - private final WindowStateListener windowStateListener - = new WindowStateListener() - { - public void windowStateChanged(WindowEvent ev) - { - switch (ev.getID()) - { - case WindowEvent.WINDOW_DEACTIVATED: - case WindowEvent.WINDOW_ICONIFIED: - case WindowEvent.WINDOW_LOST_FOCUS: - setFullScreen(false); - break; - } - } - }; - - /** - * Creates a CallDialog by specifying the underlying call panel. - */ - public CallDialog() - { - super(true, false); - - setMinimumSize(new Dimension(360, 300)); - } - - /** - * Adds a call panel. - * - * @param callPanel the call panel to add to this dialog - */ - public void addCallPanel(CallPanel callPanel) - { - this.callPanel = callPanel; - - getContentPane().add(callPanel); - - callPanel.addCallTitleListener(this); - setTitle(callPanel.getCallTitle()); - - if (!isVisible()) - { - pack(); - - // checks whether we need to open the call dialog in minimized mode - if(GuiActivator.getConfigurationService() - .getBoolean(FORCE_MINIMIZED_MODE, false)) - { - setState(ICONIFIED); - } - setVisible(true); - } - } - - /** - * Called when the title of the given CallPanel changes. - * - * @param callPanel the CallPanel, which title has changed - */ - public void callTitleChanged(CallPanel callPanel) - { - if (this.callPanel.equals(callPanel)) - setTitle(callPanel.getCallTitle()); - } - - /** - * {@inheritDoc} - * - * Hang ups the call/telephony conference depicted by this - * CallDialog on close. - */ - @Override - protected void close(boolean escape) - { - if (escape) - { - /* - * In full-screen mode, ESC does not close this CallDialog but exits - * from full-screen to windowed mode. - */ - if (isFullScreen()) - { - setFullScreen(false); - return; - } - } - else - { - /* - * If the window has been closed by clicking the X button or - * pressing the key combination corresponding to the same button we - * close the window first and then perform all hang up operations. - */ - - callPanel.disposeCallInfoFrame(); - // We hide the window here. It will be disposed when the call has - // been ended. - setVisible(false); - } - - // Then perform hang up operations. - callPanel.actionPerformedOnHangupButton(escape); - } - - /** - * {@inheritDoc} - * - * The delay implemented by CallDialog is 5 seconds. - */ - public void close(final CallPanel callPanel, boolean delay) - { - if (this.callPanel.equals(callPanel)) - { - if (delay) - { - Timer timer - = new Timer( - 5000, - new ActionListener() - { - public void actionPerformed(ActionEvent ev) - { - dispose(); - } - }); - - timer.setRepeats(false); - timer.start(); - } - else - { - dispose(); - } - } - } - - /** - * {@inheritDoc} - * - * CallDialog prepares the CallPanel it contains for - * garbage collection. - */ - @Override - public void dispose() - { - super.dispose(); - - /* - * Technically, CallManager adds/removes the callPanel to/from this - * instance. It may want to just move it to another CallContainer so it - * does not sound right that we are disposing of it. But we do not have - * such a case at this time so try to reduce the risk of memory leaks. - */ - if (this.callPanel != null) - { - callPanel.disposeCallInfoFrame(); - callPanel.dispose(); - } - } - - /** - * {@inheritDoc} - * - * Attempts to adjust the size of this Frame as requested in the - * AWT event dispatching thread. - *

    - * The method may be executed on the AWT event dispatching thread only - * because whoever is making the decision to request an adjustment of the - * Frame size in relation to a AWT Component should be analyzing that same - * Component in the AWT event dispatching thread only. - *

    - * - * @throws RuntimeException if the method is not called on the AWT event - * dispatching thread - */ - public void ensureSize(Component component, int width, int height) - { - CallManager.assertIsEventDispatchingThread(); - - Frame frame = CallPeerRendererUtils.getFrame(component); - - if (frame == null) - return; - else if ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) - == Frame.MAXIMIZED_BOTH) - { - /* - * Forcing the size of a Component which is displayed in a maximized - * window does not sound like anything we want to do. - */ - return; - } - else if (frame.equals( - frame.getGraphicsConfiguration().getDevice() - .getFullScreenWindow())) - { - /* - * Forcing the size of a Component which is displayed in a - * full-screen window does not sound like anything we want to do. - */ - return; - } - else if (!frame.equals(this)) - { - /* This Frame will try to adjust only its own size. */ - return; - } - else if ((component.getHeight() >= height) - && (component.getWidth() >= width)) - { - /* - * We will only enlarge the frame size. If the component has already - * been given at least what it is requesting, do not enlarge the - * frame size because the whole calculation is prone to inaccuracy. - */ - return; - } - else - { - /* - * If there is no callPanel, it is unlikely that this CallDialog - * will be asked to ensureSize. Anyway, support the scenario just in - * case. In light of the absence of a callPanel to guide this - * CallDialog about the preferred size, we do not have much of a - * choice but to trust the method arguments. - */ - if (callPanel != null) - { - /* - * If there is a callPanel, we are likely to get a much better - * estimation about the preferred size by asking the callPanel - * rather than by trusting the method arguments. For example, - * the visual Component displaying the video streaming from the - * local user/peer to the remote peer(s) will think that its - * preferred size is the one to base this Frame's size on but - * that may be misleading because the local video may not be - * displayed with its preferred size even if this Frame's size - * will accommodate it. - */ - /* - * Just asking the callPanel about its preferredSize would've - * been terrificly great. Unfortunately, that is presently - * futile because the callPanel may have a preferredSize while - * we are still required to display visual Components displaying - * video in their non-scaled size. The same goes for any - * Container which is an ancestor of the specified component. - */ - Container ancestor - = findClosestAncestorWithSetPreferredSize(component); - - if (ancestor == null) - ancestor = callPanel; - /* - * If the ancestor has a forced preferredSize, its LayoutManager - * may be able to give a good enough estimation. - */ - if (ancestor.isPreferredSizeSet()) - { - LayoutManager ancestorLayout = ancestor.getLayout(); - - if (ancestorLayout != null) - { - Dimension preferredLayoutSize - = ancestorLayout.preferredLayoutSize(ancestor); - - if (preferredLayoutSize != null) - { - component = ancestor; - width = preferredLayoutSize.width; - height = preferredLayoutSize.height; - } - } - } - else - { - /* - * If the ancestor doesn't have a preferredSize forced, then - * we may think that it will calculate an appropriate - * preferredSize itself. - */ - Dimension prefSize = ancestor.getPreferredSize(); - - if (prefSize != null) - { - component = ancestor; - width = prefSize.width; - height = prefSize.height; - } - } - } - - /* - * If the component (which may be an ancestor of the Component - * specified as an argument to the ensureSize method at this point) - * has not been given a size, we will make a mistake if we try to - * use it for the purposes of determining how much this Frame is to - * be enlarged. - */ - Dimension componentSize = component.getSize(); - - if ((componentSize.width < 1) || (componentSize.height < 1)) - return; - - Dimension frameSize = frame.getSize(); - int newFrameWidth = frameSize.width + width - componentSize.width; - int newFrameHeight - = frameSize.height + height - componentSize.height; - - // Respect the minimum size. - Dimension minSize = frame.getMinimumSize(); - - if (newFrameWidth < minSize.width) - newFrameWidth = minSize.width; - if (newFrameHeight < minSize.height) - newFrameHeight = minSize.height; - - // Don't get bigger than the screen. - Rectangle screenBounds - = frame.getGraphicsConfiguration().getBounds(); - - if (newFrameWidth > screenBounds.width) - newFrameWidth = screenBounds.width; - if (newFrameHeight > screenBounds.height) - newFrameHeight = screenBounds.height; - - /* - * If we're going to make too small a change, don't even bother. - * Besides, we don't want some weird recursive resizing. - * Additionally, do not reduce the Frame size. - */ - boolean changeWidth = ((newFrameWidth - frameSize.width) > 1); - boolean changeHeight = ((newFrameHeight - frameSize.height) > 1); - - if (changeWidth || changeHeight) - { - if (!changeWidth) - newFrameWidth = frameSize.width; - else if (!changeHeight) - newFrameHeight = frameSize.height; - - /* - * The latest requirement with respect to the behavior upon - * resizing is to center the Frame. - */ - int newFrameX - = screenBounds.x - + (screenBounds.width - newFrameWidth) / 2; - int newFrameY - = screenBounds.y - + (screenBounds.height - newFrameHeight) / 2; - - // Do not let the top left go out of the screen. - if (newFrameX < screenBounds.x) - newFrameX = screenBounds.x; - if (newFrameY < screenBounds.y) - newFrameY = screenBounds.y; - - frame.setBounds( - newFrameX, newFrameY, - newFrameWidth, newFrameHeight); - - /* - * Make sure that the component which originally requested the - * update to the size of the frame realizes the change as soon - * as possible; otherwise, it may request yet another update. - */ - if (frame.isDisplayable()) - { - if (frame.isValid()) - frame.doLayout(); - else - frame.validate(); - frame.repaint(); - } - else - frame.doLayout(); - } - } - } - - /** - * Returns the frame of the call window. - * - * @return the frame of the call window - */ - public JFrame getFrame() - { - return this; - } - - /** - * Overrides getMinimumSize and checks the minimum size that - * is needed to display buttons and use it for minimum size if - * needed. - * @return minimum size. - */ - @Override - public Dimension getMinimumSize() - { - Dimension minSize = super.getMinimumSize(); - - if(callPanel != null) - { - int minButtonWidth = callPanel.getMinimumButtonWidth(); - - if(minButtonWidth > minSize.getWidth()) - minSize = new Dimension(minButtonWidth, 300); - } - - return minSize; - } - - /** - * Indicates if the given callPanel is currently visible. - * - * @param callPanel the CallPanel, for which we verify - * @return true if the given call container is visible in this - * call window, otherwise - false - */ - public boolean isCallVisible(CallPanel callPanel) - { - return this.callPanel.equals(callPanel) ? isVisible() : false; - } - - /** - * {@inheritDoc} - */ - public boolean isFullScreen() - { - return isFullScreen(getFrame()); - } - - /** - * Determines whether a specific Window is displayed in full-screen - * mode. - * - * @param window the Window to be checked whether it is displayed - * in full-screen mode - * @return true if the specified window is displayed in - * full-screen mode; otherwise, false - */ - public static boolean isFullScreen(Window window) - { - GraphicsConfiguration graphicsConfiguration - = window.getGraphicsConfiguration(); - - if (graphicsConfiguration != null) - { - GraphicsDevice device = graphicsConfiguration.getDevice(); - - if (device != null) - return window.equals(device.getFullScreenWindow()); - } - return false; - } - - /** - * {@inheritDoc} - */ - public void setFullScreen(boolean fullScreen) - { - GraphicsConfiguration graphicsConfiguration - = getGraphicsConfiguration(); - - if (graphicsConfiguration != null) - { - GraphicsDevice device = graphicsConfiguration.getDevice(); - - if (device != null) - { - boolean thisIsFullScreen = equals(device.getFullScreenWindow()); - boolean firePropertyChange = false; - boolean setVisible = isVisible(); - - try - { - if (fullScreen) - { - if (!thisIsFullScreen) - { - /* - * XXX The setUndecorated method will only work if - * this Window is not displayable. - */ - windowDispose(); - setUndecorated(true); - - device.setFullScreenWindow(this); - firePropertyChange = true; - } - } - else if (thisIsFullScreen) - { - /* - * XXX The setUndecorated method will only work if this - * Window is not displayable. - */ - windowDispose(); - setUndecorated(false); - - device.setFullScreenWindow(null); - firePropertyChange = true; - } - - if (firePropertyChange) - { - if (fullScreen) - { - addWindowStateListener(windowStateListener); - - /* - * If full-screen mode, a black background is the - * most common. - */ - getContentPane().setBackground(Color.BLACK); - } - else - { - removeWindowStateListener(windowStateListener); - - /* - * In windowed mode, a system-defined background is - * the most common. - */ - getContentPane().setBackground(null); - } - - firePropertyChange( - PROP_FULL_SCREEN, - thisIsFullScreen, - fullScreen); - } - } - finally - { - /* - * Regardless of whether this Window successfully entered or - * exited full-screen mode, make sure that remains visible. - */ - if (setVisible) - setVisible(true); - } - } - } - } -} +package net.java.sip.communicator.impl.gui.main.call; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.plugin.desktoputil.*; + +/** + * The dialog created for a given call. + * + * @author Yana Stamcheva + * @author Adam Netocny + * @author Lyubomir Marinov + */ +public class CallDialog + extends SIPCommFrame + implements CallContainer, + CallTitleListener +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Enabling force minimized mode will always open call dialog minimized. + * The call dialog still can be shown, but by default it will be minimized. + */ + private static final String FORCE_MINIMIZED_MODE + = "net.java.sip.communicator.impl.gui.main.call.FORCE_MINIMIZED_MODE"; + + /** + * Finds a Container which is an ancestor of a specific + * Component, has a set preferredSize and is closest to + * the specified Component up the ancestor hierarchy. + * + * @param component the Component whose ancestor hierarchy is to be + * searched upwards + * @return a Container, if any, which is an ancestor of the + * specified component, has a set preferredSize and is + * closest to the specified component up the ancestor hierarchy + */ + private static Container findClosestAncestorWithSetPreferredSize( + Component component) + { + if ((component instanceof Container) && component.isPreferredSizeSet()) + return (Container) component; + else + { + Container parent; + + while ((parent = component.getParent()) != null) + { + if (parent.isPreferredSizeSet()) + return parent; + else + component = parent; + } + return null; + } + } + + /** + * The panel, where all call components are added. + */ + private CallPanel callPanel; + + private final WindowStateListener windowStateListener + = new WindowStateListener() + { + public void windowStateChanged(WindowEvent ev) + { + switch (ev.getID()) + { + case WindowEvent.WINDOW_DEACTIVATED: + case WindowEvent.WINDOW_ICONIFIED: + case WindowEvent.WINDOW_LOST_FOCUS: + setFullScreen(false); + break; + } + } + }; + + /** + * Creates a CallDialog by specifying the underlying call panel. + */ + public CallDialog() + { + super(true, false); + + setMinimumSize(new Dimension(360, 300)); + } + + /** + * Adds a call panel. + * + * @param callPanel the call panel to add to this dialog + */ + public void addCallPanel(CallPanel callPanel) + { + this.callPanel = callPanel; + + getContentPane().add(callPanel); + + callPanel.addCallTitleListener(this); + setTitle(callPanel.getCallTitle()); + + if (!isVisible()) + { + pack(); + + // checks whether we need to open the call dialog in minimized mode + if(GuiActivator.getConfigurationService() + .getBoolean(FORCE_MINIMIZED_MODE, false)) + { + setState(ICONIFIED); + } + setVisible(true); + } + } + + /** + * Called when the title of the given CallPanel changes. + * + * @param callPanel the CallPanel, which title has changed + */ + public void callTitleChanged(CallPanel callPanel) + { + if (this.callPanel.equals(callPanel)) + setTitle(callPanel.getCallTitle()); + } + + /** + * {@inheritDoc} + * + * Hang ups the call/telephony conference depicted by this + * CallDialog on close. + */ + @Override + protected void close(boolean escape) + { + if (escape) + { + /* + * In full-screen mode, ESC does not close this CallDialog but exits + * from full-screen to windowed mode. + */ + if (isFullScreen()) + { + setFullScreen(false); + return; + } + } + else + { + /* + * If the window has been closed by clicking the X button or + * pressing the key combination corresponding to the same button we + * close the window first and then perform all hang up operations. + */ + + callPanel.disposeCallInfoFrame(); + // We hide the window here. It will be disposed when the call has + // been ended. + setVisible(false); + } + + // Then perform hang up operations. + callPanel.actionPerformedOnHangupButton(escape); + } + + /** + * {@inheritDoc} + * + * The delay implemented by CallDialog is 5 seconds. + */ + public void close(final CallPanel callPanel, boolean delay) + { + if (this.callPanel.equals(callPanel)) + { + if (delay) + { + Timer timer + = new Timer( + 5000, + new ActionListener() + { + public void actionPerformed(ActionEvent ev) + { + dispose(); + } + }); + + timer.setRepeats(false); + timer.start(); + } + else + { + dispose(); + } + } + } + + /** + * {@inheritDoc} + * + * CallDialog prepares the CallPanel it contains for + * garbage collection. + */ + @Override + public void dispose() + { + super.dispose(); + + /* + * Technically, CallManager adds/removes the callPanel to/from this + * instance. It may want to just move it to another CallContainer so it + * does not sound right that we are disposing of it. But we do not have + * such a case at this time so try to reduce the risk of memory leaks. + */ + if (this.callPanel != null) + { + callPanel.disposeCallInfoFrame(); + callPanel.dispose(); + } + } + + /** + * {@inheritDoc} + * + * Attempts to adjust the size of this Frame as requested in the + * AWT event dispatching thread. + *

    + * The method may be executed on the AWT event dispatching thread only + * because whoever is making the decision to request an adjustment of the + * Frame size in relation to a AWT Component should be analyzing that same + * Component in the AWT event dispatching thread only. + *

    + * + * @throws RuntimeException if the method is not called on the AWT event + * dispatching thread + */ + public void ensureSize(Component component, int width, int height) + { + CallManager.assertIsEventDispatchingThread(); + + Frame frame = CallPeerRendererUtils.getFrame(component); + + if (frame == null) + return; + else if ((frame.getExtendedState() & Frame.MAXIMIZED_BOTH) + == Frame.MAXIMIZED_BOTH) + { + /* + * Forcing the size of a Component which is displayed in a maximized + * window does not sound like anything we want to do. + */ + return; + } + else if (frame.equals( + frame.getGraphicsConfiguration().getDevice() + .getFullScreenWindow())) + { + /* + * Forcing the size of a Component which is displayed in a + * full-screen window does not sound like anything we want to do. + */ + return; + } + else if (!frame.equals(this)) + { + /* This Frame will try to adjust only its own size. */ + return; + } + else if ((component.getHeight() >= height) + && (component.getWidth() >= width)) + { + /* + * We will only enlarge the frame size. If the component has already + * been given at least what it is requesting, do not enlarge the + * frame size because the whole calculation is prone to inaccuracy. + */ + return; + } + else + { + /* + * If there is no callPanel, it is unlikely that this CallDialog + * will be asked to ensureSize. Anyway, support the scenario just in + * case. In light of the absence of a callPanel to guide this + * CallDialog about the preferred size, we do not have much of a + * choice but to trust the method arguments. + */ + if (callPanel != null) + { + /* + * If there is a callPanel, we are likely to get a much better + * estimation about the preferred size by asking the callPanel + * rather than by trusting the method arguments. For example, + * the visual Component displaying the video streaming from the + * local user/peer to the remote peer(s) will think that its + * preferred size is the one to base this Frame's size on but + * that may be misleading because the local video may not be + * displayed with its preferred size even if this Frame's size + * will accommodate it. + */ + /* + * Just asking the callPanel about its preferredSize would've + * been terrificly great. Unfortunately, that is presently + * futile because the callPanel may have a preferredSize while + * we are still required to display visual Components displaying + * video in their non-scaled size. The same goes for any + * Container which is an ancestor of the specified component. + */ + Container ancestor + = findClosestAncestorWithSetPreferredSize(component); + + if (ancestor == null) + ancestor = callPanel; + /* + * If the ancestor has a forced preferredSize, its LayoutManager + * may be able to give a good enough estimation. + */ + if (ancestor.isPreferredSizeSet()) + { + LayoutManager ancestorLayout = ancestor.getLayout(); + + if (ancestorLayout != null) + { + Dimension preferredLayoutSize + = ancestorLayout.preferredLayoutSize(ancestor); + + if (preferredLayoutSize != null) + { + component = ancestor; + width = preferredLayoutSize.width; + height = preferredLayoutSize.height; + } + } + } + else + { + /* + * If the ancestor doesn't have a preferredSize forced, then + * we may think that it will calculate an appropriate + * preferredSize itself. + */ + Dimension prefSize = ancestor.getPreferredSize(); + + if (prefSize != null) + { + component = ancestor; + width = prefSize.width; + height = prefSize.height; + } + } + } + + /* + * If the component (which may be an ancestor of the Component + * specified as an argument to the ensureSize method at this point) + * has not been given a size, we will make a mistake if we try to + * use it for the purposes of determining how much this Frame is to + * be enlarged. + */ + Dimension componentSize = component.getSize(); + + if ((componentSize.width < 1) || (componentSize.height < 1)) + return; + + Dimension frameSize = frame.getSize(); + int newFrameWidth = frameSize.width + width - componentSize.width; + int newFrameHeight + = frameSize.height + height - componentSize.height; + + // Respect the minimum size. + Dimension minSize = frame.getMinimumSize(); + + if (newFrameWidth < minSize.width) + newFrameWidth = minSize.width; + if (newFrameHeight < minSize.height) + newFrameHeight = minSize.height; + + // Don't get bigger than the screen. + Rectangle screenBounds + = frame.getGraphicsConfiguration().getBounds(); + + if (newFrameWidth > screenBounds.width) + newFrameWidth = screenBounds.width; + if (newFrameHeight > screenBounds.height) + newFrameHeight = screenBounds.height; + + /* + * If we're going to make too small a change, don't even bother. + * Besides, we don't want some weird recursive resizing. + * Additionally, do not reduce the Frame size. + */ + boolean changeWidth = ((newFrameWidth - frameSize.width) > 1); + boolean changeHeight = ((newFrameHeight - frameSize.height) > 1); + + if (changeWidth || changeHeight) + { + if (!changeWidth) + newFrameWidth = frameSize.width; + else if (!changeHeight) + newFrameHeight = frameSize.height; + + /* + * The latest requirement with respect to the behavior upon + * resizing is to center the Frame. + */ + int newFrameX + = screenBounds.x + + (screenBounds.width - newFrameWidth) / 2; + int newFrameY + = screenBounds.y + + (screenBounds.height - newFrameHeight) / 2; + + // Do not let the top left go out of the screen. + if (newFrameX < screenBounds.x) + newFrameX = screenBounds.x; + if (newFrameY < screenBounds.y) + newFrameY = screenBounds.y; + + frame.setBounds( + newFrameX, newFrameY, + newFrameWidth, newFrameHeight); + + /* + * Make sure that the component which originally requested the + * update to the size of the frame realizes the change as soon + * as possible; otherwise, it may request yet another update. + */ + if (frame.isDisplayable()) + { + if (frame.isValid()) + frame.doLayout(); + else + frame.validate(); + frame.repaint(); + } + else + frame.doLayout(); + } + } + } + + /** + * Returns the frame of the call window. + * + * @return the frame of the call window + */ + public JFrame getFrame() + { + return this; + } + + /** + * Overrides getMinimumSize and checks the minimum size that + * is needed to display buttons and use it for minimum size if + * needed. + * @return minimum size. + */ + @Override + public Dimension getMinimumSize() + { + Dimension minSize = super.getMinimumSize(); + + if(callPanel != null) + { + int minButtonWidth = callPanel.getMinimumButtonWidth(); + + if(minButtonWidth > minSize.getWidth()) + minSize = new Dimension(minButtonWidth, 300); + } + + return minSize; + } + + /** + * Indicates if the given callPanel is currently visible. + * + * @param callPanel the CallPanel, for which we verify + * @return true if the given call container is visible in this + * call window, otherwise - false + */ + public boolean isCallVisible(CallPanel callPanel) + { + return this.callPanel.equals(callPanel) ? isVisible() : false; + } + + /** + * {@inheritDoc} + */ + public boolean isFullScreen() + { + return isFullScreen(getFrame()); + } + + /** + * Determines whether a specific Window is displayed in full-screen + * mode. + * + * @param window the Window to be checked whether it is displayed + * in full-screen mode + * @return true if the specified window is displayed in + * full-screen mode; otherwise, false + */ + public static boolean isFullScreen(Window window) + { + GraphicsConfiguration graphicsConfiguration + = window.getGraphicsConfiguration(); + + if (graphicsConfiguration != null) + { + GraphicsDevice device = graphicsConfiguration.getDevice(); + + if (device != null) + return window.equals(device.getFullScreenWindow()); + } + return false; + } + + /** + * {@inheritDoc} + */ + public void setFullScreen(boolean fullScreen) + { + GraphicsConfiguration graphicsConfiguration + = getGraphicsConfiguration(); + + if (graphicsConfiguration != null) + { + GraphicsDevice device = graphicsConfiguration.getDevice(); + + if (device != null) + { + boolean thisIsFullScreen = equals(device.getFullScreenWindow()); + boolean firePropertyChange = false; + boolean setVisible = isVisible(); + + try + { + if (fullScreen) + { + if (!thisIsFullScreen) + { + /* + * XXX The setUndecorated method will only work if + * this Window is not displayable. + */ + windowDispose(); + setUndecorated(true); + + device.setFullScreenWindow(this); + firePropertyChange = true; + } + } + else if (thisIsFullScreen) + { + /* + * XXX The setUndecorated method will only work if this + * Window is not displayable. + */ + windowDispose(); + setUndecorated(false); + + device.setFullScreenWindow(null); + firePropertyChange = true; + } + + if (firePropertyChange) + { + if (fullScreen) + { + addWindowStateListener(windowStateListener); + + /* + * If full-screen mode, a black background is the + * most common. + */ + getContentPane().setBackground(Color.BLACK); + } + else + { + removeWindowStateListener(windowStateListener); + + /* + * In windowed mode, a system-defined background is + * the most common. + */ + getContentPane().setBackground(null); + } + + firePropertyChange( + PROP_FULL_SCREEN, + thisIsFullScreen, + fullScreen); + } + } + finally + { + /* + * Regardless of whether this Window successfully entered or + * exited full-screen mode, make sure that remains visible. + */ + if (setVisible) + setVisible(true); + } + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallTransferHandler.java b/src/net/java/sip/communicator/impl/gui/main/call/CallTransferHandler.java index 54f48ee..6235e1c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallTransferHandler.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallTransferHandler.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,276 +15,276 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call; - -import java.awt.datatransfer.*; -import java.awt.im.*; -import java.io.*; -import java.util.*; - -import javax.swing.*; - -import org.jitsi.service.resources.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.contactlist.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * A TransferHandler that handles dropping of UIContacts or - * String addresses on a CallConference. Dropping such data on - * the CallDialog will turn a one-to-one Call into a telephony - * conference. - * - * @author Yana Stamcheva - */ -public class CallTransferHandler - extends ExtendedTransferHandler -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The data flavor used when transferring UIContacts. - */ - protected static final DataFlavor uiContactDataFlavor - = new DataFlavor(UIContact.class, "UIContact"); - - /** - * The logger. - */ - private static final Logger logger - = Logger.getLogger(CallTransferHandler.class); - - /** - * The CallConference into which the dropped callees are to be - * invited. - */ - private final CallConference callConference; - - /** - * Initializes a new CallTransferHandler instance which is to - * invite dropped callees to a telephony conference specified by a specific - * Call which participates in it. - * - * @param call the Call which specifies the telephony conference to - * which dropped callees are to be invited - */ - public CallTransferHandler(Call call) - { - this(call.getConference()); - } - - /** - * Initializes a new CallTransferHandler instance which is to - * invite dropped callees to a specific CallConference. - * - * @param callConference the CallConference to which dropped - * callees are to be invited - */ - public CallTransferHandler(CallConference callConference) - { - this.callConference = callConference; - } - - /** - * Indicates whether a component will accept an import of the given - * set of data flavors prior to actually attempting to import it. We return - * true to indicate that the transfer with at least one of the - * given flavors would work and false to reject the transfer. - *

    - * @param comp component - * @param flavor the data formats available - * @return true if the data can be inserted into the component, false - * otherwise - * @throws NullPointerException if support is {@code null} - */ - @Override - public boolean canImport(JComponent comp, DataFlavor[] flavor) - { - for (DataFlavor f : flavor) - { - if (f.equals(DataFlavor.stringFlavor) - || f.equals(uiContactDataFlavor)) - { - return (comp instanceof JPanel); - } - } - return false; - } - - /** - * Handles transfers to the chat panel from the clip board or a - * DND drop operation. The Transferable parameter contains the - * data that needs to be imported. - *

    - * @param comp the component to receive the transfer; - * @param t the data to import - * @return true if the data was inserted into the component and false - * otherwise - */ - @Override - public boolean importData(JComponent comp, Transferable t) - { - String callee = null; - ProtocolProviderService provider = null; - - if (t.isDataFlavorSupported(uiContactDataFlavor)) - { - Object o = null; - - try - { - o = t.getTransferData(uiContactDataFlavor); - } - catch (UnsupportedFlavorException e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to drop meta contact.", e); - } - catch (IOException e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to drop meta contact.", e); - } - - if (o instanceof ContactNode) - { - UIContact uiContact = ((ContactNode) o).getContactDescriptor(); - Iterator contactDetails - = uiContact - .getContactDetailsForOperationSet( - OperationSetBasicTelephony.class) - .iterator(); - - while (contactDetails.hasNext()) - { - UIContactDetail detail = contactDetails.next(); - ProtocolProviderService detailProvider - = detail.getPreferredProtocolProvider( - OperationSetBasicTelephony.class); - - if (detailProvider != null) - { - /* - * Currently for videobridge conferences we only support - * adding contacts via the account with the videobridge - */ - if (callConference.isJitsiVideobridge()) - { - for (Call call : callConference.getCalls()) - { - if (detailProvider == call.getProtocolProvider()) - { - callee = detail.getAddress(); - provider = detailProvider; - break; - } - } - } - else - { - callee = detail.getAddress(); - provider = detailProvider; - break; - } - } - } - - if (callee == null) - { - /* - * It turns out that the error message to be reported would - * like to display information about the account which could - * not add the dropped callee to the telephony conference. - * Unfortunately, a telephony conference may have multiple - * accounts involved. Anyway, choose the first account - * involved in the telephony conference. - */ - ProtocolProviderService callProvider - = callConference.getCalls().get(0) - .getProtocolProvider(); - - ResourceManagementService resources - = GuiActivator.getResources(); - AccountID accountID = callProvider.getAccountID(); - - new ErrorDialog(null, - resources.getI18NString("service.gui.ERROR"), - resources.getI18NString( - "service.gui.CALL_NOT_SUPPORTING_PARTICIPANT", - new String[] - { - accountID.getService(), - accountID.getUserID(), - uiContact.getDisplayName() - })) - .showDialog(); - } - } - } - else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) - { - InputContext inputContext = comp.getInputContext(); - - if (inputContext != null) - inputContext.endComposition(); - - try - { - BufferedReader reader - = new BufferedReader( - DataFlavor.stringFlavor.getReaderForText(t)); - - try - { - String line; - StringBuilder calleeBuilder = new StringBuilder(); - - while ((line = reader.readLine()) != null) - calleeBuilder.append(line); - - callee = calleeBuilder.toString(); - /* - * The value of the local variable provider will be null - * because we have a String only and hence we have no - * associated ProtocolProviderService. - * CallManager.inviteToConferenceCall will accept it. - */ - } - finally - { - reader.close(); - } - } - catch (UnsupportedFlavorException e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to drop string.", e); - } - catch (IOException e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to drop string.", e); - } - } - - if (callee == null) - return false; - else - { - Map> callees - = new HashMap>(); - - callees.put(provider, Arrays.asList(callee)); - CallManager.inviteToConferenceCall(callees, callConference); - - return true; - } - } -} +package net.java.sip.communicator.impl.gui.main.call; + +import java.awt.datatransfer.*; +import java.awt.im.*; +import java.io.*; +import java.util.*; + +import javax.swing.*; + +import org.jitsi.service.resources.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.contactlist.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * A TransferHandler that handles dropping of UIContacts or + * String addresses on a CallConference. Dropping such data on + * the CallDialog will turn a one-to-one Call into a telephony + * conference. + * + * @author Yana Stamcheva + */ +public class CallTransferHandler + extends ExtendedTransferHandler +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The data flavor used when transferring UIContacts. + */ + protected static final DataFlavor uiContactDataFlavor + = new DataFlavor(UIContact.class, "UIContact"); + + /** + * The logger. + */ + private static final Logger logger + = Logger.getLogger(CallTransferHandler.class); + + /** + * The CallConference into which the dropped callees are to be + * invited. + */ + private final CallConference callConference; + + /** + * Initializes a new CallTransferHandler instance which is to + * invite dropped callees to a telephony conference specified by a specific + * Call which participates in it. + * + * @param call the Call which specifies the telephony conference to + * which dropped callees are to be invited + */ + public CallTransferHandler(Call call) + { + this(call.getConference()); + } + + /** + * Initializes a new CallTransferHandler instance which is to + * invite dropped callees to a specific CallConference. + * + * @param callConference the CallConference to which dropped + * callees are to be invited + */ + public CallTransferHandler(CallConference callConference) + { + this.callConference = callConference; + } + + /** + * Indicates whether a component will accept an import of the given + * set of data flavors prior to actually attempting to import it. We return + * true to indicate that the transfer with at least one of the + * given flavors would work and false to reject the transfer. + *

    + * @param comp component + * @param flavor the data formats available + * @return true if the data can be inserted into the component, false + * otherwise + * @throws NullPointerException if support is {@code null} + */ + @Override + public boolean canImport(JComponent comp, DataFlavor[] flavor) + { + for (DataFlavor f : flavor) + { + if (f.equals(DataFlavor.stringFlavor) + || f.equals(uiContactDataFlavor)) + { + return (comp instanceof JPanel); + } + } + return false; + } + + /** + * Handles transfers to the chat panel from the clip board or a + * DND drop operation. The Transferable parameter contains the + * data that needs to be imported. + *

    + * @param comp the component to receive the transfer; + * @param t the data to import + * @return true if the data was inserted into the component and false + * otherwise + */ + @Override + public boolean importData(JComponent comp, Transferable t) + { + String callee = null; + ProtocolProviderService provider = null; + + if (t.isDataFlavorSupported(uiContactDataFlavor)) + { + Object o = null; + + try + { + o = t.getTransferData(uiContactDataFlavor); + } + catch (UnsupportedFlavorException e) + { + if (logger.isDebugEnabled()) + logger.debug("Failed to drop meta contact.", e); + } + catch (IOException e) + { + if (logger.isDebugEnabled()) + logger.debug("Failed to drop meta contact.", e); + } + + if (o instanceof ContactNode) + { + UIContact uiContact = ((ContactNode) o).getContactDescriptor(); + Iterator contactDetails + = uiContact + .getContactDetailsForOperationSet( + OperationSetBasicTelephony.class) + .iterator(); + + while (contactDetails.hasNext()) + { + UIContactDetail detail = contactDetails.next(); + ProtocolProviderService detailProvider + = detail.getPreferredProtocolProvider( + OperationSetBasicTelephony.class); + + if (detailProvider != null) + { + /* + * Currently for videobridge conferences we only support + * adding contacts via the account with the videobridge + */ + if (callConference.isJitsiVideobridge()) + { + for (Call call : callConference.getCalls()) + { + if (detailProvider == call.getProtocolProvider()) + { + callee = detail.getAddress(); + provider = detailProvider; + break; + } + } + } + else + { + callee = detail.getAddress(); + provider = detailProvider; + break; + } + } + } + + if (callee == null) + { + /* + * It turns out that the error message to be reported would + * like to display information about the account which could + * not add the dropped callee to the telephony conference. + * Unfortunately, a telephony conference may have multiple + * accounts involved. Anyway, choose the first account + * involved in the telephony conference. + */ + ProtocolProviderService callProvider + = callConference.getCalls().get(0) + .getProtocolProvider(); + + ResourceManagementService resources + = GuiActivator.getResources(); + AccountID accountID = callProvider.getAccountID(); + + new ErrorDialog(null, + resources.getI18NString("service.gui.ERROR"), + resources.getI18NString( + "service.gui.CALL_NOT_SUPPORTING_PARTICIPANT", + new String[] + { + accountID.getService(), + accountID.getUserID(), + uiContact.getDisplayName() + })) + .showDialog(); + } + } + } + else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) + { + InputContext inputContext = comp.getInputContext(); + + if (inputContext != null) + inputContext.endComposition(); + + try + { + BufferedReader reader + = new BufferedReader( + DataFlavor.stringFlavor.getReaderForText(t)); + + try + { + String line; + StringBuilder calleeBuilder = new StringBuilder(); + + while ((line = reader.readLine()) != null) + calleeBuilder.append(line); + + callee = calleeBuilder.toString(); + /* + * The value of the local variable provider will be null + * because we have a String only and hence we have no + * associated ProtocolProviderService. + * CallManager.inviteToConferenceCall will accept it. + */ + } + finally + { + reader.close(); + } + } + catch (UnsupportedFlavorException e) + { + if (logger.isDebugEnabled()) + logger.debug("Failed to drop string.", e); + } + catch (IOException e) + { + if (logger.isDebugEnabled()) + logger.debug("Failed to drop string.", e); + } + } + + if (callee == null) + return false; + else + { + Map> callees + = new HashMap>(); + + callees.put(provider, Arrays.asList(callee)); + CallManager.inviteToConferenceCall(callees, callConference); + + return true; + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java index 3e823ba..c56a415 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/FullScreenLayout.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,176 +15,176 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call; - -import java.awt.*; -import java.util.*; -import java.util.List; - -/** - * Implements a LayoutManager for the full-screen Call - * display. - * - * @author Lyubomir Marinov - */ -public class FullScreenLayout - implements LayoutManager -{ - public static final String CENTER = "CENTER"; - - public static final String SOUTH = "SOUTH"; - - private Component center; - - /** - * The indicator which determines whether {@link #south} is to be laid out - * on top of {@link #center} i.e. as an overlay. - */ - private final boolean overlay; - - private Component south; - - /** - * The vertical gap between the center and the south components. - */ - private int yGap = 0; - - /** - * Initializes a new FullScreenLayout instance. - * - * @param overlay true to lay out the Component at - * {@link #SOUTH} on top of the Component at {@link #CENTER} i.e as - * an overlay; otherwise, false - * @oaram yGap the gap betwen the center and the south component - */ - public FullScreenLayout(boolean overlay, int yGap) - { - this.overlay = overlay; - this.yGap = yGap; - } - - /** - * Adds the given component to this layout. - * - * @param name the name of the constraint (CENTER or SOUTH) - * @param comp the component to add to this layout - */ - public void addLayoutComponent(String name, Component comp) - { - if (CENTER.equals(name)) - center = comp; - else if (SOUTH.equals(name)) - south = comp; - } - - /** - * Gets a List of the Components to be laid out by this - * LayoutManager i.e. the non-null of {@link #center} - * and {@link #south}. - * - * @return a List of the Components to be laid out by this - * LayoutManager - */ - private List getLayoutComponents() - { - List layoutComponents = new ArrayList(2); - - if (center != null) - layoutComponents.add(center); - if (south != null) - layoutComponents.add(south); - return layoutComponents; - } - - /** - * Lays out the components added in the given parent container - * - * @param parent the parent container to lay out - */ - public void layoutContainer(Container parent) - { - int southWidth; - int southHeight; - - if (south == null) - { - southWidth = southHeight = 0; - } - else - { - Dimension southSize = south.getPreferredSize(); - - southWidth = southSize.width; - southHeight = southSize.height; - } - - Dimension parentSize = parent.getSize(); - - if (center != null) - { - /* - * If the Component at the SOUTH is not to be shown as an overlay, - * make room for it bellow the Component at the CENTER. - */ - int yOffset = overlay ? 0 : southHeight + yGap; - - center.setBounds( - 0, - 0, - parentSize.width, - parentSize.height - yOffset); - } - if (south != null) - { - south.setBounds( - (parentSize.width - southWidth) / 2, - parentSize.height - southHeight, - southWidth, - southHeight); - } - } - - public Dimension minimumLayoutSize(Container parent) - { - List components = getLayoutComponents(); - Dimension size = new Dimension(0, 0); - - for (Component component : components) - { - Dimension componentSize = component.getMinimumSize(); - - size.width = Math.max(size.width, componentSize.width); - if (overlay) - size.height = Math.max(size.height, componentSize.height); - else - size.height += componentSize.height; - } - return size; - } - - public Dimension preferredLayoutSize(Container parent) - { - List components = getLayoutComponents(); - Dimension size = new Dimension(0, 0); - - for (Component component : components) - { - Dimension componentSize = component.getPreferredSize(); - - size.width = Math.max(size.width, componentSize.width); - if (overlay) - size.height = Math.max(size.height, componentSize.height); - else - size.height += componentSize.height; - } - return size; - } - - public void removeLayoutComponent(Component comp) - { - if (comp.equals(center)) - center = null; - else if (comp.equals(south)) - south = null; - } -} +package net.java.sip.communicator.impl.gui.main.call; + +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * Implements a LayoutManager for the full-screen Call + * display. + * + * @author Lyubomir Marinov + */ +public class FullScreenLayout + implements LayoutManager +{ + public static final String CENTER = "CENTER"; + + public static final String SOUTH = "SOUTH"; + + private Component center; + + /** + * The indicator which determines whether {@link #south} is to be laid out + * on top of {@link #center} i.e. as an overlay. + */ + private final boolean overlay; + + private Component south; + + /** + * The vertical gap between the center and the south components. + */ + private int yGap = 0; + + /** + * Initializes a new FullScreenLayout instance. + * + * @param overlay true to lay out the Component at + * {@link #SOUTH} on top of the Component at {@link #CENTER} i.e as + * an overlay; otherwise, false + * @oaram yGap the gap betwen the center and the south component + */ + public FullScreenLayout(boolean overlay, int yGap) + { + this.overlay = overlay; + this.yGap = yGap; + } + + /** + * Adds the given component to this layout. + * + * @param name the name of the constraint (CENTER or SOUTH) + * @param comp the component to add to this layout + */ + public void addLayoutComponent(String name, Component comp) + { + if (CENTER.equals(name)) + center = comp; + else if (SOUTH.equals(name)) + south = comp; + } + + /** + * Gets a List of the Components to be laid out by this + * LayoutManager i.e. the non-null of {@link #center} + * and {@link #south}. + * + * @return a List of the Components to be laid out by this + * LayoutManager + */ + private List getLayoutComponents() + { + List layoutComponents = new ArrayList(2); + + if (center != null) + layoutComponents.add(center); + if (south != null) + layoutComponents.add(south); + return layoutComponents; + } + + /** + * Lays out the components added in the given parent container + * + * @param parent the parent container to lay out + */ + public void layoutContainer(Container parent) + { + int southWidth; + int southHeight; + + if (south == null) + { + southWidth = southHeight = 0; + } + else + { + Dimension southSize = south.getPreferredSize(); + + southWidth = southSize.width; + southHeight = southSize.height; + } + + Dimension parentSize = parent.getSize(); + + if (center != null) + { + /* + * If the Component at the SOUTH is not to be shown as an overlay, + * make room for it bellow the Component at the CENTER. + */ + int yOffset = overlay ? 0 : southHeight + yGap; + + center.setBounds( + 0, + 0, + parentSize.width, + parentSize.height - yOffset); + } + if (south != null) + { + south.setBounds( + (parentSize.width - southWidth) / 2, + parentSize.height - southHeight, + southWidth, + southHeight); + } + } + + public Dimension minimumLayoutSize(Container parent) + { + List components = getLayoutComponents(); + Dimension size = new Dimension(0, 0); + + for (Component component : components) + { + Dimension componentSize = component.getMinimumSize(); + + size.width = Math.max(size.width, componentSize.width); + if (overlay) + size.height = Math.max(size.height, componentSize.height); + else + size.height += componentSize.height; + } + return size; + } + + public Dimension preferredLayoutSize(Container parent) + { + List components = getLayoutComponents(); + Dimension size = new Dimension(0, 0); + + for (Component component : components) + { + Dimension componentSize = component.getPreferredSize(); + + size.width = Math.max(size.width, componentSize.width); + if (overlay) + size.height = Math.max(size.height, componentSize.height); + else + size.height += componentSize.height; + } + return size; + } + + public void removeLayoutComponent(Component comp) + { + if (comp.equals(center)) + center = null; + else if (comp.equals(south)) + south = null; + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java index 2e2ed5b..b49e0a3 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,117 +15,117 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.skin.*; - -import org.jitsi.service.neomedia.*; - -/** - * Base class for security panels that show encryption specific UI controls. - * - * @author Ingo Bauersachs - */ -public abstract class SecurityPanel - extends FadeInBalloonPanel - implements Skinnable -{ - /** - * The currently used security control. - */ - protected T securityControl; - - /** - * Create security panel using the security control. - * @param securityControl - */ - public SecurityPanel(T securityControl) - { - this.securityControl = securityControl; - } - - /** - * The currently used security control. - * @return - */ - public T getSecurityControl() - { - return securityControl; - } - - /** - * The currently used security control. - * @return - */ - public void setSecurityControl(T securityControl) - { - this.securityControl = securityControl; - } - - /** - * Creates the security panel depending on the concrete implementation of - * the passed security controller. - * - * @param srtpControl the security controller that provides the information - * to be shown on the UI - * @return An instance of a {@link SecurityPanel} for the security - * controller or an {@link TransparentPanel} if the controller is - * unknown or does not have any controls to show. - */ - public static SecurityPanel create( - SwingCallPeerRenderer peerRenderer, - CallPeer callPeer, - SrtpControl srtpControl) - { - if(srtpControl instanceof ZrtpControl) - { - return - new ZrtpSecurityPanel( - peerRenderer, - callPeer, - (ZrtpControl) srtpControl); - } - else - { - return - new SecurityPanel(srtpControl) - { - public void loadSkin() {} - - @Override - public void securityOn(CallPeerSecurityOnEvent evt) {} - - @Override - public void securityOff(CallPeerSecurityOffEvent evt) {} - - @Override - public void securityTimeout( - CallPeerSecurityTimeoutEvent evt) {} - }; - } - } - - /** - * Indicates that the security is turned on. - * - * @param evt details about the event that caused this message. - */ - public abstract void securityOn(CallPeerSecurityOnEvent evt); - - /** - * Indicates that the security is turned off. - * - * @param evt details about the event that caused this message. - */ - public abstract void securityOff(CallPeerSecurityOffEvent evt); - - /** - * Indicates that the security is timeouted, is not supported by the - * other end. - * @param evt Details about the event that caused this message. - */ - public abstract void securityTimeout(CallPeerSecurityTimeoutEvent evt); -} +package net.java.sip.communicator.impl.gui.main.call; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.skin.*; + +import org.jitsi.service.neomedia.*; + +/** + * Base class for security panels that show encryption specific UI controls. + * + * @author Ingo Bauersachs + */ +public abstract class SecurityPanel + extends FadeInBalloonPanel + implements Skinnable +{ + /** + * The currently used security control. + */ + protected T securityControl; + + /** + * Create security panel using the security control. + * @param securityControl + */ + public SecurityPanel(T securityControl) + { + this.securityControl = securityControl; + } + + /** + * The currently used security control. + * @return + */ + public T getSecurityControl() + { + return securityControl; + } + + /** + * The currently used security control. + * @return + */ + public void setSecurityControl(T securityControl) + { + this.securityControl = securityControl; + } + + /** + * Creates the security panel depending on the concrete implementation of + * the passed security controller. + * + * @param srtpControl the security controller that provides the information + * to be shown on the UI + * @return An instance of a {@link SecurityPanel} for the security + * controller or an {@link TransparentPanel} if the controller is + * unknown or does not have any controls to show. + */ + public static SecurityPanel create( + SwingCallPeerRenderer peerRenderer, + CallPeer callPeer, + SrtpControl srtpControl) + { + if(srtpControl instanceof ZrtpControl) + { + return + new ZrtpSecurityPanel( + peerRenderer, + callPeer, + (ZrtpControl) srtpControl); + } + else + { + return + new SecurityPanel(srtpControl) + { + public void loadSkin() {} + + @Override + public void securityOn(CallPeerSecurityOnEvent evt) {} + + @Override + public void securityOff(CallPeerSecurityOffEvent evt) {} + + @Override + public void securityTimeout( + CallPeerSecurityTimeoutEvent evt) {} + }; + } + } + + /** + * Indicates that the security is turned on. + * + * @param evt details about the event that caused this message. + */ + public abstract void securityOn(CallPeerSecurityOnEvent evt); + + /** + * Indicates that the security is turned off. + * + * @param evt details about the event that caused this message. + */ + public abstract void securityOff(CallPeerSecurityOffEvent evt); + + /** + * Indicates that the security is timeouted, is not supported by the + * other end. + * @param evt Details about the event that caused this message. + */ + public abstract void securityTimeout(CallPeerSecurityTimeoutEvent evt); +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/TransferCallDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/TransferCallDialog.java index f2f2bd2..982738b 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/TransferCallDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/TransferCallDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,140 +15,140 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; -import net.java.sip.communicator.impl.gui.utils.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * Represents a Dialog which allows specifying the target contact - * address of a transfer-call operation. - * - * @author Yana Stamcheva - */ -public class TransferCallDialog - extends OneChoiceInviteDialog -{ - /** - * The peer to transfer. - */ - private final CallPeer transferPeer; - - /** - * Creates a TransferCallDialog by specifying the peer to transfer - * @param peer the peer to transfer - */ - public TransferCallDialog(final CallPeer peer) - { - super(GuiActivator.getResources() - .getI18NString("service.gui.TRANSFER_CALL_TITLE")); - - this.transferPeer = peer; - - this.initContactListData(peer.getProtocolProvider()); - - this.setInfoText(GuiActivator.getResources() - .getI18NString("service.gui.TRANSFER_CALL_MSG")); - this.setOkButtonText(GuiActivator.getResources() - .getI18NString("service.gui.TRANSFER")); - - this.setMinimumSize(new Dimension(300, 300)); - - addOkButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - UIContact uiContact = getSelectedContact(); - - if (uiContact != null) - { - transferToContact(uiContact); - } - - setVisible(false); - dispose(); - } - }); - addCancelButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - }); - } - - /** - * Initializes contact list sources. - */ - private void initContactSources() - { - DemuxContactSourceService demuxCSService - = GuiActivator.getDemuxContactSourceService(); - - // If the DemuxContactSourceService isn't registered we use the default - // contact source set. - if (demuxCSService == null) - return; - - Iterator sourcesIter - = new ArrayList( - contactList.getContactSources()).iterator(); - - contactList.removeAllContactSources(); - - while (sourcesIter.hasNext()) - { - ContactSourceService contactSource - = sourcesIter.next().getContactSourceService(); - - contactList.addContactSource( - demuxCSService.createDemuxContactSource(contactSource)); - } - } - - /** - * Initializes the left contact list with the contacts that could be added - * to the current chat session. - * - * @param protocolProvider the protocol provider from which to initialize - * the contact list data - */ - private void initContactListData(ProtocolProviderService protocolProvider) - { - initContactSources(); - - contactList.addContactSource( - new ProtocolContactSourceServiceImpl( - protocolProvider, OperationSetBasicTelephony.class)); - contactList.addContactSource( - new StringContactSourceServiceImpl( - protocolProvider, OperationSetBasicTelephony.class)); - - contactList.applyDefaultFilter(); - } - - /** - * Transfer the transfer peer to the given UIContact. - * - * @param uiContact the contact to transfer to - */ - private void transferToContact(UIContact uiContact) - { - UIContactDetail contactDetail = uiContact - .getDefaultContactDetail( - OperationSetBasicTelephony.class); - - CallManager.transferCall( transferPeer, - contactDetail.getAddress()); - } -} +package net.java.sip.communicator.impl.gui.main.call; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * Represents a Dialog which allows specifying the target contact + * address of a transfer-call operation. + * + * @author Yana Stamcheva + */ +public class TransferCallDialog + extends OneChoiceInviteDialog +{ + /** + * The peer to transfer. + */ + private final CallPeer transferPeer; + + /** + * Creates a TransferCallDialog by specifying the peer to transfer + * @param peer the peer to transfer + */ + public TransferCallDialog(final CallPeer peer) + { + super(GuiActivator.getResources() + .getI18NString("service.gui.TRANSFER_CALL_TITLE")); + + this.transferPeer = peer; + + this.initContactListData(peer.getProtocolProvider()); + + this.setInfoText(GuiActivator.getResources() + .getI18NString("service.gui.TRANSFER_CALL_MSG")); + this.setOkButtonText(GuiActivator.getResources() + .getI18NString("service.gui.TRANSFER")); + + this.setMinimumSize(new Dimension(300, 300)); + + addOkButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + UIContact uiContact = getSelectedContact(); + + if (uiContact != null) + { + transferToContact(uiContact); + } + + setVisible(false); + dispose(); + } + }); + addCancelButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + setVisible(false); + dispose(); + } + }); + } + + /** + * Initializes contact list sources. + */ + private void initContactSources() + { + DemuxContactSourceService demuxCSService + = GuiActivator.getDemuxContactSourceService(); + + // If the DemuxContactSourceService isn't registered we use the default + // contact source set. + if (demuxCSService == null) + return; + + Iterator sourcesIter + = new ArrayList( + contactList.getContactSources()).iterator(); + + contactList.removeAllContactSources(); + + while (sourcesIter.hasNext()) + { + ContactSourceService contactSource + = sourcesIter.next().getContactSourceService(); + + contactList.addContactSource( + demuxCSService.createDemuxContactSource(contactSource)); + } + } + + /** + * Initializes the left contact list with the contacts that could be added + * to the current chat session. + * + * @param protocolProvider the protocol provider from which to initialize + * the contact list data + */ + private void initContactListData(ProtocolProviderService protocolProvider) + { + initContactSources(); + + contactList.addContactSource( + new ProtocolContactSourceServiceImpl( + protocolProvider, OperationSetBasicTelephony.class)); + contactList.addContactSource( + new StringContactSourceServiceImpl( + protocolProvider, OperationSetBasicTelephony.class)); + + contactList.applyDefaultFilter(); + } + + /** + * Transfer the transfer peer to the given UIContact. + * + * @param uiContact the contact to transfer to + */ + private void transferToContact(UIContact uiContact) + { + UIContactDetail contactDetail = uiContact + .getDefaultContactDetail( + OperationSetBasicTelephony.class); + + CallManager.transferCall( transferPeer, + contactDetail.getAddress()); + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceInviteDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceInviteDialog.java index 80eedc6..bb32858 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceInviteDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceInviteDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,570 +15,570 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call.conference; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import java.util.List; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.call.*; -import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; -import net.java.sip.communicator.impl.gui.utils.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * The invite dialog is the one shown when the user clicks on the conference - * button in the chat toolbar. - * - * @author Yana Stamcheva - * @author Lyubomir Marinov - */ -public class ConferenceInviteDialog - extends InviteDialog -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The account selector box. - */ - private final JComboBox accountSelectorBox = new JComboBox(); - - /** - * The last selected account. - */ - private Object lastSelectedAccount; - - /** - * The telephony conference into which this instance is to invite - * participants. - */ - private final CallConference conference; - - /** - * The current provider contact source. - */ - private ContactSourceService currentProviderContactSource; - - /** - * The current string contact source. - */ - private ContactSourceService currentStringContactSource; - - /** - * The previously selected protocol provider, with which this dialog has - * been instantiated. - */ - private ProtocolProviderService preselectedProtocolProvider; - - /** - * Indicates whether this conference invite dialog is associated with a - * Jitsi Videobridge invite. - */ - private final boolean isJitsiVideobridge; - - /** - * Initializes a new ConferenceInviteDialog instance which is to - * invite contacts/participants in a specific telephony conference. - * - * @param conference the telephony conference in which the new instance is - * to invite contacts/participants - */ - public ConferenceInviteDialog( - CallConference conference, - ProtocolProviderService preselectedProvider, - List protocolProviders, - final boolean isJitsiVideobridge) - { - // Set the correct dialog title depending if we're going to create a - // video bridge conference call - super((isJitsiVideobridge - ? GuiActivator.getResources() - .getI18NString("service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE") - : GuiActivator.getResources() - .getI18NString("service.gui.INVITE_CONTACT_TO_CALL")), - false); - - this.conference = conference; - this.preselectedProtocolProvider = preselectedProvider; - this.isJitsiVideobridge = isJitsiVideobridge; - - if (preselectedProtocolProvider == null) - initAccountSelectorPanel(protocolProviders); - - // init the list, as we check whether features are supported - // it may take some time if we have too much contacts - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - initContactSources(); - - // Initialize the list of contacts to select from. - if (preselectedProtocolProvider != null) - initContactListData(preselectedProtocolProvider); - else - initContactListData( - (ProtocolProviderService) accountSelectorBox - .getSelectedItem()); - } - }); - - this.addInviteButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - Collection selectedContacts - = destContactList.getContacts(null); - - if (selectedContacts != null && selectedContacts.size() > 0) - { - if (preselectedProtocolProvider == null) - preselectedProtocolProvider - = (ProtocolProviderService) accountSelectorBox - .getSelectedItem(); - - if (isJitsiVideobridge) - inviteJitsiVideobridgeContacts( preselectedProtocolProvider, - selectedContacts); - else - inviteContacts(selectedContacts); - - // Store the last used account in order to pre-select it - // next time. - ConfigurationUtils.setLastCallConferenceProvider( - preselectedProtocolProvider); - - dispose(); - } - else - { - // TODO: The underlying invite dialog should show a message - // to the user that she should select at least two contacts - // in order to create a conference. - } - } - }); - - this.addCancelButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - dispose(); - } - }); - } - - /** - * Constructs the ConferenceInviteDialog. - */ - public ConferenceInviteDialog() - { - this(null, null, null, false); - } - - /** - * Creates an instance of ConferenceInviteDialog by specifying an - * already created conference. To use when inviting contacts to an existing - * conference is needed. - * - * @param conference the existing CallConference - */ - public ConferenceInviteDialog(CallConference conference) - { - this(conference, null, null, false); - } - - /** - * Creates an instance of ConferenceInviteDialog by specifying an - * already created conference. To use when inviting contacts to an existing - * conference is needed. - * - * @param conference the existing CallConference - */ - public ConferenceInviteDialog( - CallConference conference, - ProtocolProviderService preselectedProtocolProvider, - boolean isJitsiVideobridge) - { - this(conference, preselectedProtocolProvider, null, isJitsiVideobridge); - } - - /** - * Creates an instance of ConferenceInviteDialog by specifying a - * preselected protocol provider to be used and if this is an invite for - * a video bridge conference. - * - * @param protocolProviders the protocol providers list - * @param isJitsiVideobridge true if this dialog should create a - * conference through a Jitsi Videobridge; otherwise, false - */ - public ConferenceInviteDialog( - List protocolProviders, - boolean isJitsiVideobridge) - { - this(null, null, protocolProviders, isJitsiVideobridge); - } - - /** - * Creates an instance of ConferenceInviteDialog by specifying a - * preselected protocol provider to be used and if this is an invite for - * a video bridge conference. - * - * @param selectedConfProvider the preselected protocol provider - * @param isJitsiVideobridge true if this dialog should create a - * conference through a Jitsi Videobridge; otherwise, false - */ - public ConferenceInviteDialog( - ProtocolProviderService selectedConfProvider, - boolean isJitsiVideobridge) - { - this(null, selectedConfProvider, null, isJitsiVideobridge); - } - - /** - * Initializes the account selector panel. - * - * @param protocolProviders the list of protocol providers we'd like to - * show in the account selector box - */ - private void initAccountSelectorPanel( - List protocolProviders) - { - JLabel accountSelectorLabel = new JLabel( - GuiActivator.getResources().getI18NString("service.gui.CALL_VIA")); - - TransparentPanel accountSelectorPanel - = new TransparentPanel(new BorderLayout()); - - accountSelectorPanel.setBorder( - BorderFactory.createEmptyBorder(5, 5, 5, 5)); - accountSelectorPanel.add(accountSelectorLabel, BorderLayout.WEST); - accountSelectorPanel.add(accountSelectorBox, BorderLayout.CENTER); - - // Initialize the account selector box. - if (protocolProviders != null && protocolProviders.size() > 0) - this.initAccountListData(protocolProviders); - else - this.initAccountListData(); - - this.accountSelectorBox.setRenderer(new DefaultListCellRenderer() - { - private static final long serialVersionUID = 0L; - - @Override - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, - boolean cellHasFocus) - { - ProtocolProviderService protocolProvider - = (ProtocolProviderService) value; - - if (protocolProvider != null) - { - this.setText( - protocolProvider.getAccountID().getDisplayName()); - this.setIcon( - ImageLoader.getAccountStatusImage(protocolProvider)); - } - - return this; - } - }); - - this.accountSelectorBox.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - Object accountSelectorBoxSelectedItem - = accountSelectorBox.getSelectedItem(); - - if (lastSelectedAccount == null - || !lastSelectedAccount - .equals(accountSelectorBoxSelectedItem)) - { - lastSelectedAccount = accountSelectorBoxSelectedItem; - - initContactListData( - (ProtocolProviderService) accountSelectorBox - .getSelectedItem()); - - if (isJitsiVideobridge) - destContactList.removeAll(); - } - } - }); - - this.getContentPane().add(accountSelectorPanel, BorderLayout.NORTH); - } - - /** - * Initializes the account selector box with the given list of - * ProtocolProviderService-s. - * - * @param protocolProviders the list of ProtocolProviderService-s - * we'd like to show in the account selector box - */ - private void initAccountListData( - List protocolProviders) - { - Iterator providersIter - = protocolProviders.iterator(); - - while (providersIter.hasNext()) - { - ProtocolProviderService protocolProvider - = providersIter.next(); - - accountSelectorBox.addItem(protocolProvider); - } - - if (accountSelectorBox.getItemCount() > 0) - accountSelectorBox.setSelectedIndex(0); - } - - /** - * Initializes the account list. - */ - private void initAccountListData() - { - Iterator protocolProviders - = GuiActivator.getUIService().getMainFrame().getProtocolProviders(); - - while(protocolProviders.hasNext()) - { - ProtocolProviderService protocolProvider - = protocolProviders.next(); - OperationSet opSet - = protocolProvider.getOperationSet( - OperationSetTelephonyConferencing.class); - - if ((opSet != null) && protocolProvider.isRegistered()) - accountSelectorBox.addItem(protocolProvider); - } - - // Try to select the last used account if available. - ProtocolProviderService pps - = ConfigurationUtils.getLastCallConferenceProvider(); - - if (pps == null && conference != null) - { - /* - * Pick up the first account from the ones participating in the - * associated telephony conference which supports - * OperationSetTelephonyConferencing. - */ - for (Call call : conference.getCalls()) - { - ProtocolProviderService callPps = call.getProtocolProvider(); - - if (callPps.getOperationSet( - OperationSetTelephonyConferencing.class) - != null) - { - pps = callPps; - break; - } - } - } - - if (pps != null) - accountSelectorBox.setSelectedItem(pps); - else if (accountSelectorBox.getItemCount() > 0) - accountSelectorBox.setSelectedIndex(0); - } - - /** - * Initializes contact list sources. - */ - private void initContactSources() - { - DemuxContactSourceService demuxCSService - = GuiActivator.getDemuxContactSourceService(); - - // If the DemuxContactSourceService isn't registered we use the default - // contact source set. - if (demuxCSService == null) - return; - - Iterator sourcesIter - = new ArrayList( - srcContactList.getContactSources()).iterator(); - - srcContactList.removeAllContactSources(); - - while (sourcesIter.hasNext()) - { - ContactSourceService contactSource - = sourcesIter.next().getContactSourceService(); - - srcContactList.addContactSource( - demuxCSService.createDemuxContactSource(contactSource)); - } - } - - /** - * Initializes the left contact list with the contacts that could be added - * to the current chat session. - * @param protocolProvider the protocol provider from which to initialize - * the contact list data - */ - private void initContactListData(ProtocolProviderService protocolProvider) - { - this.setCurrentProvider(protocolProvider); - - Iterator sourcesIter - = new ArrayList( - srcContactList.getContactSources()).iterator(); - - while (sourcesIter.hasNext()) - { - ContactSourceService contactSource - = sourcesIter.next().getContactSourceService(); - - if (contactSource instanceof ProtocolAwareContactSourceService) - { - ((ProtocolAwareContactSourceService) contactSource) - .setPreferredProtocolProvider( - OperationSetBasicTelephony.class, protocolProvider); - } - } - - srcContactList.removeContactSource(currentProviderContactSource); - srcContactList.removeContactSource(currentStringContactSource); - - currentProviderContactSource - = new ProtocolContactSourceServiceImpl( - protocolProvider, - OperationSetBasicTelephony.class); - currentStringContactSource - = new StringContactSourceServiceImpl( - protocolProvider, - OperationSetBasicTelephony.class); - - srcContactList.addContactSource(currentProviderContactSource); - srcContactList.addContactSource(currentStringContactSource); - - srcContactList.applyDefaultFilter(); - } - - /** - * Invites the contacts to the chat conference. - * - * @param contacts the list of contacts to invite - */ - private void inviteContacts(Collection contacts) - { - ProtocolProviderService selectedProvider; - Map> selectedProviderCallees - = new HashMap>(); - List callees; - - Iterator contactsIter = contacts.iterator(); - - while (contactsIter.hasNext()) - { - UIContact uiContact = contactsIter.next(); - - Iterator contactDetailsIter = uiContact - .getContactDetailsForOperationSet( - OperationSetBasicTelephony.class).iterator(); - - // We invite the first protocol contact that corresponds to the - // invite provider. - if (contactDetailsIter.hasNext()) - { - UIContactDetail inviteDetail = contactDetailsIter.next(); - selectedProvider = inviteDetail - .getPreferredProtocolProvider( - OperationSetBasicTelephony.class); - - if (selectedProvider == null) - { - selectedProvider - = (ProtocolProviderService) - accountSelectorBox.getSelectedItem(); - } - - if(selectedProvider != null - && selectedProviderCallees.get(selectedProvider) != null) - { - callees = selectedProviderCallees.get(selectedProvider); - } - else - { - callees = new ArrayList(); - } - - callees.add(inviteDetail.getAddress()); - selectedProviderCallees.put(selectedProvider, callees); - } - } - - if(conference != null) - { - CallManager.inviteToConferenceCall( - selectedProviderCallees, - conference); - } - else - { - CallManager.createConferenceCall(selectedProviderCallees); - } - } - - /** - * Invites the contacts to the chat conference. - * - * @param contacts the list of contacts to invite - */ - private void inviteJitsiVideobridgeContacts( - ProtocolProviderService preselectedProvider, - Collection contacts) - { - List callees = new ArrayList(); - - Iterator contactsIter = contacts.iterator(); - - while (contactsIter.hasNext()) - { - UIContact uiContact = contactsIter.next(); - - Iterator contactDetailsIter = uiContact - .getContactDetailsForOperationSet( - OperationSetBasicTelephony.class).iterator(); - - // We invite the first protocol contact that corresponds to the - // invite provider. - if (contactDetailsIter.hasNext()) - { - UIContactDetail inviteDetail = contactDetailsIter.next(); - - callees.add(inviteDetail.getAddress()); - } - } - - if(conference != null) - { - CallManager.inviteToJitsiVideobridgeConfCall( - callees.toArray(new String[callees.size()]), - conference.getCalls().get(0)); - } - else - { - CallManager.createJitsiVideobridgeConfCall( - preselectedProvider, - callees.toArray(new String[callees.size()])); - } - } -} +package net.java.sip.communicator.impl.gui.main.call.conference; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The invite dialog is the one shown when the user clicks on the conference + * button in the chat toolbar. + * + * @author Yana Stamcheva + * @author Lyubomir Marinov + */ +public class ConferenceInviteDialog + extends InviteDialog +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The account selector box. + */ + private final JComboBox accountSelectorBox = new JComboBox(); + + /** + * The last selected account. + */ + private Object lastSelectedAccount; + + /** + * The telephony conference into which this instance is to invite + * participants. + */ + private final CallConference conference; + + /** + * The current provider contact source. + */ + private ContactSourceService currentProviderContactSource; + + /** + * The current string contact source. + */ + private ContactSourceService currentStringContactSource; + + /** + * The previously selected protocol provider, with which this dialog has + * been instantiated. + */ + private ProtocolProviderService preselectedProtocolProvider; + + /** + * Indicates whether this conference invite dialog is associated with a + * Jitsi Videobridge invite. + */ + private final boolean isJitsiVideobridge; + + /** + * Initializes a new ConferenceInviteDialog instance which is to + * invite contacts/participants in a specific telephony conference. + * + * @param conference the telephony conference in which the new instance is + * to invite contacts/participants + */ + public ConferenceInviteDialog( + CallConference conference, + ProtocolProviderService preselectedProvider, + List protocolProviders, + final boolean isJitsiVideobridge) + { + // Set the correct dialog title depending if we're going to create a + // video bridge conference call + super((isJitsiVideobridge + ? GuiActivator.getResources() + .getI18NString("service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE") + : GuiActivator.getResources() + .getI18NString("service.gui.INVITE_CONTACT_TO_CALL")), + false); + + this.conference = conference; + this.preselectedProtocolProvider = preselectedProvider; + this.isJitsiVideobridge = isJitsiVideobridge; + + if (preselectedProtocolProvider == null) + initAccountSelectorPanel(protocolProviders); + + // init the list, as we check whether features are supported + // it may take some time if we have too much contacts + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + initContactSources(); + + // Initialize the list of contacts to select from. + if (preselectedProtocolProvider != null) + initContactListData(preselectedProtocolProvider); + else + initContactListData( + (ProtocolProviderService) accountSelectorBox + .getSelectedItem()); + } + }); + + this.addInviteButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + Collection selectedContacts + = destContactList.getContacts(null); + + if (selectedContacts != null && selectedContacts.size() > 0) + { + if (preselectedProtocolProvider == null) + preselectedProtocolProvider + = (ProtocolProviderService) accountSelectorBox + .getSelectedItem(); + + if (isJitsiVideobridge) + inviteJitsiVideobridgeContacts( preselectedProtocolProvider, + selectedContacts); + else + inviteContacts(selectedContacts); + + // Store the last used account in order to pre-select it + // next time. + ConfigurationUtils.setLastCallConferenceProvider( + preselectedProtocolProvider); + + dispose(); + } + else + { + // TODO: The underlying invite dialog should show a message + // to the user that she should select at least two contacts + // in order to create a conference. + } + } + }); + + this.addCancelButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + dispose(); + } + }); + } + + /** + * Constructs the ConferenceInviteDialog. + */ + public ConferenceInviteDialog() + { + this(null, null, null, false); + } + + /** + * Creates an instance of ConferenceInviteDialog by specifying an + * already created conference. To use when inviting contacts to an existing + * conference is needed. + * + * @param conference the existing CallConference + */ + public ConferenceInviteDialog(CallConference conference) + { + this(conference, null, null, false); + } + + /** + * Creates an instance of ConferenceInviteDialog by specifying an + * already created conference. To use when inviting contacts to an existing + * conference is needed. + * + * @param conference the existing CallConference + */ + public ConferenceInviteDialog( + CallConference conference, + ProtocolProviderService preselectedProtocolProvider, + boolean isJitsiVideobridge) + { + this(conference, preselectedProtocolProvider, null, isJitsiVideobridge); + } + + /** + * Creates an instance of ConferenceInviteDialog by specifying a + * preselected protocol provider to be used and if this is an invite for + * a video bridge conference. + * + * @param protocolProviders the protocol providers list + * @param isJitsiVideobridge true if this dialog should create a + * conference through a Jitsi Videobridge; otherwise, false + */ + public ConferenceInviteDialog( + List protocolProviders, + boolean isJitsiVideobridge) + { + this(null, null, protocolProviders, isJitsiVideobridge); + } + + /** + * Creates an instance of ConferenceInviteDialog by specifying a + * preselected protocol provider to be used and if this is an invite for + * a video bridge conference. + * + * @param selectedConfProvider the preselected protocol provider + * @param isJitsiVideobridge true if this dialog should create a + * conference through a Jitsi Videobridge; otherwise, false + */ + public ConferenceInviteDialog( + ProtocolProviderService selectedConfProvider, + boolean isJitsiVideobridge) + { + this(null, selectedConfProvider, null, isJitsiVideobridge); + } + + /** + * Initializes the account selector panel. + * + * @param protocolProviders the list of protocol providers we'd like to + * show in the account selector box + */ + private void initAccountSelectorPanel( + List protocolProviders) + { + JLabel accountSelectorLabel = new JLabel( + GuiActivator.getResources().getI18NString("service.gui.CALL_VIA")); + + TransparentPanel accountSelectorPanel + = new TransparentPanel(new BorderLayout()); + + accountSelectorPanel.setBorder( + BorderFactory.createEmptyBorder(5, 5, 5, 5)); + accountSelectorPanel.add(accountSelectorLabel, BorderLayout.WEST); + accountSelectorPanel.add(accountSelectorBox, BorderLayout.CENTER); + + // Initialize the account selector box. + if (protocolProviders != null && protocolProviders.size() > 0) + this.initAccountListData(protocolProviders); + else + this.initAccountListData(); + + this.accountSelectorBox.setRenderer(new DefaultListCellRenderer() + { + private static final long serialVersionUID = 0L; + + @Override + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, + boolean cellHasFocus) + { + ProtocolProviderService protocolProvider + = (ProtocolProviderService) value; + + if (protocolProvider != null) + { + this.setText( + protocolProvider.getAccountID().getDisplayName()); + this.setIcon( + ImageLoader.getAccountStatusImage(protocolProvider)); + } + + return this; + } + }); + + this.accountSelectorBox.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + Object accountSelectorBoxSelectedItem + = accountSelectorBox.getSelectedItem(); + + if (lastSelectedAccount == null + || !lastSelectedAccount + .equals(accountSelectorBoxSelectedItem)) + { + lastSelectedAccount = accountSelectorBoxSelectedItem; + + initContactListData( + (ProtocolProviderService) accountSelectorBox + .getSelectedItem()); + + if (isJitsiVideobridge) + destContactList.removeAll(); + } + } + }); + + this.getContentPane().add(accountSelectorPanel, BorderLayout.NORTH); + } + + /** + * Initializes the account selector box with the given list of + * ProtocolProviderService-s. + * + * @param protocolProviders the list of ProtocolProviderService-s + * we'd like to show in the account selector box + */ + private void initAccountListData( + List protocolProviders) + { + Iterator providersIter + = protocolProviders.iterator(); + + while (providersIter.hasNext()) + { + ProtocolProviderService protocolProvider + = providersIter.next(); + + accountSelectorBox.addItem(protocolProvider); + } + + if (accountSelectorBox.getItemCount() > 0) + accountSelectorBox.setSelectedIndex(0); + } + + /** + * Initializes the account list. + */ + private void initAccountListData() + { + Iterator protocolProviders + = GuiActivator.getUIService().getMainFrame().getProtocolProviders(); + + while(protocolProviders.hasNext()) + { + ProtocolProviderService protocolProvider + = protocolProviders.next(); + OperationSet opSet + = protocolProvider.getOperationSet( + OperationSetTelephonyConferencing.class); + + if ((opSet != null) && protocolProvider.isRegistered()) + accountSelectorBox.addItem(protocolProvider); + } + + // Try to select the last used account if available. + ProtocolProviderService pps + = ConfigurationUtils.getLastCallConferenceProvider(); + + if (pps == null && conference != null) + { + /* + * Pick up the first account from the ones participating in the + * associated telephony conference which supports + * OperationSetTelephonyConferencing. + */ + for (Call call : conference.getCalls()) + { + ProtocolProviderService callPps = call.getProtocolProvider(); + + if (callPps.getOperationSet( + OperationSetTelephonyConferencing.class) + != null) + { + pps = callPps; + break; + } + } + } + + if (pps != null) + accountSelectorBox.setSelectedItem(pps); + else if (accountSelectorBox.getItemCount() > 0) + accountSelectorBox.setSelectedIndex(0); + } + + /** + * Initializes contact list sources. + */ + private void initContactSources() + { + DemuxContactSourceService demuxCSService + = GuiActivator.getDemuxContactSourceService(); + + // If the DemuxContactSourceService isn't registered we use the default + // contact source set. + if (demuxCSService == null) + return; + + Iterator sourcesIter + = new ArrayList( + srcContactList.getContactSources()).iterator(); + + srcContactList.removeAllContactSources(); + + while (sourcesIter.hasNext()) + { + ContactSourceService contactSource + = sourcesIter.next().getContactSourceService(); + + srcContactList.addContactSource( + demuxCSService.createDemuxContactSource(contactSource)); + } + } + + /** + * Initializes the left contact list with the contacts that could be added + * to the current chat session. + * @param protocolProvider the protocol provider from which to initialize + * the contact list data + */ + private void initContactListData(ProtocolProviderService protocolProvider) + { + this.setCurrentProvider(protocolProvider); + + Iterator sourcesIter + = new ArrayList( + srcContactList.getContactSources()).iterator(); + + while (sourcesIter.hasNext()) + { + ContactSourceService contactSource + = sourcesIter.next().getContactSourceService(); + + if (contactSource instanceof ProtocolAwareContactSourceService) + { + ((ProtocolAwareContactSourceService) contactSource) + .setPreferredProtocolProvider( + OperationSetBasicTelephony.class, protocolProvider); + } + } + + srcContactList.removeContactSource(currentProviderContactSource); + srcContactList.removeContactSource(currentStringContactSource); + + currentProviderContactSource + = new ProtocolContactSourceServiceImpl( + protocolProvider, + OperationSetBasicTelephony.class); + currentStringContactSource + = new StringContactSourceServiceImpl( + protocolProvider, + OperationSetBasicTelephony.class); + + srcContactList.addContactSource(currentProviderContactSource); + srcContactList.addContactSource(currentStringContactSource); + + srcContactList.applyDefaultFilter(); + } + + /** + * Invites the contacts to the chat conference. + * + * @param contacts the list of contacts to invite + */ + private void inviteContacts(Collection contacts) + { + ProtocolProviderService selectedProvider; + Map> selectedProviderCallees + = new HashMap>(); + List callees; + + Iterator contactsIter = contacts.iterator(); + + while (contactsIter.hasNext()) + { + UIContact uiContact = contactsIter.next(); + + Iterator contactDetailsIter = uiContact + .getContactDetailsForOperationSet( + OperationSetBasicTelephony.class).iterator(); + + // We invite the first protocol contact that corresponds to the + // invite provider. + if (contactDetailsIter.hasNext()) + { + UIContactDetail inviteDetail = contactDetailsIter.next(); + selectedProvider = inviteDetail + .getPreferredProtocolProvider( + OperationSetBasicTelephony.class); + + if (selectedProvider == null) + { + selectedProvider + = (ProtocolProviderService) + accountSelectorBox.getSelectedItem(); + } + + if(selectedProvider != null + && selectedProviderCallees.get(selectedProvider) != null) + { + callees = selectedProviderCallees.get(selectedProvider); + } + else + { + callees = new ArrayList(); + } + + callees.add(inviteDetail.getAddress()); + selectedProviderCallees.put(selectedProvider, callees); + } + } + + if(conference != null) + { + CallManager.inviteToConferenceCall( + selectedProviderCallees, + conference); + } + else + { + CallManager.createConferenceCall(selectedProviderCallees); + } + } + + /** + * Invites the contacts to the chat conference. + * + * @param contacts the list of contacts to invite + */ + private void inviteJitsiVideobridgeContacts( + ProtocolProviderService preselectedProvider, + Collection contacts) + { + List callees = new ArrayList(); + + Iterator contactsIter = contacts.iterator(); + + while (contactsIter.hasNext()) + { + UIContact uiContact = contactsIter.next(); + + Iterator contactDetailsIter = uiContact + .getContactDetailsForOperationSet( + OperationSetBasicTelephony.class).iterator(); + + // We invite the first protocol contact that corresponds to the + // invite provider. + if (contactDetailsIter.hasNext()) + { + UIContactDetail inviteDetail = contactDetailsIter.next(); + + callees.add(inviteDetail.getAddress()); + } + } + + if(conference != null) + { + CallManager.inviteToJitsiVideobridgeConfCall( + callees.toArray(new String[callees.size()]), + conference.getCalls().get(0)); + } + else + { + CallManager.createJitsiVideobridgeConfCall( + preselectedProvider, + callees.toArray(new String[callees.size()])); + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java index 0dd6ef5..07c653d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/conference/VideoConferenceCallPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1395 +15,1395 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.call.conference; - -import java.awt.*; -import java.util.*; -import java.util.List; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.main.call.*; -import net.java.sip.communicator.impl.gui.utils.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.plugin.desktoputil.TransparentPanel; - -import org.jitsi.util.swing.*; - -/** - * Extends BasicConferenceCallPanel to implement a user interface - * Component which depicts a CallConference with audio and - * video and is contained in a CallPanel. - * - * @author Yana Stamcheva - * @author Lyubomir Marinov - */ -public class VideoConferenceCallPanel - extends BasicConferenceCallPanel -{ - /** - * The Logger used by the VideoConferenceCallPanel class - * and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(VideoConferenceCallPanel.class); - - /** - * The compile-time flag which indicates whether each video displayed by - * VideoConferenceCallPanel is to be depicted with an associated - * tool bar showing information and controls related to the (local or - * remote) peer sending the respective video. - */ - private static final boolean SHOW_TOOLBARS = true; - - /** - * The facility which aids this instance with the video-related information. - */ - private final UIVideoHandler2 uiVideoHandler; - - /** - * The Observer which listens to {@link #uiVideoHandler} about - * changes in the video-related information. - */ - private final Observer uiVideoHandlerObserver - = new Observer() - { - public void update(Observable o, Object arg) - { - updateViewFromModel(); - } - }; - - /** - * The VideoContainer which occupies this whole Component - * and arranges the visual Components displaying the video - * streaming between the local peer/user and the remote peer(s). - */ - private final VideoContainer videoContainer; - - /** - * The set of visual Components displaying video streaming between - * the local peer/user and the remote peers which are depicted by this - * instance. - */ - private final Set videos = new HashSet(); - - /** - * The thumbnail container. - */ - private final ThumbnailConferenceCallPanel thumbnailContainer; - - private final JPanel thumbnailPanel; - - /** - * Initializes a new VideoConferenceCallPanel instance which is to - * be used by a specific CallPanel to depict a specific - * CallConference. The new instance will depict both the - * audio-related and the video-related information. - * - * @param callPanel the CallPanel which will use the new instance - * to depict the specified CallConference. - * @param callConference the CallConference to be depicted by the - * new instance - * @param uiVideoHandler the utility which is to aid the new instance in - * dealing with the video-related information - */ - public VideoConferenceCallPanel( - CallPanel callPanel, - CallConference callConference, - UIVideoHandler2 uiVideoHandler) - { - super(callPanel, callConference); - - this.uiVideoHandler = uiVideoHandler; - - thumbnailPanel = new JPanel(new BorderLayout()); - thumbnailContainer - = new ThumbnailConferenceCallPanel( callPanel, - callConference, - uiVideoHandler); - - videoContainer = createVideoContainer(); - - /* - * Our user interface hierarchy has been initialized so we are ready to - * begin receiving events warranting updates of this view from its - * model. - */ - uiVideoHandler.addObserver(uiVideoHandlerObserver); - - /* - * Notify the super that this instance has completed its initialization - * and the view that it implements is ready to be updated from the - * model. - */ - initializeComplete(); - } - - private void addConferenceMemberContainers( - ConferenceParticipantContainer cpc) - { - List cmcs - = cpc.conferenceMemberContainers; - - if ((cmcs != null) && !cmcs.isEmpty()) - { - for (ConferenceParticipantContainer cmc : cmcs) - { - if (!cmc.toBeRemoved) - { - videoContainer.add( - cmc.getComponent(), - VideoLayout.CENTER_REMOTE); - } - } - } - } - - private Component createDefaultPhotoPanel(Call call) - { - OperationSetServerStoredAccountInfo accountInfo - = call.getProtocolProvider().getOperationSet( - OperationSetServerStoredAccountInfo.class); - ImageIcon photoLabelIcon = null; - - if (accountInfo != null) - { - byte[] accountImage = AccountInfoUtils.getImage(accountInfo); - - // do not set empty images - if ((accountImage != null) && (accountImage.length > 0)) - photoLabelIcon = new ImageIcon(accountImage); - } - if (photoLabelIcon == null) - { - photoLabelIcon - = new ImageIcon( - ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)); - } - - return createDefaultPhotoPanel(photoLabelIcon); - } - - private Component createDefaultPhotoPanel(CallPeer callPeer) - { - byte[] peerImage = CallManager.getPeerImage(callPeer); - ImageIcon photoLabelIcon - = (peerImage == null) - ? new ImageIcon( - ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)) - : new ImageIcon(peerImage); - - return createDefaultPhotoPanel(photoLabelIcon); - } - - private Component createDefaultPhotoPanel(ConferenceMember conferenceMember) - { - return - createDefaultPhotoPanel( - new ImageIcon( - ImageLoader.getImage( - ImageLoader.DEFAULT_USER_PHOTO))); - } - - /** - * Creates a new Component which is to display a specific - * ImageIcon representing the photo of a participant in a call. - * - * @param photoLabelIcon the ImageIcon which represents the photo - * of a participant in a call and which is to be displayed by the new - * Component - * @return a new Component which displays the specified - * photoLabelIcon - */ - private Component createDefaultPhotoPanel(ImageIcon photoLabelIcon) - { - JLabel photoLabel = new JLabel(); - - photoLabel.setIcon(photoLabelIcon); - - @SuppressWarnings("serial") - JPanel photoPanel - = new TransparentPanel(new GridBagLayout()) - { - /** - * @{inheritDoc} - */ - @Override - public void paintComponent(Graphics g) - { - super.paintComponent(g); - - g = g.create(); - try - { - AntialiasingManager.activateAntialiasing(g); - - g.setColor(Color.GRAY); - g.fillRoundRect( - 0, 0, this.getWidth(), this.getHeight(), - 6, 6); - } - finally - { - g.dispose(); - } - } - }; - - photoPanel.setPreferredSize(new Dimension(320, 240)); - - GridBagConstraints photoPanelConstraints = new GridBagConstraints(); - - photoPanelConstraints.anchor = GridBagConstraints.CENTER; - photoPanelConstraints.fill = GridBagConstraints.NONE; - photoPanel.add(photoLabel, photoPanelConstraints); - - return photoPanel; - } - - /** - * Initializes a new VideoContainer instance which is to contain - * the visual/video Components of the telephony conference depicted - * by this instance. - */ - private VideoContainer createVideoContainer() - { - VideoContainer videoContainer = new VideoContainer(null, true); - - thumbnailPanel.setBackground(Color.DARK_GRAY); - thumbnailPanel.add(thumbnailContainer, BorderLayout.NORTH); - - add(thumbnailPanel, BorderLayout.EAST); - add(videoContainer, BorderLayout.CENTER); - - return videoContainer; - } - - /** - * Shows/hides the participants thumbnails list. - * - * @param show true to show the participants list, false - * to hide it - */ - public void showThumbnailsList(boolean show) - { - thumbnailPanel.setVisible(show); - } - - /** - * {@inheritDoc} - */ - @Override - public void dispose() - { - try - { - uiVideoHandler.deleteObserver(uiVideoHandlerObserver); - } - finally - { - super.dispose(); - } - } - - /** - * Determines whether a specific ConferenceMember represents the - * same conference participant as a specific CallPeer. If the - * specified conferenceMember is null, returns - * true. Otherwise, determines whether the addresses of the - * specified conferenceMember and the specified callPeer - * identify one and the same entity. - * - * @param conferenceMember the ConferenceMember to be checked - * whether is represents the same conference participant as the specified - * callPeer. If it is null, true is returned. - * @param callPeer the CallPeer to be checked whether it represents - * the same conference participant as the specified - * conferenceMember - * @return true if the specified conferenceMember and the - * specified callPeer represent the same conference participant or - * the specified conferenceMember is null; otherwise, - * false - */ - private boolean isConferenceMemberCallPeer( - ConferenceMember conferenceMember, - CallPeer callPeer) - { - return - (conferenceMember == null) - ? true - : CallManager.addressesAreEqual( - conferenceMember.getAddress(), - callPeer.getAddress()); - } - - /** - * Determines whether a specific ConferenceMember represents the - * local peer/user. Since this instance depicts a whole telephony - * conference, the local peer/user may be participating with multiple - * Calls in it. The Calls may be through different - * (local) accounts. That's why the implementation determines whether the - * address of the specified conferenceMember identifies the address - * of a (local) accounts involved in the telephony conference depicted by - * this instance. - * - * @param conferenceMember the ConferenceMember to be checked - * whether it represents the local peer/user - * @return true if the specified conferenceMember - * represents the local peer/user; otherwise, false - */ - private boolean isConferenceMemberLocalUser( - ConferenceMember conferenceMember) - { - String address = conferenceMember.getAddress(); - - for (Call call : callConference.getCalls()) - { - if (CallManager.addressesAreEqual( - address, - call.getProtocolProvider().getAccountID() - .getAccountAddress())) - { - return true; - } - } - return false; - } - - private void removeConferenceMemberContainers( - ConferenceParticipantContainer cpc, - boolean all) - { - List cmcs - = cpc.conferenceMemberContainers; - - if ((cmcs != null) && !cmcs.isEmpty()) - { - Iterator i = cmcs.iterator(); - - while (i.hasNext()) - { - ConferenceParticipantContainer cmc = i.next(); - - if (all || cmc.toBeRemoved) - { - i.remove(); - - videoContainer.remove(cmc.getComponent()); - cmc.dispose(); - } - } - } - } - - /** - * Updates the ConferenceParticipantContainers which depict the - * ConferenceMembers of the CallPeer depicted by a - * specific ConferenceParticipantContainer. - * - * @param cpc the ConferenceParticipantContainer which depicts the - * CallPeer whose ConferenceMembers are to be depicted - * @param videos the visual Components displaying video streaming - * from the remote peer (represented by cpc) to the local peer/user - * @param videoTelephony the OperationSetVideoTelephony which - * retrieved the specified videos from the CallPeer - * depicted by cpc. While the CallPeer could be queried - * for it, such a query would waste more resources at run time given that - * the invoker has it already. - */ - private void updateConferenceMemberContainers( - ConferenceParticipantContainer cpc, - List videos, - OperationSetVideoTelephony videoTelephony) - { - CallPeer callPeer = (CallPeer) cpc.getParticipant(); - List cmcs - = cpc.conferenceMemberContainers; - - /* - * Invalidate all conferenceMemberContainers. Then validate which of - * them are to remain and which of them are to really be removed - * later on. - */ - if (cmcs != null) - { - for (ConferenceParticipantContainer cmc : cmcs) - cmc.toBeRemoved = true; - } - - /* - * Depict the remote videos. They may or may not be associated with - * ConferenceMembers so the ConferenceMembers which have no - * associated videos will be depicted afterwards. - */ - if (videos != null) - { - Component video = cpc.getVideo(); - - for (Component conferenceMemberVideo : videos) - { - /* - * One of the remote videos is already used to depict the - * callPeer. - */ - if (conferenceMemberVideo == video) - continue; - - boolean addNewConferenceParticipantContainer = true; - ConferenceMember conferenceMember - = videoTelephony.getConferenceMember( - callPeer, - conferenceMemberVideo); - - if (cmcs == null) - { - cmcs = new LinkedList(); - cpc.conferenceMemberContainers = cmcs; - } - else - { - for (ConferenceParticipantContainer cmc : cmcs) - { - Object cmcParticipant = cmc.getParticipant(); - - if (conferenceMember == null) - { - if (cmcParticipant == callPeer) - { - Component cmcVideo = cmc.getVideo(); - - if (cmcVideo == null) - { - cmc.setVideo(conferenceMemberVideo); - cmc.toBeRemoved = false; - addNewConferenceParticipantContainer - = false; - break; - } - else if (cmcVideo == conferenceMemberVideo) - { - cmc.toBeRemoved = false; - addNewConferenceParticipantContainer - = false; - break; - } - } - } - else if (cmcParticipant == conferenceMember) - { - cmc.setVideo(conferenceMemberVideo); - cmc.toBeRemoved = false; - addNewConferenceParticipantContainer = false; - break; - } - } - } - - if (addNewConferenceParticipantContainer) - { - ConferenceParticipantContainer cmc - = (conferenceMember == null) - ? new ConferenceParticipantContainer( - callPeer, - conferenceMemberVideo) - : new ConferenceParticipantContainer( - conferenceMember, - conferenceMemberVideo); - - cmcs.add(cmc); - } - } - } - - /* - * Depict the ConferenceMembers which have not been depicted yet. - * They have no associated videos. - */ - List conferenceMembers - = callPeer.getConferenceMembers(); - - if (!conferenceMembers.isEmpty()) - { - if (cmcs == null) - { - cmcs = new LinkedList(); - cpc.conferenceMemberContainers = cmcs; - } - for (ConferenceMember conferenceMember : conferenceMembers) - { - /* - * If the callPeer reports itself as a ConferenceMember, then - * we've already depicted it with cpc. - */ - if (isConferenceMemberCallPeer(conferenceMember, callPeer)) - continue; - /* - * If the callPeer reports the local peer/user as a - * ConferenceMember, then we've already depicted it. - */ - if (isConferenceMemberLocalUser(conferenceMember)) - continue; - - boolean addNewConferenceParticipantContainer = true; - - for (ConferenceParticipantContainer cmc : cmcs) - { - if (cmc.getParticipant() == conferenceMember) - { - /* - * It is possible to have a ConferenceMember who is - * sending video but we just do not have the SSRC of - * that video to associate the video with the - * ConferenceMember. In such a case, we may be depicting - * the ConferenceMember twice: once with video without a - * ConferenceMember and once with a ConferenceMember - * without video. This will surely be the case at the - * time of this writing with non-focus participants in a - * telephony conference hosted on a Jitsi Videobridge. - * Such a display is undesirable. If the - * conferenceMember is known to send video, we will not - * display it until we associated it with a video. This - * way, if a ConferenceMember is not sending video, we - * will depict it and we can be sure that no video - * without a ConferenceMember association will be - * depicting it a second time. - */ - if (cmc.toBeRemoved - && !conferenceMember - .getVideoStatus() - .allowsSending()) - { - cmc.setVideo(null); - cmc.toBeRemoved = false; - } - addNewConferenceParticipantContainer = false; - break; - } - } - - if (addNewConferenceParticipantContainer) - { - ConferenceParticipantContainer cmc - = new ConferenceParticipantContainer( - conferenceMember, - null); - - cmcs.add(cmc); - } - } - } - - if ((cmcs != null) && !cmcs.isEmpty()) - { - removeConferenceMemberContainers(cpc, false); - /* - * If cpc is already added to the user interface hierarchy of this - * instance, then it was there before the update procedure and it - * was determined to be appropriate to continue to depict its model. - * Consequently, its Component will be neither added to (because it - * was already added) nor removed from the user interface hierarchy - * of this instance. That's why we have make sure that the - * Components of its conferenceMemberContainers are also added to - * the user interface. - */ - if (UIVideoHandler2.isAncestor(this, cpc.getComponent())) - addConferenceMemberContainers(cpc); - } - } - - /** - * {@inheritDoc} - */ - @Override - protected ConferenceCallPeerRenderer updateViewFromModel( - ConferenceCallPeerRenderer callPeerPanel, - CallPeer callPeer) - { - if (callPeer == null) - { - /* - * The local peer/user will be represented by a Call which has a - * CallPeer who provides local video. However, if the user has - * selected to hide the local video, the local peer/user will not be - * represented at all. - */ - Component video = null; - - if (uiVideoHandler.isLocalVideoVisible()) - { - for (Call aCall : callConference.getCalls()) - { - Iterator callPeerIter - = aCall.getCallPeers(); - OperationSetVideoTelephony videoTelephony - = aCall.getProtocolProvider().getOperationSet( - OperationSetVideoTelephony.class); - - while (callPeerIter.hasNext()) - { - callPeer = callPeerIter.next(); - - if (videoTelephony != null) - { - try - { - video - = videoTelephony.getLocalVisualComponent( - callPeer); - } - catch (OperationFailedException ofe) - { - logger.error( - "Failed to retrieve the local video" - + " for display", - ofe); - } - if (video != null) - break; - } - } - if (video != null) - break; - } - } - - if (callPeer == null) - callPeerPanel = null; - else - { - Call call = callPeer.getCall(); - - if (callPeerPanel instanceof ConferenceParticipantContainer) - { - ConferenceParticipantContainer cpc - = (ConferenceParticipantContainer) callPeerPanel; - - if (cpc.getParticipant() == call) - cpc.setVideo(video); - else - callPeerPanel = null; - } - else - callPeerPanel = null; - if (callPeerPanel == null) - { - callPeerPanel - = new ConferenceParticipantContainer(call, video); - } - } - } - else - { - /* - * The specified callPeer will be represented by one of its remote - * videos which is not associated with a ConferenceMember or is - * associated with a ConferenceMember representing the callPeer - * itself. - */ - OperationSetVideoTelephony videoTelephony - = callPeer.getProtocolProvider().getOperationSet( - OperationSetVideoTelephony.class); - List videos = null; - Component video = null; - - if (videoTelephony != null) - { - videos = videoTelephony.getVisualComponents(callPeer); - if ((videos != null) && !videos.isEmpty()) - { - for (Component aVideo : videos) - { - ConferenceMember conferenceMember - = videoTelephony.getConferenceMember( - callPeer, - aVideo); - - if (isConferenceMemberCallPeer( - conferenceMember, - callPeer)) - { - video = aVideo; - break; - } - } - } - } - - ConferenceParticipantContainer cpc = null; - - if (callPeerPanel instanceof ConferenceParticipantContainer) - { - cpc = (ConferenceParticipantContainer) callPeerPanel; - if (cpc.getParticipant() == callPeer) - cpc.setVideo(video); - else - cpc = null; - } - if (cpc == null) - cpc = new ConferenceParticipantContainer(callPeer, video); - callPeerPanel = cpc; - - // Update the conferenceMemberContainers of the cpc. - updateConferenceMemberContainers(cpc, videos, videoTelephony); - } - return callPeerPanel; - } - - /** - * {@inheritDoc} - * - * If {@link #SHOW_TOOLBARS} is false, disables the use of - * ConferenceParticipantContainer. A reason for such a value of - * SHOW_TOOLBARS may be that the functionality implemented in the - * model may not fully support mapping of visual Components - * displaying video to telephony conference participants (e.g. in telephony - * conferences utilizing the Jitsi Videobridge server-side technology). In - * such a case displays the videos only, does not map videos to participants - * and does not display participants who do not have videos. - */ - @Override - protected void updateViewFromModelInEventDispatchThread() - { - if (SHOW_TOOLBARS) - { - super.updateViewFromModelInEventDispatchThread(); - return; - } - - /* - * Determine the set of visual Components displaying video streaming - * between the local peer/user and the remote peers which are to be - * depicted by this instance. - */ - Component localVideo = null; - Set videos = new HashSet(); - - for (Call call : callConference.getCalls()) - { - OperationSetVideoTelephony videoTelephony - = call.getProtocolProvider().getOperationSet( - OperationSetVideoTelephony.class); - - if (videoTelephony == null) - continue; - - Iterator callPeerIter = call.getCallPeers(); - - while (callPeerIter.hasNext()) - { - CallPeer callPeer = callPeerIter.next(); - - /* - * TODO VideoConferenceCallPanel respects - * UIVideoHandler2.isLocalVideoVisible() in order to react to - * the associated button at the bottom of the CallPanel. - * However, it does not add a close button on top of the local - * video in contrast to OneToOneCallPeerPanel. Overall, the - * result is questionable. - */ - if (uiVideoHandler.isLocalVideoVisible() - && (localVideo == null)) - { - try - { - localVideo - = videoTelephony.getLocalVisualComponent(callPeer); - } - catch (OperationFailedException ofe) - { - /* - * We'll just try to get the local video through another - * CallPeer then. - */ - } - if (localVideo != null) - videos.add(localVideo); - } - - List callPeerRemoteVideos - = videoTelephony.getVisualComponents(callPeer); - - videos.addAll(callPeerRemoteVideos); - } - } - - /* - * Remove the Components of this view which are no longer present in the - * model. - */ - Iterator thisVideoIter = this.videos.iterator(); - - while (thisVideoIter.hasNext()) - { - Component thisVideo = thisVideoIter.next(); - - if (!videos.contains(thisVideo)) - { - thisVideoIter.remove(); - videoContainer.remove(thisVideo); - } - - /* - * If a video is known to be depicted by this view and is still - * present in the model, then we could remove it from the set of - * videos present in the model in order to prevent going through the - * procedure of adding it to this view. However, we choose to play - * on the safe side. - */ - } - - /* - * Add the Components of the model which are not depicted by this view. - */ - for (Component video : videos) - { - if (!UIVideoHandler2.isAncestor(videoContainer, video)) - { - this.videos.add(video); - videoContainer.add( - video, - (video == localVideo) - ? VideoLayout.LOCAL - : VideoLayout.CENTER_REMOTE); - } - } - } - - @Override - protected void viewForModelAdded( - ConferenceCallPeerRenderer callPeerPanel, - CallPeer callPeer) - { - videoContainer.add( - callPeerPanel.getComponent(), - VideoLayout.CENTER_REMOTE); - if ((callPeer != null) - && (callPeerPanel instanceof ConferenceParticipantContainer)) - { - addConferenceMemberContainers( - (ConferenceParticipantContainer) callPeerPanel); - } - } - - @Override - protected void viewForModelRemoved( - ConferenceCallPeerRenderer callPeerPanel, - CallPeer callPeer) - { - videoContainer.remove(callPeerPanel.getComponent()); - if ((callPeer != null) - && (callPeerPanel instanceof ConferenceParticipantContainer)) - { - removeConferenceMemberContainers( - (ConferenceParticipantContainer) callPeerPanel, - true); - } - } - - /** - * Implements an AWT Component which contains the user interface - * elements depicting a specific participant in the telephony conference - * depicted by a VideoConferenceCallPanel. - */ - private class ConferenceParticipantContainer - extends TransparentPanel - implements ConferenceCallPeerRenderer - { - /** - * The list of ConferenceParticipantContainers which represent - * the ConferenceMembers of the participant represented by this - * instance. Since a CallPeer may send the local peer/user - * multiple videos without providing a way to associate a - * ConferenceMember with each one of them, the list may contain - * ConferenceParticipantContainers which do not represent a - * specific ConferenceMember instance but rather a video sent - * by a CallPeer to the local peer/user which looks like (in - * the terms of VideoConferenceCallPanel) a member of a conference - * organized by the CallPeer in question. - *

    - * Implements a state which is private to - * VideoConferenceCallPanel and is of no concern to - * ConferenceParticipantContainer. - *

    - */ - List conferenceMemberContainers; - - /** - * The indicator which determines whether this instance is to be removed - * because it has become out-of-date, obsolete, unnecessary. - *

    - * Implements a state which is private to - * VideoConferenceCallPanel and is of no concern to - * ConferenceParticipantContainer. - *

    - */ - boolean toBeRemoved; - - /** - * The BasicConferenceParticipantPanel which is displayed at - * the bottom of this instance, bellow the {@link #video} (i.e. - * {@link #videoContainer}) and is referred to as the tool bar. - */ - private final BasicConferenceParticipantPanel toolBar; - - /** - * The visual Component, if any, displaying video which is - * depicted by this instance. - */ - private Component video; - - /** - * The VideoContainer which lays out the video depicted by this - * instance i.e. {@link #video}. - */ - private final VideoContainer videoContainer; - - /** - * The CallPeer associated with this container, if it has been - * created to represent a CallPeer. - */ - private CallPeer callPeer; - - /** - * The conferenceMember associated with this container, if it - * has been created to represent a conferenceMember. - */ - private ConferenceMember conferenceMember; - - /** - * Indicates that this container contains information for the local - * user. - */ - private boolean isLocalUser; - - /** - * Initializes a new ConferenceParticipantContainer instance - * which is to depict the local peer/user. - * - * @param call a Call which is to provide information about the - * local peer/user - * @param video the visual Component, if any, displaying the - * video streaming from the local peer/user to the remote peer(s) - */ - public ConferenceParticipantContainer(Call call, Component video) - { - this( - createDefaultPhotoPanel(call), - video, - new ConferencePeerPanel( - VideoConferenceCallPanel.this, - call, - true), - null, null, true); - } - - public ConferenceParticipantContainer( - CallPeer callPeer, - Component video) - { - this( createDefaultPhotoPanel(callPeer), - video, - new ConferencePeerPanel( - VideoConferenceCallPanel.this, - callPeer, - true), - callPeer, null, false); - } - - private ConferenceParticipantContainer( - Component noVideo, - Component video, - BasicConferenceParticipantPanel toolBar, - CallPeer callPeer, - ConferenceMember conferenceMember, - boolean isLocalUser) - { - super(new BorderLayout()); - - this.callPeer = callPeer; - this.conferenceMember = conferenceMember; - this.isLocalUser = isLocalUser; - - videoContainer = new VideoContainer(noVideo, false); - add(videoContainer, BorderLayout.CENTER); - - this.toolBar = toolBar; - if (this.toolBar != null) - add(this.toolBar, BorderLayout.SOUTH); - - if (video != null) - { - setVideo(video); - } - else - setVisible(false); - } - - public ConferenceParticipantContainer( - ConferenceMember conferenceMember, - Component video) - { - this( - createDefaultPhotoPanel(conferenceMember), - video, - new ConferenceMemberPanel( - VideoConferenceCallPanel.this, - conferenceMember, - true), - null, conferenceMember, false); - } - - public void dispose() - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.dispose(); - - // Dispose of the conferenceMemberContainers if any. - /* - * XXX The field conferenceMemberContainers implements a state - * private to VideoConferenceCallPanel which the latter makes sure - * to access on the AWT event dispatching thread only. Since we are - * going out of our way here to help VideoConferenceCallPanel, - * ensure that the mentioned synchronization rule is not violated. - */ - CallManager.assertIsEventDispatchingThread(); - if (conferenceMemberContainers != null) - { - for (ConferenceParticipantContainer cmc - : conferenceMemberContainers) - { - cmc.dispose(); - } - } - } - - public CallPanel getCallPanel() - { - return getCallRenderer().getCallContainer(); - } - - public SwingCallRenderer getCallRenderer() - { - return VideoConferenceCallPanel.this; - } - - public Component getComponent() - { - return this; - } - - private ConferenceCallPeerRenderer - getConferenceCallPeerRendererDelegate() - { - return - (toolBar instanceof ConferenceCallPeerRenderer) - ? (ConferenceCallPeerRenderer) toolBar - : null; - } - - /** - * Gets the conference participant depicted by this instance. - * - * @return the conference participant depicted by this instance - */ - public Object getParticipant() - { - return (toolBar == null) ? null : toolBar.getParticipant(); - } - - public Component getVideo() - { - return video; - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. Otherwise, returns false. - */ - public boolean isLocalVideoVisible() - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - return (delegate == null) ? false : delegate.isLocalVideoVisible(); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void printDTMFTone(char dtmfChar) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.printDTMFTone(dtmfChar); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void securityNegotiationStarted( - CallPeerSecurityNegotiationStartedEvent ev) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.securityNegotiationStarted(ev); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void securityOff(CallPeerSecurityOffEvent ev) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.securityOff(ev); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void securityOn(CallPeerSecurityOnEvent ev) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.securityOn(ev); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void securityPending() - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.securityPending(); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void securityTimeout(CallPeerSecurityTimeoutEvent ev) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.securityTimeout(ev); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setErrorReason(String reason) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setErrorReason(reason); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setLocalVideoVisible(boolean visible) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setLocalVideoVisible(visible); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setMute(boolean mute) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setMute(mute); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setOnHold(boolean onHold) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setOnHold(onHold); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setPeerImage(byte[] image) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setPeerImage(image); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setPeerName(String name) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setPeerName(name); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setPeerState( - CallPeerState oldState, - CallPeerState newState, - String stateString) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setPeerState(oldState, newState, stateString); - } - - /** - * {@inheritDoc} - * - * Delegates to the toolBar, if the latter implements - * ConferenceCallPeerRenderer, because this instance is a - * container only. - */ - public void setSecurityPanelVisible(boolean visible) - { - ConferenceCallPeerRenderer delegate - = getConferenceCallPeerRendererDelegate(); - - if (delegate != null) - delegate.setSecurityPanelVisible(visible); - } - - /** - * Sets the visual Component displaying the video associated - * with the participant depicted by this instance. - * - * @param video the visual Component displaying video which is - * to be associated with the participant depicted by this instance - */ - void setVideo(Component video) - { - if (this.video != video) - { - if (this.video != null) - videoContainer.remove(this.video); - - this.video = video; - - if (this.video != null) - { - setVisible(true); - videoContainer.add(this.video, VideoLayout.CENTER_REMOTE); - } - else - setVisible(false); - - // Update thumbnails container according to video status. - if (thumbnailContainer != null) - { - if (conferenceMember != null) - thumbnailContainer - .updateThumbnail(conferenceMember, (video != null)); - else if (callPeer != null) - thumbnailContainer - .updateThumbnail(callPeer, (video != null)); - else if (isLocalUser) - thumbnailContainer - .updateThumbnail((video != null)); - } - } - } - } -} +package net.java.sip.communicator.impl.gui.main.call.conference; + +import java.awt.*; +import java.util.*; +import java.util.List; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.desktoputil.TransparentPanel; + +import org.jitsi.util.swing.*; + +/** + * Extends BasicConferenceCallPanel to implement a user interface + * Component which depicts a CallConference with audio and + * video and is contained in a CallPanel. + * + * @author Yana Stamcheva + * @author Lyubomir Marinov + */ +public class VideoConferenceCallPanel + extends BasicConferenceCallPanel +{ + /** + * The Logger used by the VideoConferenceCallPanel class + * and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(VideoConferenceCallPanel.class); + + /** + * The compile-time flag which indicates whether each video displayed by + * VideoConferenceCallPanel is to be depicted with an associated + * tool bar showing information and controls related to the (local or + * remote) peer sending the respective video. + */ + private static final boolean SHOW_TOOLBARS = true; + + /** + * The facility which aids this instance with the video-related information. + */ + private final UIVideoHandler2 uiVideoHandler; + + /** + * The Observer which listens to {@link #uiVideoHandler} about + * changes in the video-related information. + */ + private final Observer uiVideoHandlerObserver + = new Observer() + { + public void update(Observable o, Object arg) + { + updateViewFromModel(); + } + }; + + /** + * The VideoContainer which occupies this whole Component + * and arranges the visual Components displaying the video + * streaming between the local peer/user and the remote peer(s). + */ + private final VideoContainer videoContainer; + + /** + * The set of visual Components displaying video streaming between + * the local peer/user and the remote peers which are depicted by this + * instance. + */ + private final Set videos = new HashSet(); + + /** + * The thumbnail container. + */ + private final ThumbnailConferenceCallPanel thumbnailContainer; + + private final JPanel thumbnailPanel; + + /** + * Initializes a new VideoConferenceCallPanel instance which is to + * be used by a specific CallPanel to depict a specific + * CallConference. The new instance will depict both the + * audio-related and the video-related information. + * + * @param callPanel the CallPanel which will use the new instance + * to depict the specified CallConference. + * @param callConference the CallConference to be depicted by the + * new instance + * @param uiVideoHandler the utility which is to aid the new instance in + * dealing with the video-related information + */ + public VideoConferenceCallPanel( + CallPanel callPanel, + CallConference callConference, + UIVideoHandler2 uiVideoHandler) + { + super(callPanel, callConference); + + this.uiVideoHandler = uiVideoHandler; + + thumbnailPanel = new JPanel(new BorderLayout()); + thumbnailContainer + = new ThumbnailConferenceCallPanel( callPanel, + callConference, + uiVideoHandler); + + videoContainer = createVideoContainer(); + + /* + * Our user interface hierarchy has been initialized so we are ready to + * begin receiving events warranting updates of this view from its + * model. + */ + uiVideoHandler.addObserver(uiVideoHandlerObserver); + + /* + * Notify the super that this instance has completed its initialization + * and the view that it implements is ready to be updated from the + * model. + */ + initializeComplete(); + } + + private void addConferenceMemberContainers( + ConferenceParticipantContainer cpc) + { + List cmcs + = cpc.conferenceMemberContainers; + + if ((cmcs != null) && !cmcs.isEmpty()) + { + for (ConferenceParticipantContainer cmc : cmcs) + { + if (!cmc.toBeRemoved) + { + videoContainer.add( + cmc.getComponent(), + VideoLayout.CENTER_REMOTE); + } + } + } + } + + private Component createDefaultPhotoPanel(Call call) + { + OperationSetServerStoredAccountInfo accountInfo + = call.getProtocolProvider().getOperationSet( + OperationSetServerStoredAccountInfo.class); + ImageIcon photoLabelIcon = null; + + if (accountInfo != null) + { + byte[] accountImage = AccountInfoUtils.getImage(accountInfo); + + // do not set empty images + if ((accountImage != null) && (accountImage.length > 0)) + photoLabelIcon = new ImageIcon(accountImage); + } + if (photoLabelIcon == null) + { + photoLabelIcon + = new ImageIcon( + ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)); + } + + return createDefaultPhotoPanel(photoLabelIcon); + } + + private Component createDefaultPhotoPanel(CallPeer callPeer) + { + byte[] peerImage = CallManager.getPeerImage(callPeer); + ImageIcon photoLabelIcon + = (peerImage == null) + ? new ImageIcon( + ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO)) + : new ImageIcon(peerImage); + + return createDefaultPhotoPanel(photoLabelIcon); + } + + private Component createDefaultPhotoPanel(ConferenceMember conferenceMember) + { + return + createDefaultPhotoPanel( + new ImageIcon( + ImageLoader.getImage( + ImageLoader.DEFAULT_USER_PHOTO))); + } + + /** + * Creates a new Component which is to display a specific + * ImageIcon representing the photo of a participant in a call. + * + * @param photoLabelIcon the ImageIcon which represents the photo + * of a participant in a call and which is to be displayed by the new + * Component + * @return a new Component which displays the specified + * photoLabelIcon + */ + private Component createDefaultPhotoPanel(ImageIcon photoLabelIcon) + { + JLabel photoLabel = new JLabel(); + + photoLabel.setIcon(photoLabelIcon); + + @SuppressWarnings("serial") + JPanel photoPanel + = new TransparentPanel(new GridBagLayout()) + { + /** + * @{inheritDoc} + */ + @Override + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + g = g.create(); + try + { + AntialiasingManager.activateAntialiasing(g); + + g.setColor(Color.GRAY); + g.fillRoundRect( + 0, 0, this.getWidth(), this.getHeight(), + 6, 6); + } + finally + { + g.dispose(); + } + } + }; + + photoPanel.setPreferredSize(new Dimension(320, 240)); + + GridBagConstraints photoPanelConstraints = new GridBagConstraints(); + + photoPanelConstraints.anchor = GridBagConstraints.CENTER; + photoPanelConstraints.fill = GridBagConstraints.NONE; + photoPanel.add(photoLabel, photoPanelConstraints); + + return photoPanel; + } + + /** + * Initializes a new VideoContainer instance which is to contain + * the visual/video Components of the telephony conference depicted + * by this instance. + */ + private VideoContainer createVideoContainer() + { + VideoContainer videoContainer = new VideoContainer(null, true); + + thumbnailPanel.setBackground(Color.DARK_GRAY); + thumbnailPanel.add(thumbnailContainer, BorderLayout.NORTH); + + add(thumbnailPanel, BorderLayout.EAST); + add(videoContainer, BorderLayout.CENTER); + + return videoContainer; + } + + /** + * Shows/hides the participants thumbnails list. + * + * @param show true to show the participants list, false + * to hide it + */ + public void showThumbnailsList(boolean show) + { + thumbnailPanel.setVisible(show); + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() + { + try + { + uiVideoHandler.deleteObserver(uiVideoHandlerObserver); + } + finally + { + super.dispose(); + } + } + + /** + * Determines whether a specific ConferenceMember represents the + * same conference participant as a specific CallPeer. If the + * specified conferenceMember is null, returns + * true. Otherwise, determines whether the addresses of the + * specified conferenceMember and the specified callPeer + * identify one and the same entity. + * + * @param conferenceMember the ConferenceMember to be checked + * whether is represents the same conference participant as the specified + * callPeer. If it is null, true is returned. + * @param callPeer the CallPeer to be checked whether it represents + * the same conference participant as the specified + * conferenceMember + * @return true if the specified conferenceMember and the + * specified callPeer represent the same conference participant or + * the specified conferenceMember is null; otherwise, + * false + */ + private boolean isConferenceMemberCallPeer( + ConferenceMember conferenceMember, + CallPeer callPeer) + { + return + (conferenceMember == null) + ? true + : CallManager.addressesAreEqual( + conferenceMember.getAddress(), + callPeer.getAddress()); + } + + /** + * Determines whether a specific ConferenceMember represents the + * local peer/user. Since this instance depicts a whole telephony + * conference, the local peer/user may be participating with multiple + * Calls in it. The Calls may be through different + * (local) accounts. That's why the implementation determines whether the + * address of the specified conferenceMember identifies the address + * of a (local) accounts involved in the telephony conference depicted by + * this instance. + * + * @param conferenceMember the ConferenceMember to be checked + * whether it represents the local peer/user + * @return true if the specified conferenceMember + * represents the local peer/user; otherwise, false + */ + private boolean isConferenceMemberLocalUser( + ConferenceMember conferenceMember) + { + String address = conferenceMember.getAddress(); + + for (Call call : callConference.getCalls()) + { + if (CallManager.addressesAreEqual( + address, + call.getProtocolProvider().getAccountID() + .getAccountAddress())) + { + return true; + } + } + return false; + } + + private void removeConferenceMemberContainers( + ConferenceParticipantContainer cpc, + boolean all) + { + List cmcs + = cpc.conferenceMemberContainers; + + if ((cmcs != null) && !cmcs.isEmpty()) + { + Iterator i = cmcs.iterator(); + + while (i.hasNext()) + { + ConferenceParticipantContainer cmc = i.next(); + + if (all || cmc.toBeRemoved) + { + i.remove(); + + videoContainer.remove(cmc.getComponent()); + cmc.dispose(); + } + } + } + } + + /** + * Updates the ConferenceParticipantContainers which depict the + * ConferenceMembers of the CallPeer depicted by a + * specific ConferenceParticipantContainer. + * + * @param cpc the ConferenceParticipantContainer which depicts the + * CallPeer whose ConferenceMembers are to be depicted + * @param videos the visual Components displaying video streaming + * from the remote peer (represented by cpc) to the local peer/user + * @param videoTelephony the OperationSetVideoTelephony which + * retrieved the specified videos from the CallPeer + * depicted by cpc. While the CallPeer could be queried + * for it, such a query would waste more resources at run time given that + * the invoker has it already. + */ + private void updateConferenceMemberContainers( + ConferenceParticipantContainer cpc, + List videos, + OperationSetVideoTelephony videoTelephony) + { + CallPeer callPeer = (CallPeer) cpc.getParticipant(); + List cmcs + = cpc.conferenceMemberContainers; + + /* + * Invalidate all conferenceMemberContainers. Then validate which of + * them are to remain and which of them are to really be removed + * later on. + */ + if (cmcs != null) + { + for (ConferenceParticipantContainer cmc : cmcs) + cmc.toBeRemoved = true; + } + + /* + * Depict the remote videos. They may or may not be associated with + * ConferenceMembers so the ConferenceMembers which have no + * associated videos will be depicted afterwards. + */ + if (videos != null) + { + Component video = cpc.getVideo(); + + for (Component conferenceMemberVideo : videos) + { + /* + * One of the remote videos is already used to depict the + * callPeer. + */ + if (conferenceMemberVideo == video) + continue; + + boolean addNewConferenceParticipantContainer = true; + ConferenceMember conferenceMember + = videoTelephony.getConferenceMember( + callPeer, + conferenceMemberVideo); + + if (cmcs == null) + { + cmcs = new LinkedList(); + cpc.conferenceMemberContainers = cmcs; + } + else + { + for (ConferenceParticipantContainer cmc : cmcs) + { + Object cmcParticipant = cmc.getParticipant(); + + if (conferenceMember == null) + { + if (cmcParticipant == callPeer) + { + Component cmcVideo = cmc.getVideo(); + + if (cmcVideo == null) + { + cmc.setVideo(conferenceMemberVideo); + cmc.toBeRemoved = false; + addNewConferenceParticipantContainer + = false; + break; + } + else if (cmcVideo == conferenceMemberVideo) + { + cmc.toBeRemoved = false; + addNewConferenceParticipantContainer + = false; + break; + } + } + } + else if (cmcParticipant == conferenceMember) + { + cmc.setVideo(conferenceMemberVideo); + cmc.toBeRemoved = false; + addNewConferenceParticipantContainer = false; + break; + } + } + } + + if (addNewConferenceParticipantContainer) + { + ConferenceParticipantContainer cmc + = (conferenceMember == null) + ? new ConferenceParticipantContainer( + callPeer, + conferenceMemberVideo) + : new ConferenceParticipantContainer( + conferenceMember, + conferenceMemberVideo); + + cmcs.add(cmc); + } + } + } + + /* + * Depict the ConferenceMembers which have not been depicted yet. + * They have no associated videos. + */ + List conferenceMembers + = callPeer.getConferenceMembers(); + + if (!conferenceMembers.isEmpty()) + { + if (cmcs == null) + { + cmcs = new LinkedList(); + cpc.conferenceMemberContainers = cmcs; + } + for (ConferenceMember conferenceMember : conferenceMembers) + { + /* + * If the callPeer reports itself as a ConferenceMember, then + * we've already depicted it with cpc. + */ + if (isConferenceMemberCallPeer(conferenceMember, callPeer)) + continue; + /* + * If the callPeer reports the local peer/user as a + * ConferenceMember, then we've already depicted it. + */ + if (isConferenceMemberLocalUser(conferenceMember)) + continue; + + boolean addNewConferenceParticipantContainer = true; + + for (ConferenceParticipantContainer cmc : cmcs) + { + if (cmc.getParticipant() == conferenceMember) + { + /* + * It is possible to have a ConferenceMember who is + * sending video but we just do not have the SSRC of + * that video to associate the video with the + * ConferenceMember. In such a case, we may be depicting + * the ConferenceMember twice: once with video without a + * ConferenceMember and once with a ConferenceMember + * without video. This will surely be the case at the + * time of this writing with non-focus participants in a + * telephony conference hosted on a Jitsi Videobridge. + * Such a display is undesirable. If the + * conferenceMember is known to send video, we will not + * display it until we associated it with a video. This + * way, if a ConferenceMember is not sending video, we + * will depict it and we can be sure that no video + * without a ConferenceMember association will be + * depicting it a second time. + */ + if (cmc.toBeRemoved + && !conferenceMember + .getVideoStatus() + .allowsSending()) + { + cmc.setVideo(null); + cmc.toBeRemoved = false; + } + addNewConferenceParticipantContainer = false; + break; + } + } + + if (addNewConferenceParticipantContainer) + { + ConferenceParticipantContainer cmc + = new ConferenceParticipantContainer( + conferenceMember, + null); + + cmcs.add(cmc); + } + } + } + + if ((cmcs != null) && !cmcs.isEmpty()) + { + removeConferenceMemberContainers(cpc, false); + /* + * If cpc is already added to the user interface hierarchy of this + * instance, then it was there before the update procedure and it + * was determined to be appropriate to continue to depict its model. + * Consequently, its Component will be neither added to (because it + * was already added) nor removed from the user interface hierarchy + * of this instance. That's why we have make sure that the + * Components of its conferenceMemberContainers are also added to + * the user interface. + */ + if (UIVideoHandler2.isAncestor(this, cpc.getComponent())) + addConferenceMemberContainers(cpc); + } + } + + /** + * {@inheritDoc} + */ + @Override + protected ConferenceCallPeerRenderer updateViewFromModel( + ConferenceCallPeerRenderer callPeerPanel, + CallPeer callPeer) + { + if (callPeer == null) + { + /* + * The local peer/user will be represented by a Call which has a + * CallPeer who provides local video. However, if the user has + * selected to hide the local video, the local peer/user will not be + * represented at all. + */ + Component video = null; + + if (uiVideoHandler.isLocalVideoVisible()) + { + for (Call aCall : callConference.getCalls()) + { + Iterator callPeerIter + = aCall.getCallPeers(); + OperationSetVideoTelephony videoTelephony + = aCall.getProtocolProvider().getOperationSet( + OperationSetVideoTelephony.class); + + while (callPeerIter.hasNext()) + { + callPeer = callPeerIter.next(); + + if (videoTelephony != null) + { + try + { + video + = videoTelephony.getLocalVisualComponent( + callPeer); + } + catch (OperationFailedException ofe) + { + logger.error( + "Failed to retrieve the local video" + + " for display", + ofe); + } + if (video != null) + break; + } + } + if (video != null) + break; + } + } + + if (callPeer == null) + callPeerPanel = null; + else + { + Call call = callPeer.getCall(); + + if (callPeerPanel instanceof ConferenceParticipantContainer) + { + ConferenceParticipantContainer cpc + = (ConferenceParticipantContainer) callPeerPanel; + + if (cpc.getParticipant() == call) + cpc.setVideo(video); + else + callPeerPanel = null; + } + else + callPeerPanel = null; + if (callPeerPanel == null) + { + callPeerPanel + = new ConferenceParticipantContainer(call, video); + } + } + } + else + { + /* + * The specified callPeer will be represented by one of its remote + * videos which is not associated with a ConferenceMember or is + * associated with a ConferenceMember representing the callPeer + * itself. + */ + OperationSetVideoTelephony videoTelephony + = callPeer.getProtocolProvider().getOperationSet( + OperationSetVideoTelephony.class); + List videos = null; + Component video = null; + + if (videoTelephony != null) + { + videos = videoTelephony.getVisualComponents(callPeer); + if ((videos != null) && !videos.isEmpty()) + { + for (Component aVideo : videos) + { + ConferenceMember conferenceMember + = videoTelephony.getConferenceMember( + callPeer, + aVideo); + + if (isConferenceMemberCallPeer( + conferenceMember, + callPeer)) + { + video = aVideo; + break; + } + } + } + } + + ConferenceParticipantContainer cpc = null; + + if (callPeerPanel instanceof ConferenceParticipantContainer) + { + cpc = (ConferenceParticipantContainer) callPeerPanel; + if (cpc.getParticipant() == callPeer) + cpc.setVideo(video); + else + cpc = null; + } + if (cpc == null) + cpc = new ConferenceParticipantContainer(callPeer, video); + callPeerPanel = cpc; + + // Update the conferenceMemberContainers of the cpc. + updateConferenceMemberContainers(cpc, videos, videoTelephony); + } + return callPeerPanel; + } + + /** + * {@inheritDoc} + * + * If {@link #SHOW_TOOLBARS} is false, disables the use of + * ConferenceParticipantContainer. A reason for such a value of + * SHOW_TOOLBARS may be that the functionality implemented in the + * model may not fully support mapping of visual Components + * displaying video to telephony conference participants (e.g. in telephony + * conferences utilizing the Jitsi Videobridge server-side technology). In + * such a case displays the videos only, does not map videos to participants + * and does not display participants who do not have videos. + */ + @Override + protected void updateViewFromModelInEventDispatchThread() + { + if (SHOW_TOOLBARS) + { + super.updateViewFromModelInEventDispatchThread(); + return; + } + + /* + * Determine the set of visual Components displaying video streaming + * between the local peer/user and the remote peers which are to be + * depicted by this instance. + */ + Component localVideo = null; + Set videos = new HashSet(); + + for (Call call : callConference.getCalls()) + { + OperationSetVideoTelephony videoTelephony + = call.getProtocolProvider().getOperationSet( + OperationSetVideoTelephony.class); + + if (videoTelephony == null) + continue; + + Iterator callPeerIter = call.getCallPeers(); + + while (callPeerIter.hasNext()) + { + CallPeer callPeer = callPeerIter.next(); + + /* + * TODO VideoConferenceCallPanel respects + * UIVideoHandler2.isLocalVideoVisible() in order to react to + * the associated button at the bottom of the CallPanel. + * However, it does not add a close button on top of the local + * video in contrast to OneToOneCallPeerPanel. Overall, the + * result is questionable. + */ + if (uiVideoHandler.isLocalVideoVisible() + && (localVideo == null)) + { + try + { + localVideo + = videoTelephony.getLocalVisualComponent(callPeer); + } + catch (OperationFailedException ofe) + { + /* + * We'll just try to get the local video through another + * CallPeer then. + */ + } + if (localVideo != null) + videos.add(localVideo); + } + + List callPeerRemoteVideos + = videoTelephony.getVisualComponents(callPeer); + + videos.addAll(callPeerRemoteVideos); + } + } + + /* + * Remove the Components of this view which are no longer present in the + * model. + */ + Iterator thisVideoIter = this.videos.iterator(); + + while (thisVideoIter.hasNext()) + { + Component thisVideo = thisVideoIter.next(); + + if (!videos.contains(thisVideo)) + { + thisVideoIter.remove(); + videoContainer.remove(thisVideo); + } + + /* + * If a video is known to be depicted by this view and is still + * present in the model, then we could remove it from the set of + * videos present in the model in order to prevent going through the + * procedure of adding it to this view. However, we choose to play + * on the safe side. + */ + } + + /* + * Add the Components of the model which are not depicted by this view. + */ + for (Component video : videos) + { + if (!UIVideoHandler2.isAncestor(videoContainer, video)) + { + this.videos.add(video); + videoContainer.add( + video, + (video == localVideo) + ? VideoLayout.LOCAL + : VideoLayout.CENTER_REMOTE); + } + } + } + + @Override + protected void viewForModelAdded( + ConferenceCallPeerRenderer callPeerPanel, + CallPeer callPeer) + { + videoContainer.add( + callPeerPanel.getComponent(), + VideoLayout.CENTER_REMOTE); + if ((callPeer != null) + && (callPeerPanel instanceof ConferenceParticipantContainer)) + { + addConferenceMemberContainers( + (ConferenceParticipantContainer) callPeerPanel); + } + } + + @Override + protected void viewForModelRemoved( + ConferenceCallPeerRenderer callPeerPanel, + CallPeer callPeer) + { + videoContainer.remove(callPeerPanel.getComponent()); + if ((callPeer != null) + && (callPeerPanel instanceof ConferenceParticipantContainer)) + { + removeConferenceMemberContainers( + (ConferenceParticipantContainer) callPeerPanel, + true); + } + } + + /** + * Implements an AWT Component which contains the user interface + * elements depicting a specific participant in the telephony conference + * depicted by a VideoConferenceCallPanel. + */ + private class ConferenceParticipantContainer + extends TransparentPanel + implements ConferenceCallPeerRenderer + { + /** + * The list of ConferenceParticipantContainers which represent + * the ConferenceMembers of the participant represented by this + * instance. Since a CallPeer may send the local peer/user + * multiple videos without providing a way to associate a + * ConferenceMember with each one of them, the list may contain + * ConferenceParticipantContainers which do not represent a + * specific ConferenceMember instance but rather a video sent + * by a CallPeer to the local peer/user which looks like (in + * the terms of VideoConferenceCallPanel) a member of a conference + * organized by the CallPeer in question. + *

    + * Implements a state which is private to + * VideoConferenceCallPanel and is of no concern to + * ConferenceParticipantContainer. + *

    + */ + List conferenceMemberContainers; + + /** + * The indicator which determines whether this instance is to be removed + * because it has become out-of-date, obsolete, unnecessary. + *

    + * Implements a state which is private to + * VideoConferenceCallPanel and is of no concern to + * ConferenceParticipantContainer. + *

    + */ + boolean toBeRemoved; + + /** + * The BasicConferenceParticipantPanel which is displayed at + * the bottom of this instance, bellow the {@link #video} (i.e. + * {@link #videoContainer}) and is referred to as the tool bar. + */ + private final BasicConferenceParticipantPanel toolBar; + + /** + * The visual Component, if any, displaying video which is + * depicted by this instance. + */ + private Component video; + + /** + * The VideoContainer which lays out the video depicted by this + * instance i.e. {@link #video}. + */ + private final VideoContainer videoContainer; + + /** + * The CallPeer associated with this container, if it has been + * created to represent a CallPeer. + */ + private CallPeer callPeer; + + /** + * The conferenceMember associated with this container, if it + * has been created to represent a conferenceMember. + */ + private ConferenceMember conferenceMember; + + /** + * Indicates that this container contains information for the local + * user. + */ + private boolean isLocalUser; + + /** + * Initializes a new ConferenceParticipantContainer instance + * which is to depict the local peer/user. + * + * @param call a Call which is to provide information about the + * local peer/user + * @param video the visual Component, if any, displaying the + * video streaming from the local peer/user to the remote peer(s) + */ + public ConferenceParticipantContainer(Call call, Component video) + { + this( + createDefaultPhotoPanel(call), + video, + new ConferencePeerPanel( + VideoConferenceCallPanel.this, + call, + true), + null, null, true); + } + + public ConferenceParticipantContainer( + CallPeer callPeer, + Component video) + { + this( createDefaultPhotoPanel(callPeer), + video, + new ConferencePeerPanel( + VideoConferenceCallPanel.this, + callPeer, + true), + callPeer, null, false); + } + + private ConferenceParticipantContainer( + Component noVideo, + Component video, + BasicConferenceParticipantPanel toolBar, + CallPeer callPeer, + ConferenceMember conferenceMember, + boolean isLocalUser) + { + super(new BorderLayout()); + + this.callPeer = callPeer; + this.conferenceMember = conferenceMember; + this.isLocalUser = isLocalUser; + + videoContainer = new VideoContainer(noVideo, false); + add(videoContainer, BorderLayout.CENTER); + + this.toolBar = toolBar; + if (this.toolBar != null) + add(this.toolBar, BorderLayout.SOUTH); + + if (video != null) + { + setVideo(video); + } + else + setVisible(false); + } + + public ConferenceParticipantContainer( + ConferenceMember conferenceMember, + Component video) + { + this( + createDefaultPhotoPanel(conferenceMember), + video, + new ConferenceMemberPanel( + VideoConferenceCallPanel.this, + conferenceMember, + true), + null, conferenceMember, false); + } + + public void dispose() + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.dispose(); + + // Dispose of the conferenceMemberContainers if any. + /* + * XXX The field conferenceMemberContainers implements a state + * private to VideoConferenceCallPanel which the latter makes sure + * to access on the AWT event dispatching thread only. Since we are + * going out of our way here to help VideoConferenceCallPanel, + * ensure that the mentioned synchronization rule is not violated. + */ + CallManager.assertIsEventDispatchingThread(); + if (conferenceMemberContainers != null) + { + for (ConferenceParticipantContainer cmc + : conferenceMemberContainers) + { + cmc.dispose(); + } + } + } + + public CallPanel getCallPanel() + { + return getCallRenderer().getCallContainer(); + } + + public SwingCallRenderer getCallRenderer() + { + return VideoConferenceCallPanel.this; + } + + public Component getComponent() + { + return this; + } + + private ConferenceCallPeerRenderer + getConferenceCallPeerRendererDelegate() + { + return + (toolBar instanceof ConferenceCallPeerRenderer) + ? (ConferenceCallPeerRenderer) toolBar + : null; + } + + /** + * Gets the conference participant depicted by this instance. + * + * @return the conference participant depicted by this instance + */ + public Object getParticipant() + { + return (toolBar == null) ? null : toolBar.getParticipant(); + } + + public Component getVideo() + { + return video; + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. Otherwise, returns false. + */ + public boolean isLocalVideoVisible() + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + return (delegate == null) ? false : delegate.isLocalVideoVisible(); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void printDTMFTone(char dtmfChar) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.printDTMFTone(dtmfChar); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void securityNegotiationStarted( + CallPeerSecurityNegotiationStartedEvent ev) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.securityNegotiationStarted(ev); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void securityOff(CallPeerSecurityOffEvent ev) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.securityOff(ev); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void securityOn(CallPeerSecurityOnEvent ev) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.securityOn(ev); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void securityPending() + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.securityPending(); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void securityTimeout(CallPeerSecurityTimeoutEvent ev) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.securityTimeout(ev); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setErrorReason(String reason) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setErrorReason(reason); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setLocalVideoVisible(boolean visible) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setLocalVideoVisible(visible); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setMute(boolean mute) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setMute(mute); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setOnHold(boolean onHold) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setOnHold(onHold); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setPeerImage(byte[] image) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setPeerImage(image); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setPeerName(String name) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setPeerName(name); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setPeerState( + CallPeerState oldState, + CallPeerState newState, + String stateString) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setPeerState(oldState, newState, stateString); + } + + /** + * {@inheritDoc} + * + * Delegates to the toolBar, if the latter implements + * ConferenceCallPeerRenderer, because this instance is a + * container only. + */ + public void setSecurityPanelVisible(boolean visible) + { + ConferenceCallPeerRenderer delegate + = getConferenceCallPeerRendererDelegate(); + + if (delegate != null) + delegate.setSecurityPanelVisible(visible); + } + + /** + * Sets the visual Component displaying the video associated + * with the participant depicted by this instance. + * + * @param video the visual Component displaying video which is + * to be associated with the participant depicted by this instance + */ + void setVideo(Component video) + { + if (this.video != video) + { + if (this.video != null) + videoContainer.remove(this.video); + + this.video = video; + + if (this.video != null) + { + setVisible(true); + videoContainer.add(this.video, VideoLayout.CENTER_REMOTE); + } + else + setVisible(false); + + // Update thumbnails container according to video status. + if (thumbnailContainer != null) + { + if (conferenceMember != null) + thumbnailContainer + .updateThumbnail(conferenceMember, (video != null)); + else if (callPeer != null) + thumbnailContainer + .updateThumbnail(callPeer, (video != null)); + else if (isLocalUser) + thumbnailContainer + .updateThumbnail((video != null)); + } + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSessionChangeListener.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSessionChangeListener.java index 0b96069..1e6127e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSessionChangeListener.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSessionChangeListener.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,32 +15,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.chat; - -/** - * Listens for changes in {@link ChatSession}. - * @author George Politis - */ -public interface ChatSessionChangeListener -{ - /** - * The icon representing the ChatTransport has changed. - */ - public static final int ICON_UPDATED = 1; - - /** - * Called when the current {@link ChatTransport} has - * changed. - * - * @param chatSession the {@link ChatSession} it's current - * {@link ChatTransport} has changed - */ - public void currentChatTransportChanged(ChatSession chatSession); - - /** - * When a property of the chatTransport has changed. - * @param eventID the event id representing the property of the transport - * that has changed. - */ - public void currentChatTransportUpdated(int eventID); -} +package net.java.sip.communicator.impl.gui.main.chat; + +/** + * Listens for changes in {@link ChatSession}. + * @author George Politis + */ +public interface ChatSessionChangeListener +{ + /** + * The icon representing the ChatTransport has changed. + */ + public static final int ICON_UPDATED = 1; + + /** + * Called when the current {@link ChatTransport} has + * changed. + * + * @param chatSession the {@link ChatSession} it's current + * {@link ChatTransport} has changed + */ + public void currentChatTransportChanged(ChatSession chatSession); + + /** + * When a property of the chatTransport has changed. + * @param eventID the event id representing the property of the transport + * that has changed. + */ + public void currentChatTransportUpdated(int eventID); +} diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactListModel.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactListModel.java index d42ecfb..acf36bf 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactListModel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactListModel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,235 +15,235 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.chat.conference; - -import java.util.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.main.chat.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.event.*; - -/** - * Implements an AbstractListModel which represents a member list of - * ChatContacts. The primary purpose of the implementation is to sort - * the ChatContacts according to their member roles and in alphabetical - * order according to their names. - * - * @author Lyubomir Marinov - */ -public class ChatContactListModel - extends AbstractListModel - implements ChatRoomMemberPropertyChangeListener -{ - - /** - * The backing store of this AbstractListModel listing the - * ChatContacts. - */ - private final List> chatContacts - = new ArrayList>(); - - /** - * Current chat session. - */ - private ChatSession chatSession; - - /** - * The implementation of the sorting rules - the ChatContacts are - * first sorted according to their roles in decreasing order of their - * privileges and then they are sorted according to their names in - * alphabetical order. - */ - private final Comparator> sorter - = new Comparator>() - { - public int compare(ChatContact chatContact0, ChatContact chatContact1) - { - /* - * Place ChatMembers with more privileges at the beginning of - * the list. - */ - if (chatContact0 instanceof ConferenceChatContact) - { - if (chatContact1 instanceof ConferenceChatContact) - { - int role0 - = ((ConferenceChatContact) chatContact0).getRole() - .getRoleIndex(); - int role1 - = ((ConferenceChatContact) chatContact1).getRole() - .getRoleIndex(); - - if (role0 > role1) - return -1; - else if (role0 < role1) - return 1; - } - else - return -1; - } - else if (chatContact1 instanceof ConferenceChatContact) - return 1; - - /* By default, sort the ChatContacts in alphabetical order. */ - return - chatContact0.getName().compareToIgnoreCase( - chatContact1.getName()); - } - }; - - /** - * Creates the model. - * @param chatSession The current model chat session. - */ - public ChatContactListModel(ChatSession chatSession) - { - this.chatSession = chatSession; - - // when something like rename on a member change update the UI to - // reflect it - Object descriptor = chatSession.getDescriptor(); - - if(descriptor instanceof ChatRoomWrapper) - { - ((ChatRoomWrapper) descriptor) - .getChatRoom().addMemberPropertyChangeListener(this); - } - } - - /** - * Listens for property change in chat room members. - * @param ev the event - */ - public void chatRoomPropertyChanged(ChatRoomMemberPropertyChangeEvent ev) - { - // Translate into - // ListDataListener.contentsChanged. - int chatContactCount = chatContacts.size(); - - for (int i = 0; i < chatContactCount; i++) - { - ChatContact chatContact = chatContacts.get(i); - - if(chatContact.getDescriptor().equals(ev.getSourceChatRoomMember())) - { - fireContentsChanged(chatContact, i, i); - /* - * TODO Can ev.sourceChatRoomMember - * equal more than one chatContacts - * element? If it cannot, it will be - * more efficient to break here. - */ - } - } - } - - /** - * Adds a specific ChatContact to this AbstractListModel - * implementation and preserves the sorting it applies. - * - * @param chatContact a ChatContact to be added to this - * AbstractListModel - */ - public void addElement(ChatContact chatContact) - { - if (chatContact == null) - throw new IllegalArgumentException("chatContact"); - - int index = -1; - - synchronized(chatContacts) - { - int chatContactCount = chatContacts.size(); - - for (int i = 0; i < chatContactCount; i++) - { - ChatContact containedChatContact = chatContacts.get(i); - - // We don't want duplicates. - if (chatContact.equals(containedChatContact)) - return; - if ((index == -1) - && (sorter.compare(containedChatContact, chatContact) > 0)) - { - index = i; - // Continue in order to prevent duplicates. - } - } - if (index == -1) - index = chatContactCount; - - chatContacts.add(index, chatContact); - } - fireIntervalAdded(this, index, index); - } - - /* Implements ListModel#getElementAt(int). */ - public ChatContact getElementAt(int index) - { - synchronized(chatContacts) - { - return chatContacts.get(index); - } - } - - /* Implements ListModel#getSize(). */ - public int getSize() - { - synchronized(chatContacts) - { - return chatContacts.size(); - } - } - - /** - * Removes a specific ChatContact from this - * AbstractListModel implementation. - * - * @param chatContact a ChatContact to be removed from this - * AbstractListModel if it's already contained - */ - public void removeElement(ChatContact chatContact) - { - synchronized(chatContacts) - { - int index = chatContacts.indexOf(chatContact); - - if ((index >= 0) && chatContacts.remove(chatContact)) - fireIntervalRemoved(this, index, index); - } - } - - /** - * Removes all the elements from this model. - */ - public void removeAllElements() - { - if (chatContacts == null || chatContacts.size() <= 0) - return; - - synchronized(chatContacts) - { - int contactsSize = chatContacts.size(); - chatContacts.clear(); - - fireIntervalRemoved(this, 0, contactsSize - 1); - } - } - - /** - * Runs clean-up. - */ - public void dispose() - { - Object descriptor = chatSession.getDescriptor(); - - if(descriptor instanceof ChatRoomWrapper) - { - ((ChatRoomWrapper) descriptor) - .getChatRoom().removeMemberPropertyChangeListener(this); - } - } -} +package net.java.sip.communicator.impl.gui.main.chat.conference; + +import java.util.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.main.chat.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.event.*; + +/** + * Implements an AbstractListModel which represents a member list of + * ChatContacts. The primary purpose of the implementation is to sort + * the ChatContacts according to their member roles and in alphabetical + * order according to their names. + * + * @author Lyubomir Marinov + */ +public class ChatContactListModel + extends AbstractListModel + implements ChatRoomMemberPropertyChangeListener +{ + + /** + * The backing store of this AbstractListModel listing the + * ChatContacts. + */ + private final List> chatContacts + = new ArrayList>(); + + /** + * Current chat session. + */ + private ChatSession chatSession; + + /** + * The implementation of the sorting rules - the ChatContacts are + * first sorted according to their roles in decreasing order of their + * privileges and then they are sorted according to their names in + * alphabetical order. + */ + private final Comparator> sorter + = new Comparator>() + { + public int compare(ChatContact chatContact0, ChatContact chatContact1) + { + /* + * Place ChatMembers with more privileges at the beginning of + * the list. + */ + if (chatContact0 instanceof ConferenceChatContact) + { + if (chatContact1 instanceof ConferenceChatContact) + { + int role0 + = ((ConferenceChatContact) chatContact0).getRole() + .getRoleIndex(); + int role1 + = ((ConferenceChatContact) chatContact1).getRole() + .getRoleIndex(); + + if (role0 > role1) + return -1; + else if (role0 < role1) + return 1; + } + else + return -1; + } + else if (chatContact1 instanceof ConferenceChatContact) + return 1; + + /* By default, sort the ChatContacts in alphabetical order. */ + return + chatContact0.getName().compareToIgnoreCase( + chatContact1.getName()); + } + }; + + /** + * Creates the model. + * @param chatSession The current model chat session. + */ + public ChatContactListModel(ChatSession chatSession) + { + this.chatSession = chatSession; + + // when something like rename on a member change update the UI to + // reflect it + Object descriptor = chatSession.getDescriptor(); + + if(descriptor instanceof ChatRoomWrapper) + { + ((ChatRoomWrapper) descriptor) + .getChatRoom().addMemberPropertyChangeListener(this); + } + } + + /** + * Listens for property change in chat room members. + * @param ev the event + */ + public void chatRoomPropertyChanged(ChatRoomMemberPropertyChangeEvent ev) + { + // Translate into + // ListDataListener.contentsChanged. + int chatContactCount = chatContacts.size(); + + for (int i = 0; i < chatContactCount; i++) + { + ChatContact chatContact = chatContacts.get(i); + + if(chatContact.getDescriptor().equals(ev.getSourceChatRoomMember())) + { + fireContentsChanged(chatContact, i, i); + /* + * TODO Can ev.sourceChatRoomMember + * equal more than one chatContacts + * element? If it cannot, it will be + * more efficient to break here. + */ + } + } + } + + /** + * Adds a specific ChatContact to this AbstractListModel + * implementation and preserves the sorting it applies. + * + * @param chatContact a ChatContact to be added to this + * AbstractListModel + */ + public void addElement(ChatContact chatContact) + { + if (chatContact == null) + throw new IllegalArgumentException("chatContact"); + + int index = -1; + + synchronized(chatContacts) + { + int chatContactCount = chatContacts.size(); + + for (int i = 0; i < chatContactCount; i++) + { + ChatContact containedChatContact = chatContacts.get(i); + + // We don't want duplicates. + if (chatContact.equals(containedChatContact)) + return; + if ((index == -1) + && (sorter.compare(containedChatContact, chatContact) > 0)) + { + index = i; + // Continue in order to prevent duplicates. + } + } + if (index == -1) + index = chatContactCount; + + chatContacts.add(index, chatContact); + } + fireIntervalAdded(this, index, index); + } + + /* Implements ListModel#getElementAt(int). */ + public ChatContact getElementAt(int index) + { + synchronized(chatContacts) + { + return chatContacts.get(index); + } + } + + /* Implements ListModel#getSize(). */ + public int getSize() + { + synchronized(chatContacts) + { + return chatContacts.size(); + } + } + + /** + * Removes a specific ChatContact from this + * AbstractListModel implementation. + * + * @param chatContact a ChatContact to be removed from this + * AbstractListModel if it's already contained + */ + public void removeElement(ChatContact chatContact) + { + synchronized(chatContacts) + { + int index = chatContacts.indexOf(chatContact); + + if ((index >= 0) && chatContacts.remove(chatContact)) + fireIntervalRemoved(this, index, index); + } + } + + /** + * Removes all the elements from this model. + */ + public void removeAllElements() + { + if (chatContacts == null || chatContacts.size() <= 0) + return; + + synchronized(chatContacts) + { + int contactsSize = chatContacts.size(); + chatContacts.clear(); + + fireIntervalRemoved(this, 0, contactsSize - 1); + } + } + + /** + * Runs clean-up. + */ + public void dispose() + { + Object descriptor = chatSession.getDescriptor(); + + if(descriptor instanceof ChatRoomWrapper) + { + ((ChatRoomWrapper) descriptor) + .getChatRoom().removeMemberPropertyChangeListener(this); + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java index 58a1db4..079e22b 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1390 +15,1390 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.chat.conference; - -import java.util.*; -import java.util.concurrent.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.chat.*; -import net.java.sip.communicator.impl.gui.main.chat.history.*; -import net.java.sip.communicator.impl.gui.main.chatroomslist.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.globalstatus.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.util.Logger; - -import org.jdesktop.swingworker.SwingWorker; -import org.jitsi.util.*; -import org.osgi.framework.*; - -/** - * The ConferenceChatManager is the one that manages both chat room and - * ad-hoc chat rooms invitations. - * - * @author Yana Stamcheva - * @author Lubomir Marinov - * @author Valentin Martinet - * @author Hristo Terezov - */ -public class ConferenceChatManager - implements ChatRoomMessageListener, - ChatRoomInvitationListener, - ChatRoomInvitationRejectionListener, - AdHocChatRoomMessageListener, - AdHocChatRoomInvitationListener, - AdHocChatRoomInvitationRejectionListener, - LocalUserChatRoomPresenceListener, - LocalUserAdHocChatRoomPresenceListener, - ServiceListener, ChatRoomLocalUserRoleListener -{ - /** - * The object used for logging. - */ - private static final Logger logger - = Logger.getLogger(ConferenceChatManager.class); - - /** - * Maps each history window to a ChatRoomWrapper. - */ - private final Hashtable chatRoomHistory = - new Hashtable(); - - /** - * The list of ad-hoc chat rooms. - */ - private final AdHocChatRoomList adHocChatRoomList = new AdHocChatRoomList(); - - /** - * A list of all AdHocChatRoomListChangeListener-s. - */ - private final Vector - adHoclistChangeListeners = new Vector(); - - /** - * Creates an instance of ConferenceChatManager. - */ - public ConferenceChatManager() - { - // Loads the chat rooms list in a separate thread. - new Thread() - { - @Override - public void run() - { - adHocChatRoomList.loadList(); - } - }.start(); - - GuiActivator.bundleContext.addServiceListener(this); - - } - - /** - * Returns all chat room providers currently contained in the ad-hoc chat - * room list. - * - * @return all chat room providers currently contained in the ad-hoc chat - * room list. - */ - public AdHocChatRoomList getAdHocChatRoomList() - { - return adHocChatRoomList; - } - - /** - * Handles ChatRoomInvitationReceivedEvent-s. - */ - public void invitationReceived(ChatRoomInvitationReceivedEvent evt) - { - InvitationReceivedDialog dialog - = new InvitationReceivedDialog( - this, - evt.getSourceOperationSet(), - evt.getInvitation()); - - dialog.setVisible(true); - } - - public void invitationRejected(ChatRoomInvitationRejectedEvent evt) {} - - /** - * Implements the ChatRoomMessageListener.messageDelivered method. - *
    - * Shows the message in the conversation area and clears the write message - * area. - * @param evt the ChatRoomMessageDeliveredEvent that notified us - * that the message was delivered to its destination - */ - public void messageDelivered(ChatRoomMessageDeliveredEvent evt) - { - ChatRoom sourceChatRoom = (ChatRoom) evt.getSource(); - - if (logger.isTraceEnabled()) - logger.trace( - "MESSAGE DELIVERED to chat room: " + sourceChatRoom.getName()); - - ChatPanel chatPanel = GuiActivator.getUIService().getChatWindowManager() - .getMultiChat(sourceChatRoom, false); - - if(chatPanel != null) - { - String messageType; - - switch (evt.getEventType()) - { - case ChatRoomMessageDeliveredEvent.CONVERSATION_MESSAGE_DELIVERED: - messageType = Chat.OUTGOING_MESSAGE; - break; - case ChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED: - messageType = Chat.ACTION_MESSAGE; - break; - default: - messageType = null; - break; - } - - Message msg = evt.getMessage(); - - chatPanel.addMessage( - sourceChatRoom.getUserNickname(), - null, - evt.getTimestamp(), - messageType, - msg.getContent(), - msg.getContentType(), - msg.getMessageUID(), - null); - } - } - - /** - * Implements the ChatRoomMessageListener.messageReceived method. - *
    - * Obtains the corresponding ChatPanel and process the message - * there. - * @param evt the ChatRoomMessageReceivedEvent that notified us - * that a message has been received - */ - public void messageReceived(ChatRoomMessageReceivedEvent evt) - { - ChatRoom sourceChatRoom = evt.getSourceChatRoom(); - ChatRoomMember sourceMember = evt.getSourceChatRoomMember(); - - String messageType = null; - - switch (evt.getEventType()) - { - case ChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED: - messageType = Chat.INCOMING_MESSAGE; - break; - case ChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED: - messageType = Chat.SYSTEM_MESSAGE; - break; - case ChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED: - messageType = Chat.ACTION_MESSAGE; - break; - } - - if (logger.isTraceEnabled()) - logger.trace("MESSAGE RECEIVED from contact: " - + sourceMember.getContactAddress()); - - Message message = evt.getMessage(); - - ChatPanel chatPanel = null; - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - - boolean createWindow = false; - String autoOpenConfig - = MUCService.getChatRoomAutoOpenOption( - sourceChatRoom.getParentProvider(), - sourceChatRoom.getIdentifier()); - if(autoOpenConfig == null) - autoOpenConfig = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR; - - if(autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY) - || (autoOpenConfig.equals(MUCService.OPEN_ON_MESSAGE) - && !evt.isHistoryMessage()) - || evt.isImportantMessage()) - createWindow = true; - - if(sourceChatRoom.isSystem()) - { - ChatRoomProviderWrapper serverWrapper - = GuiActivator.getMUCService().findServerWrapperFromProvider( - sourceChatRoom.getParentProvider()); - - chatPanel = chatWindowManager.getMultiChat( - serverWrapper.getSystemRoomWrapper(), createWindow); - } - else - { - chatPanel = chatWindowManager.getMultiChat( - sourceChatRoom, createWindow, message.getMessageUID()); - } - - if(chatPanel == null) - return; - - String messageContent = message.getContent(); - - if (evt.isHistoryMessage()) - { - Date timeStamp = chatPanel.getChatConversationPanel() - .getLastIncomingMsgTimestamp(); - Collection c = - chatPanel.getChatSession().getHistoryBeforeDate( - new Date( - timeStamp.equals(new Date(0)) - ? System.currentTimeMillis() - 10000 - : timeStamp.getTime() - ), 20); - if (c.size() > 0) - { - boolean isPresent = false; - for (Object o : c) - { - if (o instanceof ChatRoomMessageDeliveredEvent) - { - ChatRoomMessageDeliveredEvent ev = - (ChatRoomMessageDeliveredEvent) o; - if (evt.getTimestamp() != null - && evt.getTimestamp().equals(ev.getTimestamp())) - { - isPresent = true; - break; - } - } - else if(o instanceof ChatRoomMessageReceivedEvent) - { - ChatRoomMessageReceivedEvent ev = - (ChatRoomMessageReceivedEvent) o; - if (evt.getTimestamp() != null - && evt.getTimestamp().equals(ev.getTimestamp())) - { - isPresent = true; - break; - } - } - - Message m2 = evt.getMessage(); - - if(m2 != null - && m2.getContent().equals(messageContent)) - { - isPresent = true; - break; - } - } - - if (isPresent) - return; - } - } - - chatPanel.addMessage( - sourceMember.getName(), - null, - evt.getTimestamp(), - messageType, - messageContent, - message.getContentType(), - message.getMessageUID(), - null); - - if(createWindow) - chatWindowManager.openChat(chatPanel, false); - } - - /** - * Implements the ChatRoomMessageListener.messageDeliveryFailed - * method. - *
    - * In the conversation area shows an error message, explaining the problem. - * @param evt the ChatRoomMessageDeliveryFailedEvent that notified - * us of a delivery failure - */ - public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt) - { - ChatRoom sourceChatRoom = evt.getSourceChatRoom(); - - String errorMsg = null; - - /* - * FIXME ChatRoomMessageDeliveryFailedEvent#getSource() is not a Message - * instance at the time of this writing and the attempt "(Message) - * evt.getSource()" seems to be to get the message which failed to be - * delivered. I'm not sure it's - * ChatRoomMessageDeliveryFailedEvent#getMessage() but since it's the - * only message I can get out of ChatRoomMessageDeliveryFailedEvent, I'm - * using it. - */ - Message sourceMessage = evt.getMessage(); - - ChatRoomMember destMember = evt.getDestinationChatRoomMember(); - - if (evt.getErrorCode() - == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_NOT_SUPPORTED", - new String[]{destMember.getName()}); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.NETWORK_FAILURE) - { - errorMsg = GuiActivator.getResources() - .getI18NString("service.gui.MSG_NOT_DELIVERED"); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_SEND_CONNECTION_PROBLEM"); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.INTERNAL_ERROR) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_INTERNAL_ERROR"); - } - else if (evt.getErrorCode() - == ChatRoomMessageDeliveryFailedEvent.FORBIDDEN) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN"); - } - else if (evt.getErrorCode() - == ChatRoomMessageDeliveryFailedEvent.UNSUPPORTED_OPERATION) - { - errorMsg = - GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION"); - } - else - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_UNKNOWN_ERROR"); - } - - String reason = evt.getReason(); - if (reason != null) - errorMsg += " " + GuiActivator.getResources().getI18NString( - "service.gui.ERROR_WAS", - new String[]{reason}); - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager.getMultiChat(sourceChatRoom, true); - - chatPanel.addMessage( - destMember != null ? destMember.getName() - : sourceChatRoom.getName(), - new Date(), - Chat.OUTGOING_MESSAGE, - sourceMessage.getContent(), - sourceMessage.getContentType()); - - chatPanel.addErrorMessage( - destMember != null ? destMember.getName() - : sourceChatRoom.getName(), - errorMsg); - - chatWindowManager.openChat(chatPanel, false); - } - - /** - * Implements the - * LocalUserAdHocChatRoomPresenceListener.localUserPresenceChanged - * method - * - * @param evt the LocalUserAdHocChatRoomPresenceChangeEvent that - * notified us of a presence change - */ - public void localUserAdHocPresenceChanged( - LocalUserAdHocChatRoomPresenceChangeEvent evt) - { - AdHocChatRoom sourceAdHocChatRoom = evt.getAdHocChatRoom(); - AdHocChatRoomWrapper adHocChatRoomWrapper - = adHocChatRoomList - .findChatRoomWrapperFromAdHocChatRoom(sourceAdHocChatRoom); - - String eventType = evt.getEventType(); - - if (LocalUserAdHocChatRoomPresenceChangeEvent - .LOCAL_USER_JOINED.equals(eventType)) - { - if(adHocChatRoomWrapper != null) - { - this.fireAdHocChatRoomListChangedEvent( - adHocChatRoomWrapper, - AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED); - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager - .getMultiChat(adHocChatRoomWrapper, true); - - // Check if we have already opened a chat window for this chat - // wrapper and load the real chat room corresponding to the - // wrapper. - if(chatPanel.isShown()) - ((AdHocConferenceChatSession) chatPanel.getChatSession()) - .loadChatRoom(sourceAdHocChatRoom); - else - chatWindowManager.openChat(chatPanel, true); - } - - sourceAdHocChatRoom.addMessageListener(this); - } - else if (evt.getEventType().equals( - LocalUserAdHocChatRoomPresenceChangeEvent.LOCAL_USER_JOIN_FAILED)) - { - GuiActivator.getAlertUIService().showAlertPopup( - GuiActivator.getResources().getI18NString("service.gui.ERROR"), - GuiActivator.getResources().getI18NString( - "service.gui.FAILED_TO_JOIN_CHAT_ROOM", - new String[]{sourceAdHocChatRoom.getName()}) - + evt.getReason()); - } - else if (LocalUserAdHocChatRoomPresenceChangeEvent - .LOCAL_USER_LEFT.equals(eventType) - || LocalUserAdHocChatRoomPresenceChangeEvent - .LOCAL_USER_DROPPED.equals(eventType)) - { - this.closeAdHocChatRoom(adHocChatRoomWrapper); - - // Need to refresh the chat room's list in order to change - // the state of the chat room to offline. - fireAdHocChatRoomListChangedEvent( - adHocChatRoomWrapper, - AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED); - - sourceAdHocChatRoom.removeMessageListener(this); - } - } - - /** - * Implements the - * LocalUserChatRoomPresenceListener.localUserPresenceChanged - * method. - * @param evt the LocalUserChatRoomPresenceChangeEvent that - * notified us - */ - public void localUserPresenceChanged( - final LocalUserChatRoomPresenceChangeEvent evt) - { - if(!SwingUtilities.isEventDispatchThread()) - { - SwingUtilities.invokeLater(new Runnable() - { - @Override - public void run() - { - localUserPresenceChanged(evt); - } - }); - return; - } - - ChatRoom sourceChatRoom = evt.getChatRoom(); - ChatRoomWrapper chatRoomWrapper - = GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom( - sourceChatRoom); - - String eventType = evt.getEventType(); - - if (LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_JOINED.equals(eventType)) - { - if(chatRoomWrapper != null) - { - GuiActivator.getMUCService().fireChatRoomListChangedEvent( - chatRoomWrapper, - ChatRoomListChangeEvent.CHAT_ROOM_CHANGED); - - boolean createWindow = false; - - String autoOpenConfig - = MUCService.getChatRoomAutoOpenOption( - sourceChatRoom.getParentProvider(), - sourceChatRoom.getIdentifier()); - - if(autoOpenConfig != null - && autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY)) - createWindow = true; - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager.getMultiChat( - chatRoomWrapper, createWindow); - - if(chatPanel != null) - { - chatPanel.setChatIcon( - chatPanel.getChatSession().getChatStatusIcon()); - - // Check if we have already opened a chat window for this chat - // wrapper and load the real chat room corresponding to the - // wrapper. - if(chatPanel.isShown()) - { - ((ConferenceChatSession) chatPanel.getChatSession()) - .loadChatRoom(sourceChatRoom); - } - else - { - chatWindowManager.openChat(chatPanel, true); - } - } - } - - if (sourceChatRoom.isSystem()) - { - ChatRoomProviderWrapper serverWrapper - = GuiActivator.getMUCService() - .findServerWrapperFromProvider( - sourceChatRoom.getParentProvider()); - - serverWrapper.setSystemRoom(sourceChatRoom); - } - - sourceChatRoom.addMessageListener(this); - sourceChatRoom.addLocalUserRoleListener(this); - } - else if (LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_JOIN_FAILED.equals(eventType)) - { - GuiActivator.getAlertUIService().showAlertPopup( - GuiActivator.getResources().getI18NString("service.gui.ERROR"), - GuiActivator.getResources().getI18NString( - "service.gui.FAILED_TO_JOIN_CHAT_ROOM", - new String[]{sourceChatRoom.getName()}) - + evt.getReason()); - } - else if (LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_LEFT.equals(eventType) - || LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_KICKED.equals(eventType) - || LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_DROPPED.equals(eventType)) - { - if(chatRoomWrapper != null) - { - if(StringUtils.isNullOrEmpty(evt.getReason())) - { - GuiActivator.getUIService() - .closeChatRoomWindow(chatRoomWrapper); - } - else - { - // send some system messages informing for the - // reason of leaving - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - - ChatPanel chatPanel = chatWindowManager.getMultiChat( - sourceChatRoom, false); - - if(chatPanel != null) - { - chatPanel.addMessage( - sourceChatRoom.getName(), - null, - new Date(), - Chat.SYSTEM_MESSAGE, - evt.getReason(), - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, - null, - null); - - // print and the alternate address - if(!StringUtils.isNullOrEmpty( - evt.getAlternateAddress())) - { - chatPanel.addMessage( - sourceChatRoom.getName(), - null, - new Date(), - Chat.SYSTEM_MESSAGE, - GuiActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_ALTERNATE_ADDRESS", - new String[]{evt.getAlternateAddress()}), - OperationSetBasicInstantMessaging - .DEFAULT_MIME_TYPE, - null, - null); - } - } - } - - // Need to refresh the chat room's list in order to change - // the state of the chat room to offline. - - GuiActivator.getMUCService().fireChatRoomListChangedEvent( - chatRoomWrapper, - ChatRoomListChangeEvent.CHAT_ROOM_CHANGED); - } - - sourceChatRoom.removeMessageListener(this); - sourceChatRoom.removelocalUserRoleListener(this); - } - } - - - /** - * Called to accept an incoming invitation. Adds the invitation chat room - * to the list of chat rooms and joins it. - * - * @param invitation the invitation to accept - * @param multiUserChatOpSet the operation set for chat conferencing - * @throws OperationFailedException if the accept fails - */ - public void acceptInvitation( - AdHocChatRoomInvitation invitation, - OperationSetAdHocMultiUserChat multiUserChatOpSet) - throws OperationFailedException - { - AdHocChatRoom chatRoom = invitation.getTargetAdHocChatRoom(); - - chatRoom.join(); - } - - /** - * Rejects the given invitation with the specified reason. - * - * @param multiUserChatAdHocOpSet the operation set to use for rejecting the - * invitation - * @param invitation the invitation to reject - * @param reason the reason for the rejection - */ - public void rejectInvitation( - OperationSetAdHocMultiUserChat multiUserChatAdHocOpSet, - AdHocChatRoomInvitation invitation, - String reason) - { - multiUserChatAdHocOpSet.rejectInvitation(invitation, reason); - } - - /** - * Creates an ad-hoc chat room, by specifying the ad-hoc chat room name, the - * parent protocol provider and eventually, the contacts invited to - * participate in this ad-hoc chat room. - * - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason the reason for this invitation - * @return the AdHocChatRoomWrapper corresponding to the created - * ad hoc chat room - */ - public AdHocChatRoomWrapper createAdHocChatRoom( - ProtocolProviderService protocolProvider, - Collection contacts, - String reason) - { - AdHocChatRoomWrapper chatRoomWrapper = null; - - OperationSetAdHocMultiUserChat groupChatOpSet - = protocolProvider - .getOperationSet(OperationSetAdHocMultiUserChat.class); - - // If there's no group chat operation set we have nothing to do here. - if (groupChatOpSet == null) - return null; - - AdHocChatRoom chatRoom = null; - - try - { - java.util.List members = new LinkedList(); - - for(String address : contacts) - members.add(address); - - chatRoom = groupChatOpSet.createAdHocChatRoom( - "chatroom-" + new Date().getTime(), members, reason); - } - catch (OperationFailedException ex) - { - new ErrorDialog( - GuiActivator.getUIService().getMainFrame(), - GuiActivator.getResources().getI18NString("service.gui.ERROR"), - GuiActivator.getResources().getI18NString( - "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{protocolProvider.getProtocolDisplayName()}), - ex) - .showDialog(); - } - catch (OperationNotSupportedException ex) - { - new ErrorDialog( - GuiActivator.getUIService().getMainFrame(), - GuiActivator.getResources().getI18NString("service.gui.ERROR"), - GuiActivator.getResources().getI18NString( - "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{protocolProvider.getProtocolDisplayName()}), - ex) - .showDialog(); - } - - if(chatRoom != null) - { - AdHocChatRoomProviderWrapper parentProvider - = adHocChatRoomList.findServerWrapperFromProvider( - protocolProvider); - - chatRoomWrapper = new AdHocChatRoomWrapper( - parentProvider, chatRoom); - parentProvider.addAdHocChatRoom(chatRoomWrapper); - adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper); - - fireAdHocChatRoomListChangedEvent( - chatRoomWrapper, - AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED); - } - - return chatRoomWrapper; - } - - /** - * Joins the given ad-hoc chat room - * - * @param chatRoomWrapper - */ - public void joinChatRoom(AdHocChatRoomWrapper chatRoomWrapper) - { - AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom(); - - if(chatRoom == null) - { - new ErrorDialog( - GuiActivator.getUIService().getMainFrame(), - GuiActivator.getResources().getI18NString("service.gui.WARNING"), - GuiActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getAdHocChatRoomName()})) - .showDialog(); - - return; - } - - new JoinAdHocChatRoomTask(chatRoomWrapper).execute(); - } - - /** - * Removes the given chat room from the UI. - * - * @param chatRoomWrapper the chat room to remove. - */ - public void removeChatRoom(ChatRoomWrapper chatRoomWrapper) - { - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if (chatRoom != null) - leaveChatRoom(chatRoomWrapper); - - GuiActivator.getUIService().closeChatRoomWindow(chatRoomWrapper); - - GuiActivator.getMUCService().removeChatRoom(chatRoomWrapper); - - } - - /** - * Joins the given chat room and manages all the exceptions that could - * occur during the join process. - * - * @param chatRoom the chat room to join - */ - public void joinChatRoom(AdHocChatRoom chatRoom) - { - AdHocChatRoomWrapper chatRoomWrapper - = adHocChatRoomList.findChatRoomWrapperFromAdHocChatRoom(chatRoom); - - if(chatRoomWrapper == null) - { - AdHocChatRoomProviderWrapper parentProvider - = adHocChatRoomList.findServerWrapperFromProvider( - chatRoom.getParentProvider()); - - chatRoomWrapper = - new AdHocChatRoomWrapper(parentProvider, chatRoom); - - adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper); - - fireAdHocChatRoomListChangedEvent( - chatRoomWrapper, - AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED); - } - - this.joinChatRoom(chatRoomWrapper); - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - - chatWindowManager - .openChat( - chatWindowManager.getMultiChat(chatRoomWrapper, true), - true); - } - - /** - * Leaves the given ChatRoom. - * - * @param chatRoomWrapper the ChatRoom to leave. - */ - public void leaveChatRoom(ChatRoomWrapper chatRoomWrapper) - { - ChatRoomWrapper leavedRoomWrapped - = GuiActivator.getMUCService().leaveChatRoom(chatRoomWrapper); - if(leavedRoomWrapped != null) - GuiActivator.getUIService().closeChatRoomWindow(leavedRoomWrapped); - } - - /** - * Leaves the given ChatRoom. - * - * @param chatRoomWrapper the ChatRoom to leave. - */ - public void leaveChatRoom(AdHocChatRoomWrapper chatRoomWrapper) - { - AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom(); - - if (chatRoom != null) - { - chatRoom.leave(); - } - else - { - new ErrorDialog( - GuiActivator.getUIService().getMainFrame(), - GuiActivator.getResources().getI18NString("service.gui.WARNING"), - GuiActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED")) - .showDialog(); - } - } - - /** - * Checks if there's an open history window for the given chat room. - * - * @param chatRoomWrapper the chat room wrapper to check for - * @return TRUE if there's an opened history window for the given chat room, - * FALSE otherwise. - */ - public boolean containsHistoryWindowForChatRoom( - ChatRoomWrapper chatRoomWrapper) - { - return chatRoomHistory.containsKey(chatRoomWrapper); - } - - /** - * Returns the history window for the given chat room. - * - * @param chatRoomWrapper the chat room wrapper to search for - * @return the history window for the given chat room - */ - public HistoryWindow getHistoryWindowForChatRoom( - ChatRoomWrapper chatRoomWrapper) - { - return chatRoomHistory.get(chatRoomWrapper); - } - - /** - * Adds a history window for a given chat room in the table of opened - * history windows. - * - * @param chatRoomWrapper the chat room wrapper to add - * @param historyWindow the history window to add - */ - public void addHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper, - HistoryWindow historyWindow) - { - chatRoomHistory.put(chatRoomWrapper, historyWindow); - } - - /** - * Removes the history window for the given chat room. - * - * @param chatRoomWrapper the chat room wrapper to remove the history window - */ - public void removeHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper) - { - chatRoomHistory.remove(chatRoomWrapper); - } - - /** - * Adds the given AdHocChatRoomListChangeListener that will listen - * for all changes of the chat room list data model. - * - * @param l the listener to add. - */ - public void addAdHocChatRoomListChangeListener( - AdHocChatRoomListChangeListener l) - { - synchronized (adHoclistChangeListeners) - { - adHoclistChangeListeners.add(l); - } - } - - /** - * Removes the given AdHocChatRoomListChangeListener. - * - * @param l the listener to remove. - */ - public void removeAdHocChatRoomListChangeListener( - AdHocChatRoomListChangeListener l) - { - synchronized (adHoclistChangeListeners) - { - adHoclistChangeListeners.remove(l); - } - } - - /** - * Notifies all interested listeners that a change in the chat room list - * model has occurred. - * @param adHocChatRoomWrapper the chat room wrapper that identifies the - * chat room - * @param eventID the identifier of the event - */ - private void fireAdHocChatRoomListChangedEvent( - AdHocChatRoomWrapper adHocChatRoomWrapper, - int eventID) - { - AdHocChatRoomListChangeEvent evt - = new AdHocChatRoomListChangeEvent(adHocChatRoomWrapper, eventID); - - for (AdHocChatRoomListChangeListener l : adHoclistChangeListeners) - { - l.contentChanged(evt); - } - } - - - /** - * Closes the chat corresponding to the given ad-hoc chat room wrapper, if - * such exists. - * - * @param chatRoomWrapper the ad-hoc chat room wrapper for which we search a - * chat to close. - */ - private void closeAdHocChatRoom(AdHocChatRoomWrapper chatRoomWrapper) - { - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager.getMultiChat(chatRoomWrapper, false); - - if (chatPanel != null) - chatWindowManager.closeChat(chatPanel); - } - - /** - * Handles ServiceEvents triggered by adding or removing a - * ProtocolProviderService. Updates the list of available chat rooms and - * chat room servers. - * - * @param event The event to handle. - */ - public void serviceChanged(ServiceEvent event) - { - // if the event is caused by a bundle being stopped, we don't want to - // know - if (event.getServiceReference().getBundle().getState() - == Bundle.STOPPING) - return; - - Object service = GuiActivator.bundleContext.getService(event - .getServiceReference()); - - // we don't care if the source service is not a protocol provider - if (!(service instanceof ProtocolProviderService)) - return; - - ProtocolProviderService protocolProvider - = (ProtocolProviderService) service; - - - Object multiUserChatAdHocOpSet - = protocolProvider - .getOperationSet(OperationSetAdHocMultiUserChat.class); - - if (multiUserChatAdHocOpSet != null) - { - if (event.getType() == ServiceEvent.REGISTERED) - { - adHocChatRoomList.addChatProvider(protocolProvider); - } - else if (event.getType() == ServiceEvent.UNREGISTERING) - { - adHocChatRoomList.removeChatProvider(protocolProvider); - } - } - } - - /** - * Joins an ad-hoc chat room in an asynchronous way. - */ - private static class JoinAdHocChatRoomTask - extends SwingWorker - { - private static final String SUCCESS = "Success"; - - private static final String AUTHENTICATION_FAILED - = "AuthenticationFailed"; - - private static final String REGISTRATION_REQUIRED - = "RegistrationRequired"; - - private static final String PROVIDER_NOT_REGISTERED - = "ProviderNotRegistered"; - - private static final String SUBSCRIPTION_ALREADY_EXISTS - = "SubscriptionAlreadyExists"; - - private static final String UNKNOWN_ERROR - = "UnknownError"; - - private final AdHocChatRoomWrapper adHocChatRoomWrapper; - - JoinAdHocChatRoomTask(AdHocChatRoomWrapper chatRoomWrapper) - { - this.adHocChatRoomWrapper = chatRoomWrapper; - } - - /** - * @override {@link SwingWorker}{@link #doInBackground()} to perform - * all asynchronous tasks. - * @return SUCCESS if success, otherwise the error code - */ - @Override - public String doInBackground() - { - AdHocChatRoom chatRoom = adHocChatRoomWrapper.getAdHocChatRoom(); - - try - { - chatRoom.join(); - - return SUCCESS; - } - catch (OperationFailedException e) - { - if (logger.isTraceEnabled()) - logger.trace("Failed to join ad-hoc chat room: " - + chatRoom.getName(), e); - - switch (e.getErrorCode()) - { - case OperationFailedException.AUTHENTICATION_FAILED: - return AUTHENTICATION_FAILED; - case OperationFailedException.REGISTRATION_REQUIRED: - return REGISTRATION_REQUIRED; - case OperationFailedException.PROVIDER_NOT_REGISTERED: - return PROVIDER_NOT_REGISTERED; - case OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS: - return SUBSCRIPTION_ALREADY_EXISTS; - default: - return UNKNOWN_ERROR; - } - } - } - - /** - * @override {@link SwingWorker}{@link #done()} to perform UI changes - * after the ad-hoc chat room join task has finished. - */ - @Override - protected void done() - { - String returnCode = null; - try - { - returnCode = get(); - } - catch (InterruptedException ignore) - {} - catch (ExecutionException ignore) - {} - - ConfigurationUtils.updateChatRoomStatus( - adHocChatRoomWrapper.getParentProvider().getProtocolProvider(), - adHocChatRoomWrapper.getAdHocChatRoomID(), - GlobalStatusEnum.ONLINE_STATUS); - - String errorMessage = null; - if(PROVIDER_NOT_REGISTERED.equals(returnCode)) - { - errorMessage - = GuiActivator.getResources() - .getI18NString("service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{ - adHocChatRoomWrapper.getAdHocChatRoomName()}); - } - else if(SUBSCRIPTION_ALREADY_EXISTS.equals(returnCode)) - { - errorMessage - = GuiActivator.getResources() - .getI18NString("service.gui.CHAT_ROOM_ALREADY_JOINED", - new String[]{ - adHocChatRoomWrapper.getAdHocChatRoomName()}); - } - else - { - errorMessage - = GuiActivator.getResources() - .getI18NString("service.gui.FAILED_TO_JOIN_CHAT_ROOM", - new String[]{ - adHocChatRoomWrapper.getAdHocChatRoomName()}); - } - - if (!SUCCESS.equals(returnCode) - && !AUTHENTICATION_FAILED.equals(returnCode)) - { - GuiActivator.getAlertUIService().showAlertPopup( - GuiActivator.getResources().getI18NString( - "service.gui.ERROR"), errorMessage); - } - } - } - - - /** - * Indicates that an invitation has been received and opens the invitation - * dialog to notify the user. - * @param evt the AdHocChatRoomInvitationReceivedEvent that - * notified us - */ - public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt) - { - if (logger.isInfoEnabled()) - logger.info("Invitation received: "+evt.toString()); - OperationSetAdHocMultiUserChat multiUserChatOpSet - = evt.getSourceOperationSet(); - - InvitationReceivedDialog dialog = new InvitationReceivedDialog( - this, multiUserChatOpSet, evt.getInvitation()); - - dialog.setVisible(true); - } - - /** - * Implements the AdHocChatRoomMessageListener.messageDelivered - * method. - *
    - * Shows the message in the conversation area and clears the write message - * area. - * @param evt the AdHocChatRoomMessageDeliveredEvent that notified - * us - */ - public void messageDelivered(AdHocChatRoomMessageDeliveredEvent evt) - { - AdHocChatRoom sourceChatRoom = (AdHocChatRoom) evt.getSource(); - - if (logger.isInfoEnabled()) - logger.info("MESSAGE DELIVERED to ad-hoc chat room: " - + sourceChatRoom.getName()); - - ChatPanel chatPanel - = GuiActivator - .getUIService() - .getChatWindowManager() - .getMultiChat(sourceChatRoom, false); - - if(chatPanel != null) - { - String messageType; - switch (evt.getEventType()) - { - case AdHocChatRoomMessageDeliveredEvent - .CONVERSATION_MESSAGE_DELIVERED: - messageType = Chat.OUTGOING_MESSAGE; - break; - case AdHocChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED: - messageType = Chat.ACTION_MESSAGE; - break; - default: - messageType = null; - } - - Message msg = evt.getMessage(); - - chatPanel - .addMessage( - sourceChatRoom - .getParentProvider().getAccountID().getUserID(), - null, - evt.getTimestamp(), - messageType, - msg.getContent(), - msg.getContentType(), - msg.getMessageUID(), - null); - } - else - { - logger.error("chat panel is null, message NOT DELIVERED !"); - } - } - - /** - * Implements AdHocChatRoomMessageListener.messageDeliveryFailed - * method. - *
    - * In the conversation area shows an error message, explaining the problem. - * @param evt the AdHocChatRoomMessageDeliveryFailedEvent that - * notified us - */ - public void messageDeliveryFailed( - AdHocChatRoomMessageDeliveryFailedEvent evt) - { - AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom(); - Message sourceMessage = evt.getMessage(); - Contact destParticipant = evt.getDestinationParticipant(); - - String errorMsg = null; - if (evt.getErrorCode() - == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_NOT_SUPPORTED", - new String[]{destParticipant.getDisplayName()}); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.NETWORK_FAILURE) - { - errorMsg = GuiActivator.getResources() - .getI18NString("service.gui.MSG_NOT_DELIVERED"); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_SEND_CONNECTION_PROBLEM"); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.INTERNAL_ERROR) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_INTERNAL_ERROR"); - } - else if (evt.getErrorCode() - == MessageDeliveryFailedEvent.UNSUPPORTED_OPERATION) - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION"); - } - else - { - errorMsg = GuiActivator.getResources().getI18NString( - "service.gui.MSG_DELIVERY_UNKNOWN_ERROR"); - } - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager.getMultiChat(sourceChatRoom, true); - - chatPanel.addMessage( - destParticipant.getDisplayName(), - new Date(), - Chat.OUTGOING_MESSAGE, - sourceMessage.getContent(), - sourceMessage.getContentType()); - - chatPanel.addErrorMessage( - destParticipant.getDisplayName(), - errorMsg); - - chatWindowManager.openChat(chatPanel, false); - } - - /** - * Implements the AdHocChatRoomMessageListener.messageReceived - * method. - *
    - * Obtains the corresponding ChatPanel and process the message - * there. - * @param evt the AdHocChatRoomMessageReceivedEvent that notified - * us - */ - public void messageReceived(AdHocChatRoomMessageReceivedEvent evt) - { - AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom(); - Contact sourceParticipant = evt.getSourceChatRoomParticipant(); - - String messageType = null; - - switch (evt.getEventType()) - { - case AdHocChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED: - messageType = Chat.INCOMING_MESSAGE; - break; - case AdHocChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED: - messageType = Chat.SYSTEM_MESSAGE; - break; - case AdHocChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED: - messageType = Chat.ACTION_MESSAGE; - break; - } - - if (logger.isInfoEnabled()) - logger.info("MESSAGE RECEIVED from contact: " - + sourceParticipant.getAddress()); - - Message message = evt.getMessage(); - - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager - .getMultiChat(sourceChatRoom, true, message.getMessageUID()); - - String messageContent = message.getContent(); - - chatPanel.addMessage( - sourceParticipant.getDisplayName(), - null, - evt.getTimestamp(), - messageType, - messageContent, - message.getContentType(), - message.getMessageUID(), - null); - - chatWindowManager.openChat(chatPanel, false); - } - - public void invitationRejected(AdHocChatRoomInvitationRejectedEvent evt) {} - - @Override - public void localUserRoleChanged(ChatRoomLocalUserRoleChangeEvent evt) - { - if(evt.isInitial()) - return; - ChatRoom sourceChatRoom = evt.getSourceChatRoom(); - ChatRoomWrapper chatRoomWrapper - = GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom( - sourceChatRoom); - ChatWindowManager chatWindowManager - = GuiActivator.getUIService().getChatWindowManager(); - ChatPanel chatPanel - = chatWindowManager.getMultiChat(chatRoomWrapper, true); - chatWindowManager.openChat(chatPanel, true); - } - -} +package net.java.sip.communicator.impl.gui.main.chat.conference; + +import java.util.*; +import java.util.concurrent.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.chat.*; +import net.java.sip.communicator.impl.gui.main.chat.history.*; +import net.java.sip.communicator.impl.gui.main.chatroomslist.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.globalstatus.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.Logger; + +import org.jdesktop.swingworker.SwingWorker; +import org.jitsi.util.*; +import org.osgi.framework.*; + +/** + * The ConferenceChatManager is the one that manages both chat room and + * ad-hoc chat rooms invitations. + * + * @author Yana Stamcheva + * @author Lubomir Marinov + * @author Valentin Martinet + * @author Hristo Terezov + */ +public class ConferenceChatManager + implements ChatRoomMessageListener, + ChatRoomInvitationListener, + ChatRoomInvitationRejectionListener, + AdHocChatRoomMessageListener, + AdHocChatRoomInvitationListener, + AdHocChatRoomInvitationRejectionListener, + LocalUserChatRoomPresenceListener, + LocalUserAdHocChatRoomPresenceListener, + ServiceListener, ChatRoomLocalUserRoleListener +{ + /** + * The object used for logging. + */ + private static final Logger logger + = Logger.getLogger(ConferenceChatManager.class); + + /** + * Maps each history window to a ChatRoomWrapper. + */ + private final Hashtable chatRoomHistory = + new Hashtable(); + + /** + * The list of ad-hoc chat rooms. + */ + private final AdHocChatRoomList adHocChatRoomList = new AdHocChatRoomList(); + + /** + * A list of all AdHocChatRoomListChangeListener-s. + */ + private final Vector + adHoclistChangeListeners = new Vector(); + + /** + * Creates an instance of ConferenceChatManager. + */ + public ConferenceChatManager() + { + // Loads the chat rooms list in a separate thread. + new Thread() + { + @Override + public void run() + { + adHocChatRoomList.loadList(); + } + }.start(); + + GuiActivator.bundleContext.addServiceListener(this); + + } + + /** + * Returns all chat room providers currently contained in the ad-hoc chat + * room list. + * + * @return all chat room providers currently contained in the ad-hoc chat + * room list. + */ + public AdHocChatRoomList getAdHocChatRoomList() + { + return adHocChatRoomList; + } + + /** + * Handles ChatRoomInvitationReceivedEvent-s. + */ + public void invitationReceived(ChatRoomInvitationReceivedEvent evt) + { + InvitationReceivedDialog dialog + = new InvitationReceivedDialog( + this, + evt.getSourceOperationSet(), + evt.getInvitation()); + + dialog.setVisible(true); + } + + public void invitationRejected(ChatRoomInvitationRejectedEvent evt) {} + + /** + * Implements the ChatRoomMessageListener.messageDelivered method. + *
    + * Shows the message in the conversation area and clears the write message + * area. + * @param evt the ChatRoomMessageDeliveredEvent that notified us + * that the message was delivered to its destination + */ + public void messageDelivered(ChatRoomMessageDeliveredEvent evt) + { + ChatRoom sourceChatRoom = (ChatRoom) evt.getSource(); + + if (logger.isTraceEnabled()) + logger.trace( + "MESSAGE DELIVERED to chat room: " + sourceChatRoom.getName()); + + ChatPanel chatPanel = GuiActivator.getUIService().getChatWindowManager() + .getMultiChat(sourceChatRoom, false); + + if(chatPanel != null) + { + String messageType; + + switch (evt.getEventType()) + { + case ChatRoomMessageDeliveredEvent.CONVERSATION_MESSAGE_DELIVERED: + messageType = Chat.OUTGOING_MESSAGE; + break; + case ChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED: + messageType = Chat.ACTION_MESSAGE; + break; + default: + messageType = null; + break; + } + + Message msg = evt.getMessage(); + + chatPanel.addMessage( + sourceChatRoom.getUserNickname(), + null, + evt.getTimestamp(), + messageType, + msg.getContent(), + msg.getContentType(), + msg.getMessageUID(), + null); + } + } + + /** + * Implements the ChatRoomMessageListener.messageReceived method. + *
    + * Obtains the corresponding ChatPanel and process the message + * there. + * @param evt the ChatRoomMessageReceivedEvent that notified us + * that a message has been received + */ + public void messageReceived(ChatRoomMessageReceivedEvent evt) + { + ChatRoom sourceChatRoom = evt.getSourceChatRoom(); + ChatRoomMember sourceMember = evt.getSourceChatRoomMember(); + + String messageType = null; + + switch (evt.getEventType()) + { + case ChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED: + messageType = Chat.INCOMING_MESSAGE; + break; + case ChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED: + messageType = Chat.SYSTEM_MESSAGE; + break; + case ChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED: + messageType = Chat.ACTION_MESSAGE; + break; + } + + if (logger.isTraceEnabled()) + logger.trace("MESSAGE RECEIVED from contact: " + + sourceMember.getContactAddress()); + + Message message = evt.getMessage(); + + ChatPanel chatPanel = null; + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + + boolean createWindow = false; + String autoOpenConfig + = MUCService.getChatRoomAutoOpenOption( + sourceChatRoom.getParentProvider(), + sourceChatRoom.getIdentifier()); + if(autoOpenConfig == null) + autoOpenConfig = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR; + + if(autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY) + || (autoOpenConfig.equals(MUCService.OPEN_ON_MESSAGE) + && !evt.isHistoryMessage()) + || evt.isImportantMessage()) + createWindow = true; + + if(sourceChatRoom.isSystem()) + { + ChatRoomProviderWrapper serverWrapper + = GuiActivator.getMUCService().findServerWrapperFromProvider( + sourceChatRoom.getParentProvider()); + + chatPanel = chatWindowManager.getMultiChat( + serverWrapper.getSystemRoomWrapper(), createWindow); + } + else + { + chatPanel = chatWindowManager.getMultiChat( + sourceChatRoom, createWindow, message.getMessageUID()); + } + + if(chatPanel == null) + return; + + String messageContent = message.getContent(); + + if (evt.isHistoryMessage()) + { + Date timeStamp = chatPanel.getChatConversationPanel() + .getLastIncomingMsgTimestamp(); + Collection c = + chatPanel.getChatSession().getHistoryBeforeDate( + new Date( + timeStamp.equals(new Date(0)) + ? System.currentTimeMillis() - 10000 + : timeStamp.getTime() + ), 20); + if (c.size() > 0) + { + boolean isPresent = false; + for (Object o : c) + { + if (o instanceof ChatRoomMessageDeliveredEvent) + { + ChatRoomMessageDeliveredEvent ev = + (ChatRoomMessageDeliveredEvent) o; + if (evt.getTimestamp() != null + && evt.getTimestamp().equals(ev.getTimestamp())) + { + isPresent = true; + break; + } + } + else if(o instanceof ChatRoomMessageReceivedEvent) + { + ChatRoomMessageReceivedEvent ev = + (ChatRoomMessageReceivedEvent) o; + if (evt.getTimestamp() != null + && evt.getTimestamp().equals(ev.getTimestamp())) + { + isPresent = true; + break; + } + } + + Message m2 = evt.getMessage(); + + if(m2 != null + && m2.getContent().equals(messageContent)) + { + isPresent = true; + break; + } + } + + if (isPresent) + return; + } + } + + chatPanel.addMessage( + sourceMember.getName(), + null, + evt.getTimestamp(), + messageType, + messageContent, + message.getContentType(), + message.getMessageUID(), + null); + + if(createWindow) + chatWindowManager.openChat(chatPanel, false); + } + + /** + * Implements the ChatRoomMessageListener.messageDeliveryFailed + * method. + *
    + * In the conversation area shows an error message, explaining the problem. + * @param evt the ChatRoomMessageDeliveryFailedEvent that notified + * us of a delivery failure + */ + public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt) + { + ChatRoom sourceChatRoom = evt.getSourceChatRoom(); + + String errorMsg = null; + + /* + * FIXME ChatRoomMessageDeliveryFailedEvent#getSource() is not a Message + * instance at the time of this writing and the attempt "(Message) + * evt.getSource()" seems to be to get the message which failed to be + * delivered. I'm not sure it's + * ChatRoomMessageDeliveryFailedEvent#getMessage() but since it's the + * only message I can get out of ChatRoomMessageDeliveryFailedEvent, I'm + * using it. + */ + Message sourceMessage = evt.getMessage(); + + ChatRoomMember destMember = evt.getDestinationChatRoomMember(); + + if (evt.getErrorCode() + == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_NOT_SUPPORTED", + new String[]{destMember.getName()}); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.NETWORK_FAILURE) + { + errorMsg = GuiActivator.getResources() + .getI18NString("service.gui.MSG_NOT_DELIVERED"); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_SEND_CONNECTION_PROBLEM"); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.INTERNAL_ERROR) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_INTERNAL_ERROR"); + } + else if (evt.getErrorCode() + == ChatRoomMessageDeliveryFailedEvent.FORBIDDEN) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN"); + } + else if (evt.getErrorCode() + == ChatRoomMessageDeliveryFailedEvent.UNSUPPORTED_OPERATION) + { + errorMsg = + GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION"); + } + else + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_UNKNOWN_ERROR"); + } + + String reason = evt.getReason(); + if (reason != null) + errorMsg += " " + GuiActivator.getResources().getI18NString( + "service.gui.ERROR_WAS", + new String[]{reason}); + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager.getMultiChat(sourceChatRoom, true); + + chatPanel.addMessage( + destMember != null ? destMember.getName() + : sourceChatRoom.getName(), + new Date(), + Chat.OUTGOING_MESSAGE, + sourceMessage.getContent(), + sourceMessage.getContentType()); + + chatPanel.addErrorMessage( + destMember != null ? destMember.getName() + : sourceChatRoom.getName(), + errorMsg); + + chatWindowManager.openChat(chatPanel, false); + } + + /** + * Implements the + * LocalUserAdHocChatRoomPresenceListener.localUserPresenceChanged + * method + * + * @param evt the LocalUserAdHocChatRoomPresenceChangeEvent that + * notified us of a presence change + */ + public void localUserAdHocPresenceChanged( + LocalUserAdHocChatRoomPresenceChangeEvent evt) + { + AdHocChatRoom sourceAdHocChatRoom = evt.getAdHocChatRoom(); + AdHocChatRoomWrapper adHocChatRoomWrapper + = adHocChatRoomList + .findChatRoomWrapperFromAdHocChatRoom(sourceAdHocChatRoom); + + String eventType = evt.getEventType(); + + if (LocalUserAdHocChatRoomPresenceChangeEvent + .LOCAL_USER_JOINED.equals(eventType)) + { + if(adHocChatRoomWrapper != null) + { + this.fireAdHocChatRoomListChangedEvent( + adHocChatRoomWrapper, + AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED); + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager + .getMultiChat(adHocChatRoomWrapper, true); + + // Check if we have already opened a chat window for this chat + // wrapper and load the real chat room corresponding to the + // wrapper. + if(chatPanel.isShown()) + ((AdHocConferenceChatSession) chatPanel.getChatSession()) + .loadChatRoom(sourceAdHocChatRoom); + else + chatWindowManager.openChat(chatPanel, true); + } + + sourceAdHocChatRoom.addMessageListener(this); + } + else if (evt.getEventType().equals( + LocalUserAdHocChatRoomPresenceChangeEvent.LOCAL_USER_JOIN_FAILED)) + { + GuiActivator.getAlertUIService().showAlertPopup( + GuiActivator.getResources().getI18NString("service.gui.ERROR"), + GuiActivator.getResources().getI18NString( + "service.gui.FAILED_TO_JOIN_CHAT_ROOM", + new String[]{sourceAdHocChatRoom.getName()}) + + evt.getReason()); + } + else if (LocalUserAdHocChatRoomPresenceChangeEvent + .LOCAL_USER_LEFT.equals(eventType) + || LocalUserAdHocChatRoomPresenceChangeEvent + .LOCAL_USER_DROPPED.equals(eventType)) + { + this.closeAdHocChatRoom(adHocChatRoomWrapper); + + // Need to refresh the chat room's list in order to change + // the state of the chat room to offline. + fireAdHocChatRoomListChangedEvent( + adHocChatRoomWrapper, + AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_CHANGED); + + sourceAdHocChatRoom.removeMessageListener(this); + } + } + + /** + * Implements the + * LocalUserChatRoomPresenceListener.localUserPresenceChanged + * method. + * @param evt the LocalUserChatRoomPresenceChangeEvent that + * notified us + */ + public void localUserPresenceChanged( + final LocalUserChatRoomPresenceChangeEvent evt) + { + if(!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + localUserPresenceChanged(evt); + } + }); + return; + } + + ChatRoom sourceChatRoom = evt.getChatRoom(); + ChatRoomWrapper chatRoomWrapper + = GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom( + sourceChatRoom); + + String eventType = evt.getEventType(); + + if (LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_JOINED.equals(eventType)) + { + if(chatRoomWrapper != null) + { + GuiActivator.getMUCService().fireChatRoomListChangedEvent( + chatRoomWrapper, + ChatRoomListChangeEvent.CHAT_ROOM_CHANGED); + + boolean createWindow = false; + + String autoOpenConfig + = MUCService.getChatRoomAutoOpenOption( + sourceChatRoom.getParentProvider(), + sourceChatRoom.getIdentifier()); + + if(autoOpenConfig != null + && autoOpenConfig.equals(MUCService.OPEN_ON_ACTIVITY)) + createWindow = true; + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager.getMultiChat( + chatRoomWrapper, createWindow); + + if(chatPanel != null) + { + chatPanel.setChatIcon( + chatPanel.getChatSession().getChatStatusIcon()); + + // Check if we have already opened a chat window for this chat + // wrapper and load the real chat room corresponding to the + // wrapper. + if(chatPanel.isShown()) + { + ((ConferenceChatSession) chatPanel.getChatSession()) + .loadChatRoom(sourceChatRoom); + } + else + { + chatWindowManager.openChat(chatPanel, true); + } + } + } + + if (sourceChatRoom.isSystem()) + { + ChatRoomProviderWrapper serverWrapper + = GuiActivator.getMUCService() + .findServerWrapperFromProvider( + sourceChatRoom.getParentProvider()); + + serverWrapper.setSystemRoom(sourceChatRoom); + } + + sourceChatRoom.addMessageListener(this); + sourceChatRoom.addLocalUserRoleListener(this); + } + else if (LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_JOIN_FAILED.equals(eventType)) + { + GuiActivator.getAlertUIService().showAlertPopup( + GuiActivator.getResources().getI18NString("service.gui.ERROR"), + GuiActivator.getResources().getI18NString( + "service.gui.FAILED_TO_JOIN_CHAT_ROOM", + new String[]{sourceChatRoom.getName()}) + + evt.getReason()); + } + else if (LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_LEFT.equals(eventType) + || LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_KICKED.equals(eventType) + || LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_DROPPED.equals(eventType)) + { + if(chatRoomWrapper != null) + { + if(StringUtils.isNullOrEmpty(evt.getReason())) + { + GuiActivator.getUIService() + .closeChatRoomWindow(chatRoomWrapper); + } + else + { + // send some system messages informing for the + // reason of leaving + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + + ChatPanel chatPanel = chatWindowManager.getMultiChat( + sourceChatRoom, false); + + if(chatPanel != null) + { + chatPanel.addMessage( + sourceChatRoom.getName(), + null, + new Date(), + Chat.SYSTEM_MESSAGE, + evt.getReason(), + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, + null, + null); + + // print and the alternate address + if(!StringUtils.isNullOrEmpty( + evt.getAlternateAddress())) + { + chatPanel.addMessage( + sourceChatRoom.getName(), + null, + new Date(), + Chat.SYSTEM_MESSAGE, + GuiActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_ALTERNATE_ADDRESS", + new String[]{evt.getAlternateAddress()}), + OperationSetBasicInstantMessaging + .DEFAULT_MIME_TYPE, + null, + null); + } + } + } + + // Need to refresh the chat room's list in order to change + // the state of the chat room to offline. + + GuiActivator.getMUCService().fireChatRoomListChangedEvent( + chatRoomWrapper, + ChatRoomListChangeEvent.CHAT_ROOM_CHANGED); + } + + sourceChatRoom.removeMessageListener(this); + sourceChatRoom.removelocalUserRoleListener(this); + } + } + + + /** + * Called to accept an incoming invitation. Adds the invitation chat room + * to the list of chat rooms and joins it. + * + * @param invitation the invitation to accept + * @param multiUserChatOpSet the operation set for chat conferencing + * @throws OperationFailedException if the accept fails + */ + public void acceptInvitation( + AdHocChatRoomInvitation invitation, + OperationSetAdHocMultiUserChat multiUserChatOpSet) + throws OperationFailedException + { + AdHocChatRoom chatRoom = invitation.getTargetAdHocChatRoom(); + + chatRoom.join(); + } + + /** + * Rejects the given invitation with the specified reason. + * + * @param multiUserChatAdHocOpSet the operation set to use for rejecting the + * invitation + * @param invitation the invitation to reject + * @param reason the reason for the rejection + */ + public void rejectInvitation( + OperationSetAdHocMultiUserChat multiUserChatAdHocOpSet, + AdHocChatRoomInvitation invitation, + String reason) + { + multiUserChatAdHocOpSet.rejectInvitation(invitation, reason); + } + + /** + * Creates an ad-hoc chat room, by specifying the ad-hoc chat room name, the + * parent protocol provider and eventually, the contacts invited to + * participate in this ad-hoc chat room. + * + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason the reason for this invitation + * @return the AdHocChatRoomWrapper corresponding to the created + * ad hoc chat room + */ + public AdHocChatRoomWrapper createAdHocChatRoom( + ProtocolProviderService protocolProvider, + Collection contacts, + String reason) + { + AdHocChatRoomWrapper chatRoomWrapper = null; + + OperationSetAdHocMultiUserChat groupChatOpSet + = protocolProvider + .getOperationSet(OperationSetAdHocMultiUserChat.class); + + // If there's no group chat operation set we have nothing to do here. + if (groupChatOpSet == null) + return null; + + AdHocChatRoom chatRoom = null; + + try + { + java.util.List members = new LinkedList(); + + for(String address : contacts) + members.add(address); + + chatRoom = groupChatOpSet.createAdHocChatRoom( + "chatroom-" + new Date().getTime(), members, reason); + } + catch (OperationFailedException ex) + { + new ErrorDialog( + GuiActivator.getUIService().getMainFrame(), + GuiActivator.getResources().getI18NString("service.gui.ERROR"), + GuiActivator.getResources().getI18NString( + "service.gui.CREATE_CHAT_ROOM_ERROR", + new String[]{protocolProvider.getProtocolDisplayName()}), + ex) + .showDialog(); + } + catch (OperationNotSupportedException ex) + { + new ErrorDialog( + GuiActivator.getUIService().getMainFrame(), + GuiActivator.getResources().getI18NString("service.gui.ERROR"), + GuiActivator.getResources().getI18NString( + "service.gui.CREATE_CHAT_ROOM_ERROR", + new String[]{protocolProvider.getProtocolDisplayName()}), + ex) + .showDialog(); + } + + if(chatRoom != null) + { + AdHocChatRoomProviderWrapper parentProvider + = adHocChatRoomList.findServerWrapperFromProvider( + protocolProvider); + + chatRoomWrapper = new AdHocChatRoomWrapper( + parentProvider, chatRoom); + parentProvider.addAdHocChatRoom(chatRoomWrapper); + adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper); + + fireAdHocChatRoomListChangedEvent( + chatRoomWrapper, + AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED); + } + + return chatRoomWrapper; + } + + /** + * Joins the given ad-hoc chat room + * + * @param chatRoomWrapper + */ + public void joinChatRoom(AdHocChatRoomWrapper chatRoomWrapper) + { + AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom(); + + if(chatRoom == null) + { + new ErrorDialog( + GuiActivator.getUIService().getMainFrame(), + GuiActivator.getResources().getI18NString("service.gui.WARNING"), + GuiActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getAdHocChatRoomName()})) + .showDialog(); + + return; + } + + new JoinAdHocChatRoomTask(chatRoomWrapper).execute(); + } + + /** + * Removes the given chat room from the UI. + * + * @param chatRoomWrapper the chat room to remove. + */ + public void removeChatRoom(ChatRoomWrapper chatRoomWrapper) + { + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if (chatRoom != null) + leaveChatRoom(chatRoomWrapper); + + GuiActivator.getUIService().closeChatRoomWindow(chatRoomWrapper); + + GuiActivator.getMUCService().removeChatRoom(chatRoomWrapper); + + } + + /** + * Joins the given chat room and manages all the exceptions that could + * occur during the join process. + * + * @param chatRoom the chat room to join + */ + public void joinChatRoom(AdHocChatRoom chatRoom) + { + AdHocChatRoomWrapper chatRoomWrapper + = adHocChatRoomList.findChatRoomWrapperFromAdHocChatRoom(chatRoom); + + if(chatRoomWrapper == null) + { + AdHocChatRoomProviderWrapper parentProvider + = adHocChatRoomList.findServerWrapperFromProvider( + chatRoom.getParentProvider()); + + chatRoomWrapper = + new AdHocChatRoomWrapper(parentProvider, chatRoom); + + adHocChatRoomList.addAdHocChatRoom(chatRoomWrapper); + + fireAdHocChatRoomListChangedEvent( + chatRoomWrapper, + AdHocChatRoomListChangeEvent.AD_HOC_CHAT_ROOM_ADDED); + } + + this.joinChatRoom(chatRoomWrapper); + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + + chatWindowManager + .openChat( + chatWindowManager.getMultiChat(chatRoomWrapper, true), + true); + } + + /** + * Leaves the given ChatRoom. + * + * @param chatRoomWrapper the ChatRoom to leave. + */ + public void leaveChatRoom(ChatRoomWrapper chatRoomWrapper) + { + ChatRoomWrapper leavedRoomWrapped + = GuiActivator.getMUCService().leaveChatRoom(chatRoomWrapper); + if(leavedRoomWrapped != null) + GuiActivator.getUIService().closeChatRoomWindow(leavedRoomWrapped); + } + + /** + * Leaves the given ChatRoom. + * + * @param chatRoomWrapper the ChatRoom to leave. + */ + public void leaveChatRoom(AdHocChatRoomWrapper chatRoomWrapper) + { + AdHocChatRoom chatRoom = chatRoomWrapper.getAdHocChatRoom(); + + if (chatRoom != null) + { + chatRoom.leave(); + } + else + { + new ErrorDialog( + GuiActivator.getUIService().getMainFrame(), + GuiActivator.getResources().getI18NString("service.gui.WARNING"), + GuiActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED")) + .showDialog(); + } + } + + /** + * Checks if there's an open history window for the given chat room. + * + * @param chatRoomWrapper the chat room wrapper to check for + * @return TRUE if there's an opened history window for the given chat room, + * FALSE otherwise. + */ + public boolean containsHistoryWindowForChatRoom( + ChatRoomWrapper chatRoomWrapper) + { + return chatRoomHistory.containsKey(chatRoomWrapper); + } + + /** + * Returns the history window for the given chat room. + * + * @param chatRoomWrapper the chat room wrapper to search for + * @return the history window for the given chat room + */ + public HistoryWindow getHistoryWindowForChatRoom( + ChatRoomWrapper chatRoomWrapper) + { + return chatRoomHistory.get(chatRoomWrapper); + } + + /** + * Adds a history window for a given chat room in the table of opened + * history windows. + * + * @param chatRoomWrapper the chat room wrapper to add + * @param historyWindow the history window to add + */ + public void addHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper, + HistoryWindow historyWindow) + { + chatRoomHistory.put(chatRoomWrapper, historyWindow); + } + + /** + * Removes the history window for the given chat room. + * + * @param chatRoomWrapper the chat room wrapper to remove the history window + */ + public void removeHistoryWindowForChatRoom(ChatRoomWrapper chatRoomWrapper) + { + chatRoomHistory.remove(chatRoomWrapper); + } + + /** + * Adds the given AdHocChatRoomListChangeListener that will listen + * for all changes of the chat room list data model. + * + * @param l the listener to add. + */ + public void addAdHocChatRoomListChangeListener( + AdHocChatRoomListChangeListener l) + { + synchronized (adHoclistChangeListeners) + { + adHoclistChangeListeners.add(l); + } + } + + /** + * Removes the given AdHocChatRoomListChangeListener. + * + * @param l the listener to remove. + */ + public void removeAdHocChatRoomListChangeListener( + AdHocChatRoomListChangeListener l) + { + synchronized (adHoclistChangeListeners) + { + adHoclistChangeListeners.remove(l); + } + } + + /** + * Notifies all interested listeners that a change in the chat room list + * model has occurred. + * @param adHocChatRoomWrapper the chat room wrapper that identifies the + * chat room + * @param eventID the identifier of the event + */ + private void fireAdHocChatRoomListChangedEvent( + AdHocChatRoomWrapper adHocChatRoomWrapper, + int eventID) + { + AdHocChatRoomListChangeEvent evt + = new AdHocChatRoomListChangeEvent(adHocChatRoomWrapper, eventID); + + for (AdHocChatRoomListChangeListener l : adHoclistChangeListeners) + { + l.contentChanged(evt); + } + } + + + /** + * Closes the chat corresponding to the given ad-hoc chat room wrapper, if + * such exists. + * + * @param chatRoomWrapper the ad-hoc chat room wrapper for which we search a + * chat to close. + */ + private void closeAdHocChatRoom(AdHocChatRoomWrapper chatRoomWrapper) + { + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager.getMultiChat(chatRoomWrapper, false); + + if (chatPanel != null) + chatWindowManager.closeChat(chatPanel); + } + + /** + * Handles ServiceEvents triggered by adding or removing a + * ProtocolProviderService. Updates the list of available chat rooms and + * chat room servers. + * + * @param event The event to handle. + */ + public void serviceChanged(ServiceEvent event) + { + // if the event is caused by a bundle being stopped, we don't want to + // know + if (event.getServiceReference().getBundle().getState() + == Bundle.STOPPING) + return; + + Object service = GuiActivator.bundleContext.getService(event + .getServiceReference()); + + // we don't care if the source service is not a protocol provider + if (!(service instanceof ProtocolProviderService)) + return; + + ProtocolProviderService protocolProvider + = (ProtocolProviderService) service; + + + Object multiUserChatAdHocOpSet + = protocolProvider + .getOperationSet(OperationSetAdHocMultiUserChat.class); + + if (multiUserChatAdHocOpSet != null) + { + if (event.getType() == ServiceEvent.REGISTERED) + { + adHocChatRoomList.addChatProvider(protocolProvider); + } + else if (event.getType() == ServiceEvent.UNREGISTERING) + { + adHocChatRoomList.removeChatProvider(protocolProvider); + } + } + } + + /** + * Joins an ad-hoc chat room in an asynchronous way. + */ + private static class JoinAdHocChatRoomTask + extends SwingWorker + { + private static final String SUCCESS = "Success"; + + private static final String AUTHENTICATION_FAILED + = "AuthenticationFailed"; + + private static final String REGISTRATION_REQUIRED + = "RegistrationRequired"; + + private static final String PROVIDER_NOT_REGISTERED + = "ProviderNotRegistered"; + + private static final String SUBSCRIPTION_ALREADY_EXISTS + = "SubscriptionAlreadyExists"; + + private static final String UNKNOWN_ERROR + = "UnknownError"; + + private final AdHocChatRoomWrapper adHocChatRoomWrapper; + + JoinAdHocChatRoomTask(AdHocChatRoomWrapper chatRoomWrapper) + { + this.adHocChatRoomWrapper = chatRoomWrapper; + } + + /** + * @override {@link SwingWorker}{@link #doInBackground()} to perform + * all asynchronous tasks. + * @return SUCCESS if success, otherwise the error code + */ + @Override + public String doInBackground() + { + AdHocChatRoom chatRoom = adHocChatRoomWrapper.getAdHocChatRoom(); + + try + { + chatRoom.join(); + + return SUCCESS; + } + catch (OperationFailedException e) + { + if (logger.isTraceEnabled()) + logger.trace("Failed to join ad-hoc chat room: " + + chatRoom.getName(), e); + + switch (e.getErrorCode()) + { + case OperationFailedException.AUTHENTICATION_FAILED: + return AUTHENTICATION_FAILED; + case OperationFailedException.REGISTRATION_REQUIRED: + return REGISTRATION_REQUIRED; + case OperationFailedException.PROVIDER_NOT_REGISTERED: + return PROVIDER_NOT_REGISTERED; + case OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS: + return SUBSCRIPTION_ALREADY_EXISTS; + default: + return UNKNOWN_ERROR; + } + } + } + + /** + * @override {@link SwingWorker}{@link #done()} to perform UI changes + * after the ad-hoc chat room join task has finished. + */ + @Override + protected void done() + { + String returnCode = null; + try + { + returnCode = get(); + } + catch (InterruptedException ignore) + {} + catch (ExecutionException ignore) + {} + + ConfigurationUtils.updateChatRoomStatus( + adHocChatRoomWrapper.getParentProvider().getProtocolProvider(), + adHocChatRoomWrapper.getAdHocChatRoomID(), + GlobalStatusEnum.ONLINE_STATUS); + + String errorMessage = null; + if(PROVIDER_NOT_REGISTERED.equals(returnCode)) + { + errorMessage + = GuiActivator.getResources() + .getI18NString("service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{ + adHocChatRoomWrapper.getAdHocChatRoomName()}); + } + else if(SUBSCRIPTION_ALREADY_EXISTS.equals(returnCode)) + { + errorMessage + = GuiActivator.getResources() + .getI18NString("service.gui.CHAT_ROOM_ALREADY_JOINED", + new String[]{ + adHocChatRoomWrapper.getAdHocChatRoomName()}); + } + else + { + errorMessage + = GuiActivator.getResources() + .getI18NString("service.gui.FAILED_TO_JOIN_CHAT_ROOM", + new String[]{ + adHocChatRoomWrapper.getAdHocChatRoomName()}); + } + + if (!SUCCESS.equals(returnCode) + && !AUTHENTICATION_FAILED.equals(returnCode)) + { + GuiActivator.getAlertUIService().showAlertPopup( + GuiActivator.getResources().getI18NString( + "service.gui.ERROR"), errorMessage); + } + } + } + + + /** + * Indicates that an invitation has been received and opens the invitation + * dialog to notify the user. + * @param evt the AdHocChatRoomInvitationReceivedEvent that + * notified us + */ + public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt) + { + if (logger.isInfoEnabled()) + logger.info("Invitation received: "+evt.toString()); + OperationSetAdHocMultiUserChat multiUserChatOpSet + = evt.getSourceOperationSet(); + + InvitationReceivedDialog dialog = new InvitationReceivedDialog( + this, multiUserChatOpSet, evt.getInvitation()); + + dialog.setVisible(true); + } + + /** + * Implements the AdHocChatRoomMessageListener.messageDelivered + * method. + *
    + * Shows the message in the conversation area and clears the write message + * area. + * @param evt the AdHocChatRoomMessageDeliveredEvent that notified + * us + */ + public void messageDelivered(AdHocChatRoomMessageDeliveredEvent evt) + { + AdHocChatRoom sourceChatRoom = (AdHocChatRoom) evt.getSource(); + + if (logger.isInfoEnabled()) + logger.info("MESSAGE DELIVERED to ad-hoc chat room: " + + sourceChatRoom.getName()); + + ChatPanel chatPanel + = GuiActivator + .getUIService() + .getChatWindowManager() + .getMultiChat(sourceChatRoom, false); + + if(chatPanel != null) + { + String messageType; + switch (evt.getEventType()) + { + case AdHocChatRoomMessageDeliveredEvent + .CONVERSATION_MESSAGE_DELIVERED: + messageType = Chat.OUTGOING_MESSAGE; + break; + case AdHocChatRoomMessageDeliveredEvent.ACTION_MESSAGE_DELIVERED: + messageType = Chat.ACTION_MESSAGE; + break; + default: + messageType = null; + } + + Message msg = evt.getMessage(); + + chatPanel + .addMessage( + sourceChatRoom + .getParentProvider().getAccountID().getUserID(), + null, + evt.getTimestamp(), + messageType, + msg.getContent(), + msg.getContentType(), + msg.getMessageUID(), + null); + } + else + { + logger.error("chat panel is null, message NOT DELIVERED !"); + } + } + + /** + * Implements AdHocChatRoomMessageListener.messageDeliveryFailed + * method. + *
    + * In the conversation area shows an error message, explaining the problem. + * @param evt the AdHocChatRoomMessageDeliveryFailedEvent that + * notified us + */ + public void messageDeliveryFailed( + AdHocChatRoomMessageDeliveryFailedEvent evt) + { + AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom(); + Message sourceMessage = evt.getMessage(); + Contact destParticipant = evt.getDestinationParticipant(); + + String errorMsg = null; + if (evt.getErrorCode() + == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_NOT_SUPPORTED", + new String[]{destParticipant.getDisplayName()}); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.NETWORK_FAILURE) + { + errorMsg = GuiActivator.getResources() + .getI18NString("service.gui.MSG_NOT_DELIVERED"); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_SEND_CONNECTION_PROBLEM"); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.INTERNAL_ERROR) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_INTERNAL_ERROR"); + } + else if (evt.getErrorCode() + == MessageDeliveryFailedEvent.UNSUPPORTED_OPERATION) + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION"); + } + else + { + errorMsg = GuiActivator.getResources().getI18NString( + "service.gui.MSG_DELIVERY_UNKNOWN_ERROR"); + } + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager.getMultiChat(sourceChatRoom, true); + + chatPanel.addMessage( + destParticipant.getDisplayName(), + new Date(), + Chat.OUTGOING_MESSAGE, + sourceMessage.getContent(), + sourceMessage.getContentType()); + + chatPanel.addErrorMessage( + destParticipant.getDisplayName(), + errorMsg); + + chatWindowManager.openChat(chatPanel, false); + } + + /** + * Implements the AdHocChatRoomMessageListener.messageReceived + * method. + *
    + * Obtains the corresponding ChatPanel and process the message + * there. + * @param evt the AdHocChatRoomMessageReceivedEvent that notified + * us + */ + public void messageReceived(AdHocChatRoomMessageReceivedEvent evt) + { + AdHocChatRoom sourceChatRoom = evt.getSourceChatRoom(); + Contact sourceParticipant = evt.getSourceChatRoomParticipant(); + + String messageType = null; + + switch (evt.getEventType()) + { + case AdHocChatRoomMessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED: + messageType = Chat.INCOMING_MESSAGE; + break; + case AdHocChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED: + messageType = Chat.SYSTEM_MESSAGE; + break; + case AdHocChatRoomMessageReceivedEvent.ACTION_MESSAGE_RECEIVED: + messageType = Chat.ACTION_MESSAGE; + break; + } + + if (logger.isInfoEnabled()) + logger.info("MESSAGE RECEIVED from contact: " + + sourceParticipant.getAddress()); + + Message message = evt.getMessage(); + + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager + .getMultiChat(sourceChatRoom, true, message.getMessageUID()); + + String messageContent = message.getContent(); + + chatPanel.addMessage( + sourceParticipant.getDisplayName(), + null, + evt.getTimestamp(), + messageType, + messageContent, + message.getContentType(), + message.getMessageUID(), + null); + + chatWindowManager.openChat(chatPanel, false); + } + + public void invitationRejected(AdHocChatRoomInvitationRejectedEvent evt) {} + + @Override + public void localUserRoleChanged(ChatRoomLocalUserRoleChangeEvent evt) + { + if(evt.isInitial()) + return; + ChatRoom sourceChatRoom = evt.getSourceChatRoom(); + ChatRoomWrapper chatRoomWrapper + = GuiActivator.getMUCService().findChatRoomWrapperFromChatRoom( + sourceChatRoom); + ChatWindowManager chatWindowManager + = GuiActivator.getUIService().getChatWindowManager(); + ChatPanel chatPanel + = chatWindowManager.getMultiChat(chatRoomWrapper, true); + chatWindowManager.openChat(chatPanel, true); + } + +} diff --git a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ServerChatRoomsChoiceDialog.java b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ServerChatRoomsChoiceDialog.java index 3eeb783..4725a08 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ServerChatRoomsChoiceDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ServerChatRoomsChoiceDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,97 +15,97 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.chatroomslist; - -import java.awt.*; -import java.awt.event.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.contactlist.*; -import net.java.sip.communicator.impl.gui.utils.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.muc.*; - -/** - * A dialog that lists the existing chat rooms on the server. - * - * @author Hristo Terezov - */ -public class ServerChatRoomsChoiceDialog - extends OneChoiceInviteDialog -{ - - /** - * Generated serial id. - */ - private static final long serialVersionUID = 428358553225114162L; - - /** - * The contact source that generates the list of chat rooms. - */ - private ContactSourceService contactSource; - - /** - * Creates new instance of ServerChatRoomsChoiceDialog. - * - * @param title the title of the window. - * @param pps the protocol provider service associated with the list of chat - * rooms. - */ - public ServerChatRoomsChoiceDialog(String title, - ChatRoomProviderWrapper pps) - { - super(title); - contactList.setDefaultFilter(new SearchFilter(contactList)); - contactList.removeAllContactSources(); - contactSource = GuiActivator.getMUCService() - .getServerChatRoomsContactSourceForProvider(pps); - contactList.addContactSource( - contactSource); - - setInfoText(GuiActivator.getResources().getI18NString( - "service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT")); - - contactList.applyDefaultFilter(); - this.setMinimumSize(new Dimension(300, 300)); - addOkButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - UIContact uiContact = getSelectedContact(); - - if (uiContact != null) - { - ChatRoomTableDialog.setChatRoomField( - uiContact.getDisplayName()); - } - - setVisible(false); - dispose(); - } - }); - addCancelButtonListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - }); - } - - /** - * Handles provider change. - * - * @param provider the provider. - */ - public void changeProtocolProvider(ChatRoomProviderWrapper provider) - { - contactList.removeContactSource(contactSource); - contactSource = GuiActivator.getMUCService() - .getServerChatRoomsContactSourceForProvider(provider); - contactList.addContactSource(contactSource); - contactList.applyDefaultFilter(); - } -} +package net.java.sip.communicator.impl.gui.main.chatroomslist; + +import java.awt.*; +import java.awt.event.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.contactlist.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.muc.*; + +/** + * A dialog that lists the existing chat rooms on the server. + * + * @author Hristo Terezov + */ +public class ServerChatRoomsChoiceDialog + extends OneChoiceInviteDialog +{ + + /** + * Generated serial id. + */ + private static final long serialVersionUID = 428358553225114162L; + + /** + * The contact source that generates the list of chat rooms. + */ + private ContactSourceService contactSource; + + /** + * Creates new instance of ServerChatRoomsChoiceDialog. + * + * @param title the title of the window. + * @param pps the protocol provider service associated with the list of chat + * rooms. + */ + public ServerChatRoomsChoiceDialog(String title, + ChatRoomProviderWrapper pps) + { + super(title); + contactList.setDefaultFilter(new SearchFilter(contactList)); + contactList.removeAllContactSources(); + contactSource = GuiActivator.getMUCService() + .getServerChatRoomsContactSourceForProvider(pps); + contactList.addContactSource( + contactSource); + + setInfoText(GuiActivator.getResources().getI18NString( + "service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT")); + + contactList.applyDefaultFilter(); + this.setMinimumSize(new Dimension(300, 300)); + addOkButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + UIContact uiContact = getSelectedContact(); + + if (uiContact != null) + { + ChatRoomTableDialog.setChatRoomField( + uiContact.getDisplayName()); + } + + setVisible(false); + dispose(); + } + }); + addCancelButtonListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + setVisible(false); + dispose(); + } + }); + } + + /** + * Handles provider change. + * + * @param provider the provider. + */ + public void changeProtocolProvider(ChatRoomProviderWrapper provider) + { + contactList.removeContactSource(contactSource); + contactSource = GuiActivator.getMUCService() + .getServerChatRoomsContactSourceForProvider(provider); + contactList.addContactSource(contactSource); + contactList.applyDefaultFilter(); + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java index cf7108f..011b00a 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,353 +15,353 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.contactlist; - -import java.util.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.gui.event.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * The PresenceFilter is used to filter offline contacts from the - * contact list. - * - * @author Yana Stamcheva - */ -public class PresenceFilter - implements ContactListFilter -{ - /** - * The Logger used by the PresenceFilter class and its - * instances to print debugging information. - */ - private static final Logger logger = Logger.getLogger(PresenceFilter.class); - - /** - * Indicates if this presence filter shows or hides the offline contacts. - */ - private boolean isShowOffline; - - /** - * The initial result count below which we insert all filter results - * directly to the contact list without firing events. - */ - private static final int INITIAL_CONTACT_COUNT = 30; - - /** - * Creates an instance of PresenceFilter. - */ - public PresenceFilter() - { - isShowOffline = ConfigurationUtils.isShowOffline(); - } - - /** - * Applies this filter. This filter is applied over the - * MetaContactListService. - * - * @param filterQuery the query which keeps track of the filtering results - */ - public void applyFilter(FilterQuery filterQuery) - { - // Create the query that will track filtering. - MetaContactQuery query = new MetaContactQuery(); - - // Add this query to the filterQuery. - filterQuery.addContactQuery(query); - - TreeContactList contactList = GuiActivator.getContactList(); - - Collection uiContactSourceCollection - = contactList.getContactSources( - ContactSourceService.CONTACT_LIST_TYPE); - - Iterator filterSources - = uiContactSourceCollection.iterator(); - int maxIndex = 0; - while (filterSources.hasNext()) - { - UIContactSource filterSource = filterSources.next(); - int currIx = filterSource.getContactSourceService().getIndex(); - if(maxIndex < currIx) - maxIndex = currIx; - } - - contactList.getMetaContactListSource().setIndex(maxIndex + 1); - - filterSources = uiContactSourceCollection.iterator(); - while (filterSources.hasNext()) - { - UIContactSource filterSource = filterSources.next(); - - filterSource.setContactSourceIndex( - filterSource.getContactSourceService().getIndex()); - - ContactSourceService sourceService - = filterSource.getContactSourceService(); - - ContactQuery contactQuery - = sourceService.createContactQuery(null); - - if(contactQuery == null) - continue; - - // Add this query to the filterQuery. - filterQuery.addContactQuery(contactQuery); - - contactQuery.addContactQueryListener(contactList); - - contactQuery.start(); - } - - // Closes this filter to indicate that we finished adding queries to it. - filterQuery.close(); - - query.addContactQueryListener(GuiActivator.getContactList()); - int resultCount = 0; - - addMatching(GuiActivator.getContactListService().getRoot(), - query, - resultCount); - - query.fireQueryEvent( - query.isCanceled() - ? MetaContactQueryStatusEvent.QUERY_CANCELED - : MetaContactQueryStatusEvent.QUERY_COMPLETED); - } - - /** - * Indicates if the given uiContact is matching this filter. - * - * @param uiContact the UIContact to check - * @return true if the given uiContact is matching - * this filter, otherwise returns false - */ - public boolean isMatching(UIContact uiContact) - { - Object descriptor = uiContact.getDescriptor(); - - if (descriptor instanceof MetaContact) - return isMatching((MetaContact) descriptor); - else if (descriptor instanceof SourceContact) - return isMatching((SourceContact)descriptor); - else - return false; - } - - /** - * Indicates if the given uiGroup is matching this filter. - * - * @param uiGroup the UIGroup to check - * @return true if the given uiGroup is matching - * this filter, otherwise returns false - */ - public boolean isMatching(UIGroup uiGroup) - { - Object descriptor = uiGroup.getDescriptor(); - - if (descriptor instanceof MetaContactGroup) - return isMatching((MetaContactGroup) descriptor); - else - return false; - } - - /** - * Sets the show offline property. - * - * @param isShowOffline indicates if offline contacts are shown - */ - public void setShowOffline(boolean isShowOffline) - { - this.isShowOffline = isShowOffline; - - ConfigurationUtils.setShowOffline(isShowOffline); - } - - /** - * Returns true if offline contacts are shown, otherwise returns - * false. - * - * @return true if offline contacts are shown, otherwise returns - * false - */ - public boolean isShowOffline() - { - return isShowOffline; - } - - /** - * Returns true if offline contacts are shown or if the given - * MetaContact is online, otherwise returns false. - * - * @param metaContact the MetaContact to check - * @return true if the given MetaContact is matching this - * filter - */ - public boolean isMatching(MetaContact metaContact) - { - return isShowOffline || isContactOnline(metaContact); - } - - /** - * Returns true if offline contacts are shown or if the given - * MetaContact is online, otherwise returns false. - * - * @param contact the MetaContact to check - * @return true if the given MetaContact is matching this - * filter - */ - public boolean isMatching(SourceContact contact) - { - // make sure we always show chat rooms and recent messages - return - isShowOffline - || contact.getPresenceStatus().isOnline() - || contact.getContactSource().getType() - == ContactSourceService.CONTACT_LIST_TYPE; - } - - /** - * Returns true if offline contacts are shown or if the given - * MetaContactGroup contains online contacts. - * - * @param metaGroup the MetaContactGroup to check - * @return true if the given MetaContactGroup is matching - * this filter - */ - private boolean isMatching(MetaContactGroup metaGroup) - { - return - isShowOffline - || (metaGroup.countOnlineChildContacts() > 0) - || MetaContactListSource.isNewGroup(metaGroup); - } - - /** - * Returns true if the given meta contact is online, false - * otherwise. - * - * @param contact the meta contact - * @return true if the given meta contact is online, false - * otherwise - */ - private boolean isContactOnline(MetaContact contact) - { - // If for some reason the default contact is null we return false. - Contact defaultContact = contact.getDefaultContact(); - if(defaultContact == null) - return false; - - // Lays on the fact that the default contact is the most connected. - return defaultContact.getPresenceStatus().getStatus() - >= PresenceStatus.ONLINE_THRESHOLD; - } - - /** - * Adds all contacts contained in the given MetaContactGroup - * matching the current filter and not contained in the contact list. - * - * @param metaGroup the MetaContactGroup, which matching contacts - * to add - * @param query the MetaContactQuery that notifies interested - * listeners of the results of this matching - * @param resultCount the initial result count we would insert directly to - * the contact list without firing events - */ - private void addMatching( MetaContactGroup metaGroup, - MetaContactQuery query, - int resultCount) - { - Iterator childContacts = metaGroup.getChildContacts(); - - while (childContacts.hasNext() && !query.isCanceled()) - { - MetaContact metaContact = childContacts.next(); - - if(isMatching(metaContact)) - { - - resultCount++; - if (resultCount <= INITIAL_CONTACT_COUNT) - { - UIGroup uiGroup = null; - - if (!MetaContactListSource.isRootGroup(metaGroup)) - { - synchronized (metaGroup) - { - uiGroup = MetaContactListSource - .getUIGroup(metaGroup); - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(metaGroup); - } - } - - if (logger.isDebugEnabled()) - logger.debug("Presence filter contact added: " - + metaContact.getDisplayName()); - - UIContactImpl newUIContact; - synchronized (metaContact) - { - newUIContact - = MetaContactListSource.getUIContact(metaContact); - - if (newUIContact == null) - { - newUIContact = MetaContactListSource - .createUIContact(metaContact); - } - } - - GuiActivator.getContactList().addContact( - newUIContact, - uiGroup, - true, - true); - - query.setInitialResultCount(resultCount); - } - else - { - query.fireQueryEvent(metaContact); - } - } - } - - // If in the meantime the filtering has been stopped we return here. - if (query.isCanceled()) - return; - - Iterator subgroups = metaGroup.getSubgroups(); - while(subgroups.hasNext() && !query.isCanceled()) - { - MetaContactGroup subgroup = subgroups.next(); - - if (isMatching(subgroup)) - { - UIGroup uiGroup; - synchronized(subgroup) - { - uiGroup = MetaContactListSource - .getUIGroup(subgroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(subgroup); - } - - GuiActivator.getContactList().addGroup(uiGroup, true); - - addMatching(subgroup, query, resultCount); - } - } - } -} +package net.java.sip.communicator.impl.gui.main.contactlist; + +import java.util.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*; +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.gui.event.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The PresenceFilter is used to filter offline contacts from the + * contact list. + * + * @author Yana Stamcheva + */ +public class PresenceFilter + implements ContactListFilter +{ + /** + * The Logger used by the PresenceFilter class and its + * instances to print debugging information. + */ + private static final Logger logger = Logger.getLogger(PresenceFilter.class); + + /** + * Indicates if this presence filter shows or hides the offline contacts. + */ + private boolean isShowOffline; + + /** + * The initial result count below which we insert all filter results + * directly to the contact list without firing events. + */ + private static final int INITIAL_CONTACT_COUNT = 30; + + /** + * Creates an instance of PresenceFilter. + */ + public PresenceFilter() + { + isShowOffline = ConfigurationUtils.isShowOffline(); + } + + /** + * Applies this filter. This filter is applied over the + * MetaContactListService. + * + * @param filterQuery the query which keeps track of the filtering results + */ + public void applyFilter(FilterQuery filterQuery) + { + // Create the query that will track filtering. + MetaContactQuery query = new MetaContactQuery(); + + // Add this query to the filterQuery. + filterQuery.addContactQuery(query); + + TreeContactList contactList = GuiActivator.getContactList(); + + Collection uiContactSourceCollection + = contactList.getContactSources( + ContactSourceService.CONTACT_LIST_TYPE); + + Iterator filterSources + = uiContactSourceCollection.iterator(); + int maxIndex = 0; + while (filterSources.hasNext()) + { + UIContactSource filterSource = filterSources.next(); + int currIx = filterSource.getContactSourceService().getIndex(); + if(maxIndex < currIx) + maxIndex = currIx; + } + + contactList.getMetaContactListSource().setIndex(maxIndex + 1); + + filterSources = uiContactSourceCollection.iterator(); + while (filterSources.hasNext()) + { + UIContactSource filterSource = filterSources.next(); + + filterSource.setContactSourceIndex( + filterSource.getContactSourceService().getIndex()); + + ContactSourceService sourceService + = filterSource.getContactSourceService(); + + ContactQuery contactQuery + = sourceService.createContactQuery(null); + + if(contactQuery == null) + continue; + + // Add this query to the filterQuery. + filterQuery.addContactQuery(contactQuery); + + contactQuery.addContactQueryListener(contactList); + + contactQuery.start(); + } + + // Closes this filter to indicate that we finished adding queries to it. + filterQuery.close(); + + query.addContactQueryListener(GuiActivator.getContactList()); + int resultCount = 0; + + addMatching(GuiActivator.getContactListService().getRoot(), + query, + resultCount); + + query.fireQueryEvent( + query.isCanceled() + ? MetaContactQueryStatusEvent.QUERY_CANCELED + : MetaContactQueryStatusEvent.QUERY_COMPLETED); + } + + /** + * Indicates if the given uiContact is matching this filter. + * + * @param uiContact the UIContact to check + * @return true if the given uiContact is matching + * this filter, otherwise returns false + */ + public boolean isMatching(UIContact uiContact) + { + Object descriptor = uiContact.getDescriptor(); + + if (descriptor instanceof MetaContact) + return isMatching((MetaContact) descriptor); + else if (descriptor instanceof SourceContact) + return isMatching((SourceContact)descriptor); + else + return false; + } + + /** + * Indicates if the given uiGroup is matching this filter. + * + * @param uiGroup the UIGroup to check + * @return true if the given uiGroup is matching + * this filter, otherwise returns false + */ + public boolean isMatching(UIGroup uiGroup) + { + Object descriptor = uiGroup.getDescriptor(); + + if (descriptor instanceof MetaContactGroup) + return isMatching((MetaContactGroup) descriptor); + else + return false; + } + + /** + * Sets the show offline property. + * + * @param isShowOffline indicates if offline contacts are shown + */ + public void setShowOffline(boolean isShowOffline) + { + this.isShowOffline = isShowOffline; + + ConfigurationUtils.setShowOffline(isShowOffline); + } + + /** + * Returns true if offline contacts are shown, otherwise returns + * false. + * + * @return true if offline contacts are shown, otherwise returns + * false + */ + public boolean isShowOffline() + { + return isShowOffline; + } + + /** + * Returns true if offline contacts are shown or if the given + * MetaContact is online, otherwise returns false. + * + * @param metaContact the MetaContact to check + * @return true if the given MetaContact is matching this + * filter + */ + public boolean isMatching(MetaContact metaContact) + { + return isShowOffline || isContactOnline(metaContact); + } + + /** + * Returns true if offline contacts are shown or if the given + * MetaContact is online, otherwise returns false. + * + * @param contact the MetaContact to check + * @return true if the given MetaContact is matching this + * filter + */ + public boolean isMatching(SourceContact contact) + { + // make sure we always show chat rooms and recent messages + return + isShowOffline + || contact.getPresenceStatus().isOnline() + || contact.getContactSource().getType() + == ContactSourceService.CONTACT_LIST_TYPE; + } + + /** + * Returns true if offline contacts are shown or if the given + * MetaContactGroup contains online contacts. + * + * @param metaGroup the MetaContactGroup to check + * @return true if the given MetaContactGroup is matching + * this filter + */ + private boolean isMatching(MetaContactGroup metaGroup) + { + return + isShowOffline + || (metaGroup.countOnlineChildContacts() > 0) + || MetaContactListSource.isNewGroup(metaGroup); + } + + /** + * Returns true if the given meta contact is online, false + * otherwise. + * + * @param contact the meta contact + * @return true if the given meta contact is online, false + * otherwise + */ + private boolean isContactOnline(MetaContact contact) + { + // If for some reason the default contact is null we return false. + Contact defaultContact = contact.getDefaultContact(); + if(defaultContact == null) + return false; + + // Lays on the fact that the default contact is the most connected. + return defaultContact.getPresenceStatus().getStatus() + >= PresenceStatus.ONLINE_THRESHOLD; + } + + /** + * Adds all contacts contained in the given MetaContactGroup + * matching the current filter and not contained in the contact list. + * + * @param metaGroup the MetaContactGroup, which matching contacts + * to add + * @param query the MetaContactQuery that notifies interested + * listeners of the results of this matching + * @param resultCount the initial result count we would insert directly to + * the contact list without firing events + */ + private void addMatching( MetaContactGroup metaGroup, + MetaContactQuery query, + int resultCount) + { + Iterator childContacts = metaGroup.getChildContacts(); + + while (childContacts.hasNext() && !query.isCanceled()) + { + MetaContact metaContact = childContacts.next(); + + if(isMatching(metaContact)) + { + + resultCount++; + if (resultCount <= INITIAL_CONTACT_COUNT) + { + UIGroup uiGroup = null; + + if (!MetaContactListSource.isRootGroup(metaGroup)) + { + synchronized (metaGroup) + { + uiGroup = MetaContactListSource + .getUIGroup(metaGroup); + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(metaGroup); + } + } + + if (logger.isDebugEnabled()) + logger.debug("Presence filter contact added: " + + metaContact.getDisplayName()); + + UIContactImpl newUIContact; + synchronized (metaContact) + { + newUIContact + = MetaContactListSource.getUIContact(metaContact); + + if (newUIContact == null) + { + newUIContact = MetaContactListSource + .createUIContact(metaContact); + } + } + + GuiActivator.getContactList().addContact( + newUIContact, + uiGroup, + true, + true); + + query.setInitialResultCount(resultCount); + } + else + { + query.fireQueryEvent(metaContact); + } + } + } + + // If in the meantime the filtering has been stopped we return here. + if (query.isCanceled()) + return; + + Iterator subgroups = metaGroup.getSubgroups(); + while(subgroups.hasNext() && !query.isCanceled()) + { + MetaContactGroup subgroup = subgroups.next(); + + if (isMatching(subgroup)) + { + UIGroup uiGroup; + synchronized(subgroup) + { + uiGroup = MetaContactListSource + .getUIGroup(subgroup); + + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(subgroup); + } + + GuiActivator.getContactList().addGroup(uiGroup, true); + + addMatching(subgroup, query, resultCount); + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXPreferencesRegistration.java b/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXPreferencesRegistration.java index cfb5420..5a75ff1 100644 --- a/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXPreferencesRegistration.java +++ b/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXPreferencesRegistration.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,30 +15,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.menus; - -import com.apple.eawt.*; - -/** - * @author Lubomir Marinov - */ -public final class MacOSXPreferencesRegistration -{ - public static boolean run(final Object userData) - { - Application application = Application.getApplication(); - if (application != null) - { - application.setPreferencesHandler(new PreferencesHandler() - { - public void handlePreferences( - AppEvent.PreferencesEvent preferencesEvent) - { - ((ToolsMenu) userData).configActionPerformed(); - } - }); - return true; - } - return false; - } -} +package net.java.sip.communicator.impl.gui.main.menus; + +import com.apple.eawt.*; + +/** + * @author Lubomir Marinov + */ +public final class MacOSXPreferencesRegistration +{ + public static boolean run(final Object userData) + { + Application application = Application.getApplication(); + if (application != null) + { + application.setPreferencesHandler(new PreferencesHandler() + { + public void handlePreferences( + AppEvent.PreferencesEvent preferencesEvent) + { + ((ToolsMenu) userData).configActionPerformed(); + } + }); + return true; + } + return false; + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXQuitRegistration.java b/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXQuitRegistration.java index 594623b..4b786b2 100644 --- a/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXQuitRegistration.java +++ b/src/net/java/sip/communicator/impl/gui/main/menus/MacOSXQuitRegistration.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,68 +15,68 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.main.menus; - -import com.apple.eawt.*; - -/** - * @author Lubomir Marinov - */ -public final class MacOSXQuitRegistration -{ - public static boolean run(final Object userData) - { - Application application = Application.getApplication(); - if (application != null) - { - application.setQuitHandler(new QuitHandler() - { - public void handleQuitRequestWith(AppEvent.QuitEvent quitEvent, - final QuitResponse quitResponse) - { - ((FileMenu) userData).closeActionPerformed(); - - /* - * Tell Mac OS X that it shouldn't terminate the - * application. We've already initiated the quit and we'll - * eventually complete it i.e. we'll honor the request of - * Mac OS X to quit. - * - * (2011-06-10) Changed to true, we tell that quit is handled - * as otherwise will stop OS from logout or shutdown and - * a notification will be shown to user to inform about it. - * - * (2011-07-12) Wait before answering to the OS or we will - * end too quickly. 15sec is the time our shutdown timer - * waits before force the shutdown. - */ - - synchronized(this) - { - try - { - wait(15000); - }catch (InterruptedException ex){} - } - - /** - * Free the event dispatch thread before performing the - * quit (System.exit), shutdown timer may also has started - * the quit and is waiting to free the threads which - * we may be blocking. - */ - new Thread(new Runnable() - { - public void run() - { - quitResponse.performQuit(); - } - }).start(); - } - }); - - return true; - } - return false; - } -} +package net.java.sip.communicator.impl.gui.main.menus; + +import com.apple.eawt.*; + +/** + * @author Lubomir Marinov + */ +public final class MacOSXQuitRegistration +{ + public static boolean run(final Object userData) + { + Application application = Application.getApplication(); + if (application != null) + { + application.setQuitHandler(new QuitHandler() + { + public void handleQuitRequestWith(AppEvent.QuitEvent quitEvent, + final QuitResponse quitResponse) + { + ((FileMenu) userData).closeActionPerformed(); + + /* + * Tell Mac OS X that it shouldn't terminate the + * application. We've already initiated the quit and we'll + * eventually complete it i.e. we'll honor the request of + * Mac OS X to quit. + * + * (2011-06-10) Changed to true, we tell that quit is handled + * as otherwise will stop OS from logout or shutdown and + * a notification will be shown to user to inform about it. + * + * (2011-07-12) Wait before answering to the OS or we will + * end too quickly. 15sec is the time our shutdown timer + * waits before force the shutdown. + */ + + synchronized(this) + { + try + { + wait(15000); + }catch (InterruptedException ex){} + } + + /** + * Free the event dispatch thread before performing the + * quit (System.exit), shutdown timer may also has started + * the quit and is waiting to free the threads which + * we may be blocking. + */ + new Thread(new Runnable() + { + public void run() + { + quitResponse.performQuit(); + } + }).start(); + } + }); + + return true; + } + return false; + } +} diff --git a/src/net/java/sip/communicator/impl/gui/utils/PluginContainer.java b/src/net/java/sip/communicator/impl/gui/utils/PluginContainer.java index e85c51c..d24855f 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/PluginContainer.java +++ b/src/net/java/sip/communicator/impl/gui/utils/PluginContainer.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,318 +15,318 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.gui.utils; - -import java.awt.*; -import java.util.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.*; -import net.java.sip.communicator.impl.gui.event.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.gui.Container; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Provides capabilities to a specific JComponent to contain - * PluginComponents, track when they are added and removed. - * - * @author Lyubomir Marinov - */ -public class PluginContainer - implements PluginComponentListener -{ - /** - * The Logger used by the PluginContainer class and its - * instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(PluginContainer.class); - - /** - * The JComponent which contains the components of the - * PluginComponents managed by this instance. - */ - private final JComponent container; - - /** - * The container id of the PluginComponent managed by this - * instance. - */ - private final Container containerId; - - /** - * The list of PluginComponent instances which have their - * components added to this PluginContainer. - */ - private final java.util.List pluginComponents - = new LinkedList(); - - /** - * Initializes a new PluginContainer instance which is to - * provide capabilities to a specific JComponent container with - * a specific Container id to contain - * PluginComponent and track when they are added and removed. - * - * @param container - * the JComponent container the new instance is to - * provide its capabilities to - * @param containerId - * the Container id of the specified - * container - */ - public PluginContainer(JComponent container, Container containerId) - { - this.container = container; - this.containerId = containerId; - - initPluginComponents(); - } - - /** - * Adds a specific Component to a specific JComponent - * container. Allows extenders to apply custom logic to the exact placement - * of the specified Component in the specified container. - * - * @param component the Component to be added to the specified - * JComponent container - * @param container the JComponent container to add the specified - * Component to - * @param preferredIndex the index at which component is to be - * added to container if possible or -1 if there is no - * preference with respect to the index in question - */ - protected void addComponentToContainer( - Component component, - JComponent container, - int preferredIndex) - { - if ((0 <= preferredIndex) - && (preferredIndex < getComponentCount(container))) - container.add(component, preferredIndex); - else - container.add(component); - } - - /** - * Adds the component of a specific PluginComponent to the - * associated Container. - * - * @param factory the PluginComponentFactory which is to have its - * component added to the Container associated with this - * PluginContainer - */ - private synchronized void addPluginComponent(PluginComponentFactory factory) - { - PluginComponent c = - factory.getPluginComponentInstance(PluginContainer.this); - - if (logger.isInfoEnabled()) - logger.info("Will add plugin component: " + c); - - /* - * Try to respect positionIndex of PluginComponent to some extent: - * PluginComponents with positionIndex equal to 0 go at the beginning, - * these with positionIndex equal to -1 follow them and then go these - * with positionIndex greater than 0. - */ - int cIndex = factory.getPositionIndex(); - int index = -1; - int i = 0; - - for (PluginComponent pluginComponent : pluginComponents) - { - if (pluginComponent.equals(c)) - return; - - if (-1 == index) - { - int pluginComponentIndex = factory.getPositionIndex(); - - if ((0 == cIndex) || (-1 == cIndex)) - { - if ((0 != pluginComponentIndex) - && (cIndex != pluginComponentIndex)) - index = i; - } - else if (cIndex < pluginComponentIndex) - index = i; - } - - i++; - } - - int pluginComponentCount = pluginComponents.size(); - - if (-1 == index) - index = pluginComponents.size(); - - /* - * The container may have added Components of its own apart from the - * ones this PluginContainer has added to it. Since the common case for - * the additional Components is to have them appear at the beginning, - * adjust the index so it gets correct in the common case. - */ - int containerComponentCount = getComponentCount(container); - - addComponentToContainer( - (Component) c.getComponent(), - container, - (containerComponentCount > pluginComponentCount) - ? (index + (containerComponentCount - pluginComponentCount)) - : index); - pluginComponents.add(index, c); - - container.revalidate(); - container.repaint(); - } - - /** - * Runs clean-up for associated resources which need explicit disposal (e.g. - * listeners keeping this instance alive because they were added to the - * model which operationally outlives this instance). - */ - public void dispose() - { - GuiActivator.getUIService().removePluginComponentListener(this); - - /* - * Explicitly remove the components of the PluginComponent instances - * because the latter are registered with OSGi and are thus global. - */ - synchronized (this) - { - for (PluginComponent pluginComponent : pluginComponents) - container.remove((Component) pluginComponent.getComponent()); - pluginComponents.clear(); - } - } - - /** - * Gets the number of Components in a specific JComponent - * container. For example, returns the result of - * getMenuComponentCount() if container is an instance of - * JMenu. - * - * @param container the JComponent container to get the number of - * Components of - * @return the number of Components in the specified - * container - */ - protected int getComponentCount(JComponent container) - { - return - (container instanceof JMenu) - ? ((JMenu) container).getMenuComponentCount() - : container.getComponentCount(); - } - - /** - * Gets the PluginComponents of this PluginContainer. - * - * @return an Iterable over the PluginComponents of this - * PluginContainer - */ - public Iterable getPluginComponents() - { - return pluginComponents; - } - - /** - * Adds the Components of the PluginComponents registered - * in the OSGi BundleContext in the associated Container. - */ - private void initPluginComponents() - { - GuiActivator.getUIService().addPluginComponentListener(this); - - // Look for PluginComponents registered in the OSGi BundleContext. - ServiceReference[] serRefs = null; - - try - { - serRefs - = GuiActivator - .bundleContext - .getServiceReferences( - PluginComponentFactory.class.getName(), - "(" - + Container.CONTAINER_ID - + "=" - + containerId.getID() - + ")"); - } - catch (InvalidSyntaxException exc) - { - logger.error("Could not obtain plugin reference.", exc); - } - - if (serRefs != null) - { - for (ServiceReference serRef : serRefs) - { - PluginComponentFactory factory - = (PluginComponentFactory) - GuiActivator.bundleContext.getService(serRef); - - addPluginComponent(factory); - } - } - } - - /** - * Implements - * {@link PluginComponentListener#pluginComponentAdded(PluginComponentEvent)}. - * - * @param event a PluginComponentEvent which specifies the - * PluginComponent which has been added - */ - public void pluginComponentAdded(PluginComponentEvent event) - { - PluginComponentFactory factory = event.getPluginComponentFactory(); - - if (factory.getContainer().equals(containerId)) - addPluginComponent(factory); - } - - /** - * Implements - * {@link PluginComponentListener#pluginComponentRemoved(PluginComponentEvent)}. - * - * @param event a PluginComponentEvent which specifies the - * PluginComponent which has been added - */ - public void pluginComponentRemoved(PluginComponentEvent event) - { - PluginComponentFactory factory = event.getPluginComponentFactory(); - - if (factory.getContainer().equals(containerId)) - removePluginComponent(factory); - } - - /** - * Removes the component of a specific PluginComponent from - * this PluginContainer. - * - * @param factory - * the PluginComponent which is to have its - * component removed from this PluginContainer - */ - private synchronized void removePluginComponent( - PluginComponentFactory factory) - { - Iterator iterator = pluginComponents.iterator(); - while(iterator.hasNext()) - { - PluginComponent c = iterator.next(); - if(c.getParentFactory().equals(factory)) - { - iterator.remove(); - container.remove((Component)c.getComponent()); - } - } - } -} +package net.java.sip.communicator.impl.gui.utils; + +import java.awt.*; +import java.util.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.event.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.gui.Container; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * Provides capabilities to a specific JComponent to contain + * PluginComponents, track when they are added and removed. + * + * @author Lyubomir Marinov + */ +public class PluginContainer + implements PluginComponentListener +{ + /** + * The Logger used by the PluginContainer class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(PluginContainer.class); + + /** + * The JComponent which contains the components of the + * PluginComponents managed by this instance. + */ + private final JComponent container; + + /** + * The container id of the PluginComponent managed by this + * instance. + */ + private final Container containerId; + + /** + * The list of PluginComponent instances which have their + * components added to this PluginContainer. + */ + private final java.util.List pluginComponents + = new LinkedList(); + + /** + * Initializes a new PluginContainer instance which is to + * provide capabilities to a specific JComponent container with + * a specific Container id to contain + * PluginComponent and track when they are added and removed. + * + * @param container + * the JComponent container the new instance is to + * provide its capabilities to + * @param containerId + * the Container id of the specified + * container + */ + public PluginContainer(JComponent container, Container containerId) + { + this.container = container; + this.containerId = containerId; + + initPluginComponents(); + } + + /** + * Adds a specific Component to a specific JComponent + * container. Allows extenders to apply custom logic to the exact placement + * of the specified Component in the specified container. + * + * @param component the Component to be added to the specified + * JComponent container + * @param container the JComponent container to add the specified + * Component to + * @param preferredIndex the index at which component is to be + * added to container if possible or -1 if there is no + * preference with respect to the index in question + */ + protected void addComponentToContainer( + Component component, + JComponent container, + int preferredIndex) + { + if ((0 <= preferredIndex) + && (preferredIndex < getComponentCount(container))) + container.add(component, preferredIndex); + else + container.add(component); + } + + /** + * Adds the component of a specific PluginComponent to the + * associated Container. + * + * @param factory the PluginComponentFactory which is to have its + * component added to the Container associated with this + * PluginContainer + */ + private synchronized void addPluginComponent(PluginComponentFactory factory) + { + PluginComponent c = + factory.getPluginComponentInstance(PluginContainer.this); + + if (logger.isInfoEnabled()) + logger.info("Will add plugin component: " + c); + + /* + * Try to respect positionIndex of PluginComponent to some extent: + * PluginComponents with positionIndex equal to 0 go at the beginning, + * these with positionIndex equal to -1 follow them and then go these + * with positionIndex greater than 0. + */ + int cIndex = factory.getPositionIndex(); + int index = -1; + int i = 0; + + for (PluginComponent pluginComponent : pluginComponents) + { + if (pluginComponent.equals(c)) + return; + + if (-1 == index) + { + int pluginComponentIndex = factory.getPositionIndex(); + + if ((0 == cIndex) || (-1 == cIndex)) + { + if ((0 != pluginComponentIndex) + && (cIndex != pluginComponentIndex)) + index = i; + } + else if (cIndex < pluginComponentIndex) + index = i; + } + + i++; + } + + int pluginComponentCount = pluginComponents.size(); + + if (-1 == index) + index = pluginComponents.size(); + + /* + * The container may have added Components of its own apart from the + * ones this PluginContainer has added to it. Since the common case for + * the additional Components is to have them appear at the beginning, + * adjust the index so it gets correct in the common case. + */ + int containerComponentCount = getComponentCount(container); + + addComponentToContainer( + (Component) c.getComponent(), + container, + (containerComponentCount > pluginComponentCount) + ? (index + (containerComponentCount - pluginComponentCount)) + : index); + pluginComponents.add(index, c); + + container.revalidate(); + container.repaint(); + } + + /** + * Runs clean-up for associated resources which need explicit disposal (e.g. + * listeners keeping this instance alive because they were added to the + * model which operationally outlives this instance). + */ + public void dispose() + { + GuiActivator.getUIService().removePluginComponentListener(this); + + /* + * Explicitly remove the components of the PluginComponent instances + * because the latter are registered with OSGi and are thus global. + */ + synchronized (this) + { + for (PluginComponent pluginComponent : pluginComponents) + container.remove((Component) pluginComponent.getComponent()); + pluginComponents.clear(); + } + } + + /** + * Gets the number of Components in a specific JComponent + * container. For example, returns the result of + * getMenuComponentCount() if container is an instance of + * JMenu. + * + * @param container the JComponent container to get the number of + * Components of + * @return the number of Components in the specified + * container + */ + protected int getComponentCount(JComponent container) + { + return + (container instanceof JMenu) + ? ((JMenu) container).getMenuComponentCount() + : container.getComponentCount(); + } + + /** + * Gets the PluginComponents of this PluginContainer. + * + * @return an Iterable over the PluginComponents of this + * PluginContainer + */ + public Iterable getPluginComponents() + { + return pluginComponents; + } + + /** + * Adds the Components of the PluginComponents registered + * in the OSGi BundleContext in the associated Container. + */ + private void initPluginComponents() + { + GuiActivator.getUIService().addPluginComponentListener(this); + + // Look for PluginComponents registered in the OSGi BundleContext. + ServiceReference[] serRefs = null; + + try + { + serRefs + = GuiActivator + .bundleContext + .getServiceReferences( + PluginComponentFactory.class.getName(), + "(" + + Container.CONTAINER_ID + + "=" + + containerId.getID() + + ")"); + } + catch (InvalidSyntaxException exc) + { + logger.error("Could not obtain plugin reference.", exc); + } + + if (serRefs != null) + { + for (ServiceReference serRef : serRefs) + { + PluginComponentFactory factory + = (PluginComponentFactory) + GuiActivator.bundleContext.getService(serRef); + + addPluginComponent(factory); + } + } + } + + /** + * Implements + * {@link PluginComponentListener#pluginComponentAdded(PluginComponentEvent)}. + * + * @param event a PluginComponentEvent which specifies the + * PluginComponent which has been added + */ + public void pluginComponentAdded(PluginComponentEvent event) + { + PluginComponentFactory factory = event.getPluginComponentFactory(); + + if (factory.getContainer().equals(containerId)) + addPluginComponent(factory); + } + + /** + * Implements + * {@link PluginComponentListener#pluginComponentRemoved(PluginComponentEvent)}. + * + * @param event a PluginComponentEvent which specifies the + * PluginComponent which has been added + */ + public void pluginComponentRemoved(PluginComponentEvent event) + { + PluginComponentFactory factory = event.getPluginComponentFactory(); + + if (factory.getContainer().equals(containerId)) + removePluginComponent(factory); + } + + /** + * Removes the component of a specific PluginComponent from + * this PluginContainer. + * + * @param factory + * the PluginComponent which is to have its + * component removed from this PluginContainer + */ + private synchronized void removePluginComponent( + PluginComponentFactory factory) + { + Iterator iterator = pluginComponents.iterator(); + while(iterator.hasNext()) + { + PluginComponent c = iterator.next(); + if(c.getParentFactory().equals(factory)) + { + iterator.remove(); + container.remove((Component)c.getComponent()); + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/hid/HIDServiceImpl.java b/src/net/java/sip/communicator/impl/hid/HIDServiceImpl.java index 00046d7..02552db 100644 --- a/src/net/java/sip/communicator/impl/hid/HIDServiceImpl.java +++ b/src/net/java/sip/communicator/impl/hid/HIDServiceImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,223 +15,223 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package net.java.sip.communicator.impl.hid; - -import java.awt.*; -import java.awt.event.*; - -import net.java.sip.communicator.service.hid.*; -import net.java.sip.communicator.util.Logger; - -import org.jitsi.util.*; - -/** - * Implementation of the HID service to provide way of regenerate key press - * and mouse interactions. - * - * @author Sebastien Vincent - */ -public class HIDServiceImpl implements HIDService -{ - /** - * The Logger used by the NeomediaActivator class and its - * instances for logging output. - */ - private final Logger logger = Logger.getLogger(HIDServiceImpl.class); - - /** - * The robot used to perform some operations (mouse/key interactions). - */ - private Robot robot = null; - - /** - * Object to regenerates keys with JNI. - */ - private NativeKeyboard nativeKeyboard = null; - - /** - * Constructor. - */ - protected HIDServiceImpl() - { - try - { - robot = new Robot(); - nativeKeyboard = new NativeKeyboard(); - } - catch(Throwable e) - { - if(!GraphicsEnvironment.isHeadless()) - logger.error( - "Error when creating Robot/NativeKeyboard instance", e); - } - } - - /** - * Press a specific key using its keycode. - * - * @param keycode the Java keycode, all available keycodes can be found - * in java.awt.event.KeyEvent class (VK_A, VK_SPACE, ...) - * @see java.awt.event.KeyEvent - */ - public void keyPress(int keycode) - { - if(OSUtils.IS_WINDOWS || OSUtils.IS_MAC) - { - /* do not allow modifiers for Windows (as - * they are handled in native code with - * VkScanCode) and Mac OS X - */ - if(keycode == KeyEvent.VK_ALT || - keycode == KeyEvent.VK_SHIFT || - keycode == KeyEvent.VK_ALT_GRAPH) - { - return; - } - } - - /* AltGr does not seems to work with robot, handle it via our - * JNI code - */ - if(keycode == KeyEvent.VK_ALT_GRAPH) - { - symbolPress("altgr"); - } - else - { - robot.keyPress(keycode); - } - } - - /** - * Release a specific key using its keycode. - * - * @param keycode the Java keycode, all available keycode can be found - * in java.awt.event.KeyEvent class (VK_A, VK_SPACE, ...) - * @see java.awt.event.KeyEvent - */ - public void keyRelease(int keycode) - { - /* AltGr does not seems to work with robot, handle it via our - * JNI code - */ - if(keycode == KeyEvent.VK_ALT_GRAPH) - { - symbolRelease("altgr"); - } - else - { - robot.keyRelease(keycode); - } - } - - /** - * Press a specific key using its char representation. - * - * @param key char representation of the key - */ - public void keyPress(char key) - { - /* check for CTRL+X where X is [A-Z] - * CTRL+A = 1, A = 65 - */ - if(key >= 1 && key <= 0x1A) - { - key = (char)(key + 64); - robot.keyPress(key); - return; - } - - nativeKeyboard.keyPress(key); - } - - /** - * Release a specific key using its char representation. - * - * @param key char representation of the key - */ - public void keyRelease(char key) - { - /* check for CTRL+X where X is [A-Z] - * CTRL+A = 1, A = 65 - */ - if(key >= 1 && key <= 0x1A) - { - key = (char)(key + 64); - robot.keyRelease(key); - return; - } - - if(nativeKeyboard != null) - nativeKeyboard.keyRelease(key); - } - - /** - * Press a specific symbol (such as SHIFT or CTRL). - * - * @param symbol symbol name - */ - private void symbolPress(String symbol) - { - if(nativeKeyboard != null) - nativeKeyboard.symbolPress(symbol); - } - - /** - * Release a specific symbol (such as SHIFT or CTRL). - * - * @param symbol symbol name - */ - private void symbolRelease(String symbol) - { - if(nativeKeyboard != null) - nativeKeyboard.symbolRelease(symbol); - } - - /** - * Press a mouse button(s). - * - * @param btns button masks - * @see java.awt.Robot#mousePress(int btns) - */ - public void mousePress(int btns) - { - robot.mousePress(btns); - } - - /** - * Release a mouse button(s). - * - * @param btns button masks - * @see java.awt.Robot#mouseRelease(int btns) - */ - public void mouseRelease(int btns) - { - robot.mouseRelease(btns); - } - - /** - * Move the mouse on the screen. - * - * @param x x position on the screen - * @param y y position on the screen - * @see java.awt.Robot#mouseMove(int x, int y) - */ - public void mouseMove(int x, int y) - { - robot.mouseMove(x, y); - } - - /** - * Release a mouse button(s). - * - * @param rotation wheel rotation (could be negative or positive depending - * on the direction). - * @see java.awt.Robot#mouseWheel(int wheelAmt) - */ - public void mouseWheel(int rotation) - { - robot.mouseWheel(rotation); - } -} + +package net.java.sip.communicator.impl.hid; + +import java.awt.*; +import java.awt.event.*; + +import net.java.sip.communicator.service.hid.*; +import net.java.sip.communicator.util.Logger; + +import org.jitsi.util.*; + +/** + * Implementation of the HID service to provide way of regenerate key press + * and mouse interactions. + * + * @author Sebastien Vincent + */ +public class HIDServiceImpl implements HIDService +{ + /** + * The Logger used by the NeomediaActivator class and its + * instances for logging output. + */ + private final Logger logger = Logger.getLogger(HIDServiceImpl.class); + + /** + * The robot used to perform some operations (mouse/key interactions). + */ + private Robot robot = null; + + /** + * Object to regenerates keys with JNI. + */ + private NativeKeyboard nativeKeyboard = null; + + /** + * Constructor. + */ + protected HIDServiceImpl() + { + try + { + robot = new Robot(); + nativeKeyboard = new NativeKeyboard(); + } + catch(Throwable e) + { + if(!GraphicsEnvironment.isHeadless()) + logger.error( + "Error when creating Robot/NativeKeyboard instance", e); + } + } + + /** + * Press a specific key using its keycode. + * + * @param keycode the Java keycode, all available keycodes can be found + * in java.awt.event.KeyEvent class (VK_A, VK_SPACE, ...) + * @see java.awt.event.KeyEvent + */ + public void keyPress(int keycode) + { + if(OSUtils.IS_WINDOWS || OSUtils.IS_MAC) + { + /* do not allow modifiers for Windows (as + * they are handled in native code with + * VkScanCode) and Mac OS X + */ + if(keycode == KeyEvent.VK_ALT || + keycode == KeyEvent.VK_SHIFT || + keycode == KeyEvent.VK_ALT_GRAPH) + { + return; + } + } + + /* AltGr does not seems to work with robot, handle it via our + * JNI code + */ + if(keycode == KeyEvent.VK_ALT_GRAPH) + { + symbolPress("altgr"); + } + else + { + robot.keyPress(keycode); + } + } + + /** + * Release a specific key using its keycode. + * + * @param keycode the Java keycode, all available keycode can be found + * in java.awt.event.KeyEvent class (VK_A, VK_SPACE, ...) + * @see java.awt.event.KeyEvent + */ + public void keyRelease(int keycode) + { + /* AltGr does not seems to work with robot, handle it via our + * JNI code + */ + if(keycode == KeyEvent.VK_ALT_GRAPH) + { + symbolRelease("altgr"); + } + else + { + robot.keyRelease(keycode); + } + } + + /** + * Press a specific key using its char representation. + * + * @param key char representation of the key + */ + public void keyPress(char key) + { + /* check for CTRL+X where X is [A-Z] + * CTRL+A = 1, A = 65 + */ + if(key >= 1 && key <= 0x1A) + { + key = (char)(key + 64); + robot.keyPress(key); + return; + } + + nativeKeyboard.keyPress(key); + } + + /** + * Release a specific key using its char representation. + * + * @param key char representation of the key + */ + public void keyRelease(char key) + { + /* check for CTRL+X where X is [A-Z] + * CTRL+A = 1, A = 65 + */ + if(key >= 1 && key <= 0x1A) + { + key = (char)(key + 64); + robot.keyRelease(key); + return; + } + + if(nativeKeyboard != null) + nativeKeyboard.keyRelease(key); + } + + /** + * Press a specific symbol (such as SHIFT or CTRL). + * + * @param symbol symbol name + */ + private void symbolPress(String symbol) + { + if(nativeKeyboard != null) + nativeKeyboard.symbolPress(symbol); + } + + /** + * Release a specific symbol (such as SHIFT or CTRL). + * + * @param symbol symbol name + */ + private void symbolRelease(String symbol) + { + if(nativeKeyboard != null) + nativeKeyboard.symbolRelease(symbol); + } + + /** + * Press a mouse button(s). + * + * @param btns button masks + * @see java.awt.Robot#mousePress(int btns) + */ + public void mousePress(int btns) + { + robot.mousePress(btns); + } + + /** + * Release a mouse button(s). + * + * @param btns button masks + * @see java.awt.Robot#mouseRelease(int btns) + */ + public void mouseRelease(int btns) + { + robot.mouseRelease(btns); + } + + /** + * Move the mouse on the screen. + * + * @param x x position on the screen + * @param y y position on the screen + * @see java.awt.Robot#mouseMove(int x, int y) + */ + public void mouseMove(int x, int y) + { + robot.mouseMove(x, y); + } + + /** + * Release a mouse button(s). + * + * @param rotation wheel rotation (could be negative or positive depending + * on the direction). + * @see java.awt.Robot#mouseWheel(int wheelAmt) + */ + public void mouseWheel(int rotation) + { + robot.mouseWheel(rotation); + } +} diff --git a/src/net/java/sip/communicator/impl/ldap/LdapSSLSocketFactoryDelegate.java b/src/net/java/sip/communicator/impl/ldap/LdapSSLSocketFactoryDelegate.java index dabb4c6..9888628 100644 --- a/src/net/java/sip/communicator/impl/ldap/LdapSSLSocketFactoryDelegate.java +++ b/src/net/java/sip/communicator/impl/ldap/LdapSSLSocketFactoryDelegate.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,75 +15,75 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.ldap; - -import java.io.*; -import java.net.*; -import java.security.*; - -import javax.net.*; - -import net.java.sip.communicator.service.certificate.*; -import net.java.sip.communicator.util.*; - -/** - * Utility class to delegate the creation of sockets to LDAP servers to our - * {@link CertificateService}. - *

    - * Note that the documentation says to extend {@link SocketFactory}, but the - * LDAP directory context tries to create an unconnected socket without a - * hostname first by calling createSocket. It would be impossible to - * validate the hostname against the certificate, which leads to an insecure - * communication. It only calls {@link #createSocket(String, int)} when - * createSocket is not found - * - * @author Ingo Bauersachs - */ -public class LdapSSLSocketFactoryDelegate -{ - /** - * Logger for this class. - */ - private final static Logger logger = - Logger.getLogger(LdapSSLSocketFactoryDelegate.class); - - /** - * Get default SSL socket factory delegate. - * - * @return default SSL socket factory delegate. - */ - public static Object getDefault() - { - return new LdapSSLSocketFactoryDelegate(); - } - - /** - * Creates a socket for the specified destination host and port. - * - * @param host The hostname that the socket connects to. - * @param port The port that the socket connects to. - * @return The created socket. - * @throws IOException - * @throws UnknownHostException When the hostname cannot be resolved to an - * IP address. - */ - public Socket createSocket(String host, int port) - throws IOException, - UnknownHostException - { - try - { - return LdapServiceImpl - .getCertificateService() - .getSSLContext( - LdapServiceImpl.getCertificateService().getTrustManager( - host)).getSocketFactory().createSocket(host, port); - } - catch (GeneralSecurityException e) - { - logger.error( - "unable to create socket through the certificate service", e); - throw new IOException(e.getMessage()); - } - } -} +package net.java.sip.communicator.impl.ldap; + +import java.io.*; +import java.net.*; +import java.security.*; + +import javax.net.*; + +import net.java.sip.communicator.service.certificate.*; +import net.java.sip.communicator.util.*; + +/** + * Utility class to delegate the creation of sockets to LDAP servers to our + * {@link CertificateService}. + *

    + * Note that the documentation says to extend {@link SocketFactory}, but the + * LDAP directory context tries to create an unconnected socket without a + * hostname first by calling createSocket. It would be impossible to + * validate the hostname against the certificate, which leads to an insecure + * communication. It only calls {@link #createSocket(String, int)} when + * createSocket is not found + * + * @author Ingo Bauersachs + */ +public class LdapSSLSocketFactoryDelegate +{ + /** + * Logger for this class. + */ + private final static Logger logger = + Logger.getLogger(LdapSSLSocketFactoryDelegate.class); + + /** + * Get default SSL socket factory delegate. + * + * @return default SSL socket factory delegate. + */ + public static Object getDefault() + { + return new LdapSSLSocketFactoryDelegate(); + } + + /** + * Creates a socket for the specified destination host and port. + * + * @param host The hostname that the socket connects to. + * @param port The port that the socket connects to. + * @return The created socket. + * @throws IOException + * @throws UnknownHostException When the hostname cannot be resolved to an + * IP address. + */ + public Socket createSocket(String host, int port) + throws IOException, + UnknownHostException + { + try + { + return LdapServiceImpl + .getCertificateService() + .getSSLContext( + LdapServiceImpl.getCertificateService().getTrustManager( + host)).getSocketFactory().createSocket(host, port); + } + catch (GeneralSecurityException e) + { + logger.error( + "unable to create socket through the certificate service", e); + throw new IOException(e.getMessage()); + } + } +} diff --git a/src/net/java/sip/communicator/impl/muc/BaseChatRoomSourceContact.java b/src/net/java/sip/communicator/impl/muc/BaseChatRoomSourceContact.java index 3225af9..28f43e3 100644 --- a/src/net/java/sip/communicator/impl/muc/BaseChatRoomSourceContact.java +++ b/src/net/java/sip/communicator/impl/muc/BaseChatRoomSourceContact.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,141 +15,141 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import java.util.*; - -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * Basic source contact for the chat rooms. - * - * @author Hristo Terezov - */ -public class BaseChatRoomSourceContact - extends SortedGenericSourceContact -{ - - /** - * The parent contact query. - */ - protected final ContactQuery parentQuery; - - /** - * The name of the chat room associated with the contact. - */ - private String chatRoomName; - - /** - * The ID of the chat room associated with the contact. - */ - private String chatRoomID; - - /** - * The protocol provider of the chat room associated with the contact. - */ - private ProtocolProviderService provider; - - /** - * Contsructs new chat room source contact. - * @param chatRoomName the name of the chat room associated with the room. - * @param chatRoomID the id of the chat room associated with the room. - * @param query the query associated with the contact. - * @param pps the protocol provider of the contact. - */ - public BaseChatRoomSourceContact(String chatRoomName, - String chatRoomID, ContactQuery query, ProtocolProviderService pps) - { - super(query, query.getContactSource(), chatRoomName, - generateDefaultContactDetails(chatRoomName)); - - this.chatRoomName = chatRoomName; - this.chatRoomID = chatRoomID; - this.provider = pps; - this.parentQuery = query; - - initContactProperties(ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); - setDisplayDetails(pps.getAccountID().getDisplayName()); - } - - - /** - * Sets the given presence status and the name of the chat room associated - * with the contact. - * @param status the presence status to be set. - */ - protected void initContactProperties(PresenceStatus status) - { - setPresenceStatus(status); - setContactAddress(chatRoomName); - } - - /** - * Generates the default contact details for - * BaseChatRoomSourceContact instances. - * - * @param chatRoomName the name of the chat room associated with the contact - * @return list of default ContactDetails for the contact. - */ - private static List generateDefaultContactDetails( - String chatRoomName) - { - ContactDetail contactDetail - = new ContactDetail(chatRoomName); - List> supportedOpSets - = new ArrayList>(); - - supportedOpSets.add(OperationSetMultiUserChat.class); - contactDetail.setSupportedOpSets(supportedOpSets); - - List contactDetails - = new ArrayList(); - - contactDetails.add(contactDetail); - return contactDetails; - } - - /** - * Returns the id of the chat room associated with the contact. - * - * @return the chat room id. - */ - public String getChatRoomID() - { - return chatRoomID; - } - - /** - * Returns the name of the chat room associated with the contact. - * - * @return the chat room name - */ - public String getChatRoomName() - { - return chatRoomName; - } - - /** - * Returns the provider of the chat room associated with the contact. - * - * @return the provider - */ - public ProtocolProviderService getProvider() - { - return provider; - } - - /** - * Returns the index of this source contact in its parent group. - * - * @return the index of this contact in its parent - */ - public int getIndex() - { - if(parentQuery instanceof ServerChatRoomQuery) - return ((ServerChatRoomQuery)parentQuery).indexOf(this); - return -1; - } -} +package net.java.sip.communicator.impl.muc; + +import java.util.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * Basic source contact for the chat rooms. + * + * @author Hristo Terezov + */ +public class BaseChatRoomSourceContact + extends SortedGenericSourceContact +{ + + /** + * The parent contact query. + */ + protected final ContactQuery parentQuery; + + /** + * The name of the chat room associated with the contact. + */ + private String chatRoomName; + + /** + * The ID of the chat room associated with the contact. + */ + private String chatRoomID; + + /** + * The protocol provider of the chat room associated with the contact. + */ + private ProtocolProviderService provider; + + /** + * Contsructs new chat room source contact. + * @param chatRoomName the name of the chat room associated with the room. + * @param chatRoomID the id of the chat room associated with the room. + * @param query the query associated with the contact. + * @param pps the protocol provider of the contact. + */ + public BaseChatRoomSourceContact(String chatRoomName, + String chatRoomID, ContactQuery query, ProtocolProviderService pps) + { + super(query, query.getContactSource(), chatRoomName, + generateDefaultContactDetails(chatRoomName)); + + this.chatRoomName = chatRoomName; + this.chatRoomID = chatRoomID; + this.provider = pps; + this.parentQuery = query; + + initContactProperties(ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); + setDisplayDetails(pps.getAccountID().getDisplayName()); + } + + + /** + * Sets the given presence status and the name of the chat room associated + * with the contact. + * @param status the presence status to be set. + */ + protected void initContactProperties(PresenceStatus status) + { + setPresenceStatus(status); + setContactAddress(chatRoomName); + } + + /** + * Generates the default contact details for + * BaseChatRoomSourceContact instances. + * + * @param chatRoomName the name of the chat room associated with the contact + * @return list of default ContactDetails for the contact. + */ + private static List generateDefaultContactDetails( + String chatRoomName) + { + ContactDetail contactDetail + = new ContactDetail(chatRoomName); + List> supportedOpSets + = new ArrayList>(); + + supportedOpSets.add(OperationSetMultiUserChat.class); + contactDetail.setSupportedOpSets(supportedOpSets); + + List contactDetails + = new ArrayList(); + + contactDetails.add(contactDetail); + return contactDetails; + } + + /** + * Returns the id of the chat room associated with the contact. + * + * @return the chat room id. + */ + public String getChatRoomID() + { + return chatRoomID; + } + + /** + * Returns the name of the chat room associated with the contact. + * + * @return the chat room name + */ + public String getChatRoomName() + { + return chatRoomName; + } + + /** + * Returns the provider of the chat room associated with the contact. + * + * @return the provider + */ + public ProtocolProviderService getProvider() + { + return provider; + } + + /** + * Returns the index of this source contact in its parent group. + * + * @return the index of this contact in its parent + */ + public int getIndex() + { + if(parentQuery instanceof ServerChatRoomQuery) + return ((ServerChatRoomQuery)parentQuery).indexOf(this); + return -1; + } +} diff --git a/src/net/java/sip/communicator/impl/muc/ChatRoomQuery.java b/src/net/java/sip/communicator/impl/muc/ChatRoomQuery.java index 24a3ebd..9cd1c21 100644 --- a/src/net/java/sip/communicator/impl/muc/ChatRoomQuery.java +++ b/src/net/java/sip/communicator/impl/muc/ChatRoomQuery.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,543 +15,543 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import java.util.*; -import java.util.regex.*; - -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; - -import org.osgi.framework.*; - -/** - * The ChatRoomQuery is a query over the - * ChatRoomContactSourceService. - * - * @author Hristo Terezov - */ -public class ChatRoomQuery - extends AsyncContactQuery - implements LocalUserChatRoomPresenceListener, - ChatRoomListChangeListener, - ChatRoomProviderWrapperListener -{ - /** - * The query string. - */ - private String queryString; - - /** - * List with the current results for the query. - */ - private Set contactResults - = new TreeSet(); - - /** - * MUC service. - */ - private MUCServiceImpl mucService; - - /** - * The number of contact query listeners. - */ - private int contactQueryListenersCount = 0; - - /** - * The protocol provider registration listener. - */ - private ServiceListener protolProviderRegistrationListener = null; - - /** - * Creates an instance of ChatRoomQuery by specifying - * the parent contact source, the query string to match and the maximum - * result contacts to return. - * - * @param queryString the query string to match - * @param contactSource the parent contact source - */ - public ChatRoomQuery(String queryString, - ChatRoomContactSourceService contactSource) - { - super(contactSource, - Pattern.compile(queryString, Pattern.CASE_INSENSITIVE - | Pattern.LITERAL), true); - this.queryString = queryString; - - mucService = MUCActivator.getMUCService(); - - } - - /** - * Adds listeners for the query - */ - private void initListeners() - { - for(ProtocolProviderService pps : MUCActivator.getChatRoomProviders()) - { - addQueryToProviderPresenceListeners(pps); - } - - mucService.addChatRoomListChangeListener(this); - mucService.addChatRoomProviderWrapperListener(this); - protolProviderRegistrationListener = new ProtocolProviderRegListener(); - MUCActivator.bundleContext.addServiceListener( - protolProviderRegistrationListener); - } - - /** - * Adds the query as presence listener to protocol provider service. - * @param pps the protocol provider service. - */ - public void addQueryToProviderPresenceListeners(ProtocolProviderService pps) - { - OperationSetMultiUserChat opSetMUC - = pps.getOperationSet(OperationSetMultiUserChat.class); - if(opSetMUC != null) - { - opSetMUC.addPresenceListener(this); - } - } - - /** - * Removes the query from protocol provider service presence listeners. - * @param pps the protocol provider service. - */ - public void removeQueryFromProviderPresenceListeners( - ProtocolProviderService pps) - { - OperationSetMultiUserChat opSetMUC - = pps.getOperationSet(OperationSetMultiUserChat.class); - if(opSetMUC != null) - { - opSetMUC.removePresenceListener(this); - } - } - - @Override - protected void run() - { - Iterator chatRoomProviders - = mucService.getChatRoomProviders(); - - while (chatRoomProviders.hasNext()) - { - ChatRoomProviderWrapper provider = chatRoomProviders.next(); - providerAdded(provider, true); - } - - if (getStatus() != QUERY_CANCELED) - setStatus(QUERY_COMPLETED); - } - - /** - * Handles adding a chat room provider. - * @param provider the provider. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the results. - */ - private void providerAdded(ChatRoomProviderWrapper provider, - boolean addQueryResult) - { - - for(int i = 0; i < provider.countChatRooms(); i++) - { - ChatRoomWrapper chatRoom = provider.getChatRoom(i); - addChatRoom( provider.getProtocolProvider(), - chatRoom.getChatRoomName(), chatRoom.getChatRoomID(), - addQueryResult, chatRoom.isAutojoin()); - } - } - - /** - * Handles chat room presence status updates. - * - * @param evt the LocalUserChatRoomPresenceChangeEvent instance - * containing the chat room and the type, and reason of the change - */ - @Override - public void localUserPresenceChanged( - LocalUserChatRoomPresenceChangeEvent evt) - { - ChatRoom sourceChatRoom = evt.getChatRoom(); - - String eventType = evt.getEventType(); - - boolean existingContact = false; - ChatRoomSourceContact foundContact = null; - synchronized (contactResults) - { - for (ChatRoomSourceContact contact : contactResults) - { - if (contactEqualsChatRoom(contact, sourceChatRoom)) - { - existingContact = true; - foundContact = contact; - contactResults.remove(contact); - break; - } - } - } - - if (LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_JOINED.equals(eventType)) - { - if(existingContact) - { - foundContact.setPresenceStatus( - ChatRoomPresenceStatus.CHAT_ROOM_ONLINE); - synchronized (contactResults) - { - contactResults.add(foundContact); - } - fireContactChanged(foundContact); - } - else - { - ChatRoomWrapper chatRoom - = MUCActivator.getMUCService() - .findChatRoomWrapperFromChatRoom(sourceChatRoom); - if(chatRoom != null) - addChatRoom(sourceChatRoom, false, chatRoom.isAutojoin()); - } - } - else if ((LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_LEFT.equals(eventType) - || LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_KICKED.equals(eventType) - || LocalUserChatRoomPresenceChangeEvent - .LOCAL_USER_DROPPED.equals(eventType)) - ) - { - if(existingContact) - { - foundContact.setPresenceStatus( - ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); - synchronized (contactResults) - { - contactResults.add(foundContact); - } - fireContactChanged(foundContact); - } - } - } - - /** - * Adds found result to the query results. - * - * @param room the chat room. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the results. - * @param isAutoJoin the auto join state of the contact. - */ - private void addChatRoom(ChatRoom room, boolean addQueryResult, - boolean isAutoJoin) - { - if(queryString == null - || ((room.getName().contains( - queryString) - || room.getIdentifier().contains(queryString) - ))) - { - ChatRoomSourceContact contact - = new ChatRoomSourceContact(room, this, isAutoJoin); - synchronized (contactResults) - { - contactResults.add(contact); - } - - if(addQueryResult) - { - addQueryResult(contact, false); - } - else - { - fireContactReceived(contact, false); - } - } - } - - /** - * Adds found result to the query results. - * - * @param pps the protocol provider associated with the found chat room. - * @param chatRoomName the name of the chat room. - * @param chatRoomID the id of the chat room. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the results. - * @param isAutoJoin the auto join state of the contact. - */ - private void addChatRoom(ProtocolProviderService pps, - String chatRoomName, String chatRoomID, boolean addQueryResult, - boolean isAutoJoin) - { - if(queryString == null - || ((chatRoomName.contains( - queryString) - || chatRoomID.contains(queryString) - ))) - { - ChatRoomSourceContact contact - = new ChatRoomSourceContact(chatRoomName, chatRoomID, this, pps, - isAutoJoin); - synchronized (contactResults) - { - contactResults.add(contact); - } - - if(addQueryResult) - { - addQueryResult(contact, false); - } - else - { - fireContactReceived(contact, false); - } - } - } - - /** - * Indicates that a change has occurred in the chat room data list. - * @param evt the event that describes the change. - */ - @Override - public void contentChanged(final ChatRoomListChangeEvent evt) - { - ChatRoomWrapper chatRoom = evt.getSourceChatRoom(); - switch (evt.getEventID()) - { - case ChatRoomListChangeEvent.CHAT_ROOM_ADDED: - addChatRoom(chatRoom.getChatRoom(), false, - chatRoom.isAutojoin()); - break; - case ChatRoomListChangeEvent.CHAT_ROOM_REMOVED: - LinkedList tmpContactResults; - synchronized (contactResults) - { - tmpContactResults - = new LinkedList(contactResults); - - for (ChatRoomSourceContact contact : tmpContactResults) - { - if (contactEqualsChatRoom(contact, chatRoom)) - { - contactResults.remove(contact); - fireContactRemoved(contact); - break; - } - } - } - break; - case ChatRoomListChangeEvent.CHAT_ROOM_CHANGED: - synchronized (contactResults) - { - for (ChatRoomSourceContact contact : contactResults) - { - if (contactEqualsChatRoom(contact, - chatRoom.getChatRoom())) - { - if (chatRoom.isAutojoin() != contact.isAutoJoin()) - { - contact.setAutoJoin(chatRoom.isAutojoin()); - fireContactChanged(contact); - } - break; - } - } - } - break; - default: - break; - } - } - - @Override - public void chatRoomProviderWrapperAdded(ChatRoomProviderWrapper provider) - { - providerAdded(provider, false); - } - - @Override - public void chatRoomProviderWrapperRemoved(ChatRoomProviderWrapper provider) - { - LinkedList tmpContactResults; - synchronized (contactResults) - { - tmpContactResults - = new LinkedList(contactResults); - - for(ChatRoomSourceContact contact : tmpContactResults) - { - if(contact.getProvider().equals(provider.getProtocolProvider())) - { - contactResults.remove(contact); - fireContactRemoved(contact); - } - } - } - } - - /** - * Test equality of contact to chat room. This test recognizes that chat - * rooms may have equal names but connected to different accounts. - * - * @param contact the contact - * @param chatRoom the chat room - * @return returns true if they are equal, or false if - * they are different - */ - private boolean contactEqualsChatRoom(final ChatRoomSourceContact contact, - final ChatRoom chatRoom) - { - return contact.getProvider() == chatRoom.getParentProvider() - && chatRoom.getIdentifier().equals(contact.getContactAddress()); - } - - /** - * Test equality of contact to chat room wrapper. This method does not rely - * on a chat room instance, since that may not be available in case of - * removal. - * - * @param contact the contact - * @param chatRoomWrapper the chat room wrapper - * @return returns true if they are equal, or false if - * they are different. - */ - private boolean contactEqualsChatRoom(final ChatRoomSourceContact contact, - final ChatRoomWrapper chatRoomWrapper) - { - return contact.getProvider() == chatRoomWrapper.getParentProvider() - .getProtocolProvider() - && contact.getContactAddress().equals( - chatRoomWrapper.getChatRoomID()); - } - - /** - * Returns the index of the contact in the contact results list. - * @param contact the contact. - * @return the index of the contact in the contact results list. - */ - public synchronized int indexOf(ChatRoomSourceContact contact) - { - Iterator it = contactResults.iterator(); - int i = 0; - while(it.hasNext()) - { - if(contact.equals(it.next())) - { - return i; - } - i++; - } - return -1; - } - - /** - * Clears any listener we used. - */ - private void clearListeners() - { - mucService.removeChatRoomListChangeListener(this); - mucService.removeChatRoomProviderWrapperListener(this); - if(protolProviderRegistrationListener != null) - MUCActivator.bundleContext.removeServiceListener( - protolProviderRegistrationListener); - protolProviderRegistrationListener = null; - for(ProtocolProviderService pps : MUCActivator.getChatRoomProviders()) - { - removeQueryFromProviderPresenceListeners(pps); - } - } - - /** - * Cancels this ContactQuery. - * - * @see ContactQuery#cancel() - */ - public void cancel() - { - clearListeners(); - - super.cancel(); - } - - /** - * If query has status changed to cancel, let's clear listeners. - * @param status {@link ContactQuery#QUERY_CANCELED}, - * {@link ContactQuery#QUERY_COMPLETED} - */ - public void setStatus(int status) - { - if(status == QUERY_CANCELED) - clearListeners(); - - super.setStatus(status); - } - - @Override - public void addContactQueryListener(ContactQueryListener l) - { - super.addContactQueryListener(l); - contactQueryListenersCount++; - if(contactQueryListenersCount == 1) - { - initListeners(); - } - } - - @Override - public void removeContactQueryListener(ContactQueryListener l) - { - super.removeContactQueryListener(l); - contactQueryListenersCount--; - if(contactQueryListenersCount == 0) - { - clearListeners(); - } - } - - /** - * Listens for ProtocolProviderService registrations. - */ - private class ProtocolProviderRegListener - implements ServiceListener - { - /** - * Handles service change events. - */ - public void serviceChanged(ServiceEvent event) - { - ServiceReference serviceRef = event.getServiceReference(); - - // if the event is caused by a bundle being stopped, we don't want to - // know - if (serviceRef.getBundle().getState() == Bundle.STOPPING) - { - return; - } - - Object service = MUCActivator.bundleContext.getService(serviceRef); - - // we don't care if the source service is not a protocol provider - if (!(service instanceof ProtocolProviderService)) - { - return; - } - - switch (event.getType()) - { - case ServiceEvent.REGISTERED: - addQueryToProviderPresenceListeners( - (ProtocolProviderService) service); - break; - case ServiceEvent.UNREGISTERING: - removeQueryFromProviderPresenceListeners( - (ProtocolProviderService) service); - break; - } - } - } +package net.java.sip.communicator.impl.muc; + +import java.util.*; +import java.util.regex.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; + +import org.osgi.framework.*; + +/** + * The ChatRoomQuery is a query over the + * ChatRoomContactSourceService. + * + * @author Hristo Terezov + */ +public class ChatRoomQuery + extends AsyncContactQuery + implements LocalUserChatRoomPresenceListener, + ChatRoomListChangeListener, + ChatRoomProviderWrapperListener +{ + /** + * The query string. + */ + private String queryString; + + /** + * List with the current results for the query. + */ + private Set contactResults + = new TreeSet(); + + /** + * MUC service. + */ + private MUCServiceImpl mucService; + + /** + * The number of contact query listeners. + */ + private int contactQueryListenersCount = 0; + + /** + * The protocol provider registration listener. + */ + private ServiceListener protolProviderRegistrationListener = null; + + /** + * Creates an instance of ChatRoomQuery by specifying + * the parent contact source, the query string to match and the maximum + * result contacts to return. + * + * @param queryString the query string to match + * @param contactSource the parent contact source + */ + public ChatRoomQuery(String queryString, + ChatRoomContactSourceService contactSource) + { + super(contactSource, + Pattern.compile(queryString, Pattern.CASE_INSENSITIVE + | Pattern.LITERAL), true); + this.queryString = queryString; + + mucService = MUCActivator.getMUCService(); + + } + + /** + * Adds listeners for the query + */ + private void initListeners() + { + for(ProtocolProviderService pps : MUCActivator.getChatRoomProviders()) + { + addQueryToProviderPresenceListeners(pps); + } + + mucService.addChatRoomListChangeListener(this); + mucService.addChatRoomProviderWrapperListener(this); + protolProviderRegistrationListener = new ProtocolProviderRegListener(); + MUCActivator.bundleContext.addServiceListener( + protolProviderRegistrationListener); + } + + /** + * Adds the query as presence listener to protocol provider service. + * @param pps the protocol provider service. + */ + public void addQueryToProviderPresenceListeners(ProtocolProviderService pps) + { + OperationSetMultiUserChat opSetMUC + = pps.getOperationSet(OperationSetMultiUserChat.class); + if(opSetMUC != null) + { + opSetMUC.addPresenceListener(this); + } + } + + /** + * Removes the query from protocol provider service presence listeners. + * @param pps the protocol provider service. + */ + public void removeQueryFromProviderPresenceListeners( + ProtocolProviderService pps) + { + OperationSetMultiUserChat opSetMUC + = pps.getOperationSet(OperationSetMultiUserChat.class); + if(opSetMUC != null) + { + opSetMUC.removePresenceListener(this); + } + } + + @Override + protected void run() + { + Iterator chatRoomProviders + = mucService.getChatRoomProviders(); + + while (chatRoomProviders.hasNext()) + { + ChatRoomProviderWrapper provider = chatRoomProviders.next(); + providerAdded(provider, true); + } + + if (getStatus() != QUERY_CANCELED) + setStatus(QUERY_COMPLETED); + } + + /** + * Handles adding a chat room provider. + * @param provider the provider. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the results. + */ + private void providerAdded(ChatRoomProviderWrapper provider, + boolean addQueryResult) + { + + for(int i = 0; i < provider.countChatRooms(); i++) + { + ChatRoomWrapper chatRoom = provider.getChatRoom(i); + addChatRoom( provider.getProtocolProvider(), + chatRoom.getChatRoomName(), chatRoom.getChatRoomID(), + addQueryResult, chatRoom.isAutojoin()); + } + } + + /** + * Handles chat room presence status updates. + * + * @param evt the LocalUserChatRoomPresenceChangeEvent instance + * containing the chat room and the type, and reason of the change + */ + @Override + public void localUserPresenceChanged( + LocalUserChatRoomPresenceChangeEvent evt) + { + ChatRoom sourceChatRoom = evt.getChatRoom(); + + String eventType = evt.getEventType(); + + boolean existingContact = false; + ChatRoomSourceContact foundContact = null; + synchronized (contactResults) + { + for (ChatRoomSourceContact contact : contactResults) + { + if (contactEqualsChatRoom(contact, sourceChatRoom)) + { + existingContact = true; + foundContact = contact; + contactResults.remove(contact); + break; + } + } + } + + if (LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_JOINED.equals(eventType)) + { + if(existingContact) + { + foundContact.setPresenceStatus( + ChatRoomPresenceStatus.CHAT_ROOM_ONLINE); + synchronized (contactResults) + { + contactResults.add(foundContact); + } + fireContactChanged(foundContact); + } + else + { + ChatRoomWrapper chatRoom + = MUCActivator.getMUCService() + .findChatRoomWrapperFromChatRoom(sourceChatRoom); + if(chatRoom != null) + addChatRoom(sourceChatRoom, false, chatRoom.isAutojoin()); + } + } + else if ((LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_LEFT.equals(eventType) + || LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_KICKED.equals(eventType) + || LocalUserChatRoomPresenceChangeEvent + .LOCAL_USER_DROPPED.equals(eventType)) + ) + { + if(existingContact) + { + foundContact.setPresenceStatus( + ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); + synchronized (contactResults) + { + contactResults.add(foundContact); + } + fireContactChanged(foundContact); + } + } + } + + /** + * Adds found result to the query results. + * + * @param room the chat room. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the results. + * @param isAutoJoin the auto join state of the contact. + */ + private void addChatRoom(ChatRoom room, boolean addQueryResult, + boolean isAutoJoin) + { + if(queryString == null + || ((room.getName().contains( + queryString) + || room.getIdentifier().contains(queryString) + ))) + { + ChatRoomSourceContact contact + = new ChatRoomSourceContact(room, this, isAutoJoin); + synchronized (contactResults) + { + contactResults.add(contact); + } + + if(addQueryResult) + { + addQueryResult(contact, false); + } + else + { + fireContactReceived(contact, false); + } + } + } + + /** + * Adds found result to the query results. + * + * @param pps the protocol provider associated with the found chat room. + * @param chatRoomName the name of the chat room. + * @param chatRoomID the id of the chat room. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the results. + * @param isAutoJoin the auto join state of the contact. + */ + private void addChatRoom(ProtocolProviderService pps, + String chatRoomName, String chatRoomID, boolean addQueryResult, + boolean isAutoJoin) + { + if(queryString == null + || ((chatRoomName.contains( + queryString) + || chatRoomID.contains(queryString) + ))) + { + ChatRoomSourceContact contact + = new ChatRoomSourceContact(chatRoomName, chatRoomID, this, pps, + isAutoJoin); + synchronized (contactResults) + { + contactResults.add(contact); + } + + if(addQueryResult) + { + addQueryResult(contact, false); + } + else + { + fireContactReceived(contact, false); + } + } + } + + /** + * Indicates that a change has occurred in the chat room data list. + * @param evt the event that describes the change. + */ + @Override + public void contentChanged(final ChatRoomListChangeEvent evt) + { + ChatRoomWrapper chatRoom = evt.getSourceChatRoom(); + switch (evt.getEventID()) + { + case ChatRoomListChangeEvent.CHAT_ROOM_ADDED: + addChatRoom(chatRoom.getChatRoom(), false, + chatRoom.isAutojoin()); + break; + case ChatRoomListChangeEvent.CHAT_ROOM_REMOVED: + LinkedList tmpContactResults; + synchronized (contactResults) + { + tmpContactResults + = new LinkedList(contactResults); + + for (ChatRoomSourceContact contact : tmpContactResults) + { + if (contactEqualsChatRoom(contact, chatRoom)) + { + contactResults.remove(contact); + fireContactRemoved(contact); + break; + } + } + } + break; + case ChatRoomListChangeEvent.CHAT_ROOM_CHANGED: + synchronized (contactResults) + { + for (ChatRoomSourceContact contact : contactResults) + { + if (contactEqualsChatRoom(contact, + chatRoom.getChatRoom())) + { + if (chatRoom.isAutojoin() != contact.isAutoJoin()) + { + contact.setAutoJoin(chatRoom.isAutojoin()); + fireContactChanged(contact); + } + break; + } + } + } + break; + default: + break; + } + } + + @Override + public void chatRoomProviderWrapperAdded(ChatRoomProviderWrapper provider) + { + providerAdded(provider, false); + } + + @Override + public void chatRoomProviderWrapperRemoved(ChatRoomProviderWrapper provider) + { + LinkedList tmpContactResults; + synchronized (contactResults) + { + tmpContactResults + = new LinkedList(contactResults); + + for(ChatRoomSourceContact contact : tmpContactResults) + { + if(contact.getProvider().equals(provider.getProtocolProvider())) + { + contactResults.remove(contact); + fireContactRemoved(contact); + } + } + } + } + + /** + * Test equality of contact to chat room. This test recognizes that chat + * rooms may have equal names but connected to different accounts. + * + * @param contact the contact + * @param chatRoom the chat room + * @return returns true if they are equal, or false if + * they are different + */ + private boolean contactEqualsChatRoom(final ChatRoomSourceContact contact, + final ChatRoom chatRoom) + { + return contact.getProvider() == chatRoom.getParentProvider() + && chatRoom.getIdentifier().equals(contact.getContactAddress()); + } + + /** + * Test equality of contact to chat room wrapper. This method does not rely + * on a chat room instance, since that may not be available in case of + * removal. + * + * @param contact the contact + * @param chatRoomWrapper the chat room wrapper + * @return returns true if they are equal, or false if + * they are different. + */ + private boolean contactEqualsChatRoom(final ChatRoomSourceContact contact, + final ChatRoomWrapper chatRoomWrapper) + { + return contact.getProvider() == chatRoomWrapper.getParentProvider() + .getProtocolProvider() + && contact.getContactAddress().equals( + chatRoomWrapper.getChatRoomID()); + } + + /** + * Returns the index of the contact in the contact results list. + * @param contact the contact. + * @return the index of the contact in the contact results list. + */ + public synchronized int indexOf(ChatRoomSourceContact contact) + { + Iterator it = contactResults.iterator(); + int i = 0; + while(it.hasNext()) + { + if(contact.equals(it.next())) + { + return i; + } + i++; + } + return -1; + } + + /** + * Clears any listener we used. + */ + private void clearListeners() + { + mucService.removeChatRoomListChangeListener(this); + mucService.removeChatRoomProviderWrapperListener(this); + if(protolProviderRegistrationListener != null) + MUCActivator.bundleContext.removeServiceListener( + protolProviderRegistrationListener); + protolProviderRegistrationListener = null; + for(ProtocolProviderService pps : MUCActivator.getChatRoomProviders()) + { + removeQueryFromProviderPresenceListeners(pps); + } + } + + /** + * Cancels this ContactQuery. + * + * @see ContactQuery#cancel() + */ + public void cancel() + { + clearListeners(); + + super.cancel(); + } + + /** + * If query has status changed to cancel, let's clear listeners. + * @param status {@link ContactQuery#QUERY_CANCELED}, + * {@link ContactQuery#QUERY_COMPLETED} + */ + public void setStatus(int status) + { + if(status == QUERY_CANCELED) + clearListeners(); + + super.setStatus(status); + } + + @Override + public void addContactQueryListener(ContactQueryListener l) + { + super.addContactQueryListener(l); + contactQueryListenersCount++; + if(contactQueryListenersCount == 1) + { + initListeners(); + } + } + + @Override + public void removeContactQueryListener(ContactQueryListener l) + { + super.removeContactQueryListener(l); + contactQueryListenersCount--; + if(contactQueryListenersCount == 0) + { + clearListeners(); + } + } + + /** + * Listens for ProtocolProviderService registrations. + */ + private class ProtocolProviderRegListener + implements ServiceListener + { + /** + * Handles service change events. + */ + public void serviceChanged(ServiceEvent event) + { + ServiceReference serviceRef = event.getServiceReference(); + + // if the event is caused by a bundle being stopped, we don't want to + // know + if (serviceRef.getBundle().getState() == Bundle.STOPPING) + { + return; + } + + Object service = MUCActivator.bundleContext.getService(serviceRef); + + // we don't care if the source service is not a protocol provider + if (!(service instanceof ProtocolProviderService)) + { + return; + } + + switch (event.getType()) + { + case ServiceEvent.REGISTERED: + addQueryToProviderPresenceListeners( + (ProtocolProviderService) service); + break; + case ServiceEvent.UNREGISTERING: + removeQueryFromProviderPresenceListeners( + (ProtocolProviderService) service); + break; + } + } + } } diff --git a/src/net/java/sip/communicator/impl/muc/ChatRoomSourceContact.java b/src/net/java/sip/communicator/impl/muc/ChatRoomSourceContact.java index a659a6e..842cc15 100644 --- a/src/net/java/sip/communicator/impl/muc/ChatRoomSourceContact.java +++ b/src/net/java/sip/communicator/impl/muc/ChatRoomSourceContact.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,113 +15,113 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * Source contact for the chat rooms. - * - * @author Hristo Terezov - */ -public class ChatRoomSourceContact - extends BaseChatRoomSourceContact -{ - /** - * The protocol provider of the chat room associated with the contact. - */ - private boolean isAutoJoin; - - /** - * Constructs a new chat room source contact. - * - * @param chatRoomName the name of the chat room associated with the room. - * @param chatRoomID the id of the chat room associated with the room. - * @param query the query associated with the contact. - * @param pps the protocol provider of the contact. - * @param isAutoJoin the auto join state. - */ - public ChatRoomSourceContact(String chatRoomName, - String chatRoomID, ChatRoomQuery query, ProtocolProviderService pps, - boolean isAutoJoin) - { - super(chatRoomName, chatRoomID, query, pps); - - this.isAutoJoin = isAutoJoin; - - initContactProperties(getChatRoomStateByName()); - } - - /** - * Constructs new chat room source contact. - * - * @param chatRoom the chat room associated with the contact. - * @param query the query associated with the contact. - * @param isAutoJoin the auto join state - */ - public ChatRoomSourceContact(ChatRoom chatRoom, ChatRoomQuery query, - boolean isAutoJoin) - { - super(chatRoom.getName(), chatRoom.getIdentifier(), query, - chatRoom.getParentProvider()); - this.isAutoJoin = isAutoJoin; - - initContactProperties( - chatRoom.isJoined() - ? ChatRoomPresenceStatus.CHAT_ROOM_ONLINE - : ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); - - } - - /** - * Checks if the chat room associated with the contact is joined or not and - * returns it presence status. - * - * @return the presence status of the chat room associated with the contact. - */ - private PresenceStatus getChatRoomStateByName() - { - for(ChatRoom room : - getProvider().getOperationSet(OperationSetMultiUserChat.class) - .getCurrentlyJoinedChatRooms()) - { - if(room.getName().equals(getChatRoomName())) - { - return ChatRoomPresenceStatus.CHAT_ROOM_ONLINE; - } - } - return ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE; - } - - /** - * Returns the index of this source contact in its parent group. - * - * @return the index of this contact in its parent - */ - @Override - public int getIndex() - { - return ((ChatRoomQuery)parentQuery).indexOf(this); - } - - /** - * Returns the auto join state of the contact. - * - * @return the auto join state of the contact. - */ - public boolean isAutoJoin() - { - return isAutoJoin; - } - - /** - * Sets the auto join state of the contact. - * - * @param isAutoJoin the auto join state to be set. - */ - public void setAutoJoin(boolean isAutoJoin) - { - this.isAutoJoin = isAutoJoin; - } -} +package net.java.sip.communicator.impl.muc; + +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * Source contact for the chat rooms. + * + * @author Hristo Terezov + */ +public class ChatRoomSourceContact + extends BaseChatRoomSourceContact +{ + /** + * The protocol provider of the chat room associated with the contact. + */ + private boolean isAutoJoin; + + /** + * Constructs a new chat room source contact. + * + * @param chatRoomName the name of the chat room associated with the room. + * @param chatRoomID the id of the chat room associated with the room. + * @param query the query associated with the contact. + * @param pps the protocol provider of the contact. + * @param isAutoJoin the auto join state. + */ + public ChatRoomSourceContact(String chatRoomName, + String chatRoomID, ChatRoomQuery query, ProtocolProviderService pps, + boolean isAutoJoin) + { + super(chatRoomName, chatRoomID, query, pps); + + this.isAutoJoin = isAutoJoin; + + initContactProperties(getChatRoomStateByName()); + } + + /** + * Constructs new chat room source contact. + * + * @param chatRoom the chat room associated with the contact. + * @param query the query associated with the contact. + * @param isAutoJoin the auto join state + */ + public ChatRoomSourceContact(ChatRoom chatRoom, ChatRoomQuery query, + boolean isAutoJoin) + { + super(chatRoom.getName(), chatRoom.getIdentifier(), query, + chatRoom.getParentProvider()); + this.isAutoJoin = isAutoJoin; + + initContactProperties( + chatRoom.isJoined() + ? ChatRoomPresenceStatus.CHAT_ROOM_ONLINE + : ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE); + + } + + /** + * Checks if the chat room associated with the contact is joined or not and + * returns it presence status. + * + * @return the presence status of the chat room associated with the contact. + */ + private PresenceStatus getChatRoomStateByName() + { + for(ChatRoom room : + getProvider().getOperationSet(OperationSetMultiUserChat.class) + .getCurrentlyJoinedChatRooms()) + { + if(room.getName().equals(getChatRoomName())) + { + return ChatRoomPresenceStatus.CHAT_ROOM_ONLINE; + } + } + return ChatRoomPresenceStatus.CHAT_ROOM_OFFLINE; + } + + /** + * Returns the index of this source contact in its parent group. + * + * @return the index of this contact in its parent + */ + @Override + public int getIndex() + { + return ((ChatRoomQuery)parentQuery).indexOf(this); + } + + /** + * Returns the auto join state of the contact. + * + * @return the auto join state of the contact. + */ + public boolean isAutoJoin() + { + return isAutoJoin; + } + + /** + * Sets the auto join state of the contact. + * + * @param isAutoJoin the auto join state to be set. + */ + public void setAutoJoin(boolean isAutoJoin) + { + this.isAutoJoin = isAutoJoin; + } +} diff --git a/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java b/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java index 7c45b1d..0f4622d 100644 --- a/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java +++ b/src/net/java/sip/communicator/impl/muc/MUCCustomContactActionService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,845 +15,845 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import java.util.*; - -import net.java.sip.communicator.plugin.desktoputil.chat.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.customcontactactions.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; - -/** - * Implements CustomContactActionsService for MUC contact source. - * - * @author Hristo Terezov - */ -public class MUCCustomContactActionService - implements CustomContactActionsService -{ - /** - * List of custom menu items. - */ - private final List> mucActionMenuItems - = new LinkedList>(); - - /** - * List of custom actions. - */ - private final List> mucActions - = new LinkedList>(); - - /** - * - */ - private static final String OWNER_CANT_REMOVE_CHATROOM_PROPERTY - = "net.java.sip.communicator.impl.muc.OWNER_CANT_REMOVE_CHATROOM"; - - /** - * Array of names for the custom actions. - */ - private String[] actionsNames = { - "leave", - "join", - "autojoin", - "autojoin_pressed", - "destroy_chatroom" - }; - - /** - * Array of labels for the custom actions. - */ - private String[] actionsLabels = { - "service.gui.LEAVE", - "service.gui.JOIN", - "service.gui.JOIN_AUTOMATICALLY", - "service.gui.JOIN_AUTOMATICALLY", - "service.gui.DESTROY_CHATROOM" - }; - - /** - * Array of icons for the custom actions. - */ - private String[] actionsIcons = { - "service.gui.icons.LEAVE_ICON_BUTTON", - "service.gui.icons.JOIN_ICON_BUTTON", - "service.gui.icons.AUTOJOIN_ON_ICON_BUTTON", - "service.gui.icons.AUTOJOIN_OFF_ICON_BUTTON", - "service.gui.icons.DESTROY_ICON_BUTTON" - }; - - /** - * Array of rollover icons for the custom actions. - */ - private String[] actionsIconsRollover = { - "service.gui.icons.LEAVE_ICON_ROLLOVER_BUTTON", - "service.gui.icons.JOIN_ICON_ROLLOVER_BUTTON", - "service.gui.icons.AUTOJOIN_ON_ICON_ROLLOVER_BUTTON", - "service.gui.icons.AUTOJOIN_OFF_ICON_ROLLOVER_BUTTON", - "service.gui.icons.DESTROY_ICON_ROLLOVER_BUTTON" - }; - - /** - * Array of pressed icons for the custom actions. - */ - private String[] actionsIconsPressed = { - "service.gui.icons.LEAVE_ICON_PRESSED_BUTTON", - "service.gui.icons.JOIN_ICON_PRESSED_BUTTON", - "service.gui.icons.AUTOJOIN_ON_ICON_PRESSED_BUTTON", - "service.gui.icons.AUTOJOIN_OFF_ICON_PRESSED_BUTTON", - "service.gui.icons.DESTROY_ICON_PRESSED_BUTTON" - }; - - /** - * Array of names for the custom menu items. - */ - private String[] menuActionsNames = { - "open", - "join", - "join_as", - "leave", - "remove", - "change_nick", - "autojoin", - "autojoin_pressed", - "open_automatically", - "destroy_chatroom" - }; - - /** - * Array of labels for the custom menu items. - */ - private String[] menuActionsLabels = { - "service.gui.OPEN", - "service.gui.JOIN", - "service.gui.JOIN_AS", - "service.gui.LEAVE", - "service.gui.REMOVE", - "service.gui.CHANGE_NICK", - "service.gui.JOIN_AUTOMATICALLY", - "service.gui.DONT_JOIN_AUTOMATICALLY", - "service.gui.OPEN_AUTOMATICALLY", - "service.gui.DESTROY_CHATROOM" - }; - - /** - * Array of icons for the custom menu items. - */ - private String[] menuActionsIcons = { - "service.gui.icons.CHAT_ROOM_16x16_ICON", - "service.gui.icons.JOIN_ICON", - "service.gui.icons.JOIN_AS_ICON", - "service.gui.icons.LEAVE_ICON", - "service.gui.icons.REMOVE_CHAT_ICON", - "service.gui.icons.RENAME_16x16_ICON", - "service.gui.icons.AUTOJOIN", - "service.gui.icons.AUTOJOIN", - "service.gui.icons.OPEN_AUTOMATICALLY", - "service.gui.icons.DESTROY_CHATROOM" - }; - - /** - * A runnable that leaves the chat room. - */ - private MUCCustomActionRunnable leaveRunnable - = new MUCCustomActionRunnable() - { - - @Override - public void run() - { - ChatRoomWrapper leavedRoomWrapped - = MUCActivator.getMUCService().leaveChatRoom( - chatRoomWrapper); - if(leavedRoomWrapped != null) - MUCActivator.getUIService().closeChatRoomWindow( - leavedRoomWrapped); - } - }; - - /** - * A runnable that joins the chat room. - */ - private MUCCustomActionRunnable joinRunnable - = new MUCCustomActionRunnable() - { - - @Override - public void run() - { - String[] joinOptions; - String subject = null; - String nickName = null; - - nickName = - ConfigurationUtils.getChatRoomProperty( - chatRoomWrapper.getParentProvider() - .getProtocolProvider(), chatRoomWrapper - .getChatRoomID(), "userNickName"); - if(nickName == null) - { - joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( - chatRoomWrapper.getParentProvider() - .getProtocolProvider(), - chatRoomWrapper.getChatRoomID(), - MUCActivator.getGlobalDisplayDetailsService() - .getDisplayName(chatRoomWrapper.getParentProvider() - .getProtocolProvider())); - nickName = joinOptions[0]; - subject = joinOptions[1]; - } - - if (nickName != null) - MUCActivator.getMUCService().joinChatRoom(chatRoomWrapper, - nickName, null, subject); - } - }; - - /** - * A runnable that sets / unsets auto join setting of the chat room. - */ - private MUCCustomActionRunnable autoJoinRunnable - = new MUCCustomActionRunnable() - { - - @Override - public void run() - { - chatRoomWrapper.setAutoJoin(!chatRoomWrapper.isAutojoin()); - - } - }; - - /** - * A runnable that destroys the chat room. - */ - private MUCCustomActionRunnable destroyActionRunnable - = new MUCCustomActionRunnable() - { - - @Override - public void run() - { - String destroyOptions[] - = ChatRoomDestroyReasonDialog.getDestroyOptions(); - if(destroyOptions == null) - return; - - MUCActivator.getMUCService().destroyChatRoom(chatRoomWrapper, - destroyOptions[0], destroyOptions[1]); - - } - }; - - /** - * Array of MUCCustomActionRunnable objects for the custom menu - * items. They will be executed when the item is pressed. - */ - private MUCCustomActionRunnable[] actionsRunnable = { - leaveRunnable, - joinRunnable, - autoJoinRunnable, - autoJoinRunnable, - destroyActionRunnable - }; - - /** - * Array of MUCCustomActionRunnable objects for the custom menu - * items. They will be executed when the item is pressed. - */ - private MUCCustomActionRunnable[] menuActionsRunnable = { - new MUCCustomActionRunnable() - { - @Override - public void run() - { - MUCActivator.getMUCService().openChatRoom(chatRoomWrapper); - } - }, - joinRunnable, - new MUCCustomActionRunnable() - { - - @Override - public void run() - { - String[] joinOptions; - joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( - chatRoomWrapper.getParentProvider().getProtocolProvider(), - chatRoomWrapper.getChatRoomID(), - MUCActivator.getGlobalDisplayDetailsService() - .getDisplayName(chatRoomWrapper.getParentProvider() - .getProtocolProvider())); - if(joinOptions[0] == null) - return; - MUCActivator.getMUCService() - .joinChatRoom(chatRoomWrapper, joinOptions[0], null, - joinOptions[1]); - } - }, - leaveRunnable, - new MUCCustomActionRunnable() - { - - @Override - public void run() - { - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if (chatRoom != null) - { - ChatRoomWrapper leavedRoomWrapped - = MUCActivator.getMUCService().leaveChatRoom( - chatRoomWrapper); - if(leavedRoomWrapped != null) - MUCActivator.getUIService().closeChatRoomWindow( - leavedRoomWrapped); - } - - MUCActivator.getUIService().closeChatRoomWindow(chatRoomWrapper); - - MUCActivator.getMUCService().removeChatRoom(chatRoomWrapper); - } - }, - new MUCCustomActionRunnable() - { - - @Override - public void run() - { - ChatRoomJoinOptionsDialog.getJoinOptions(true, - chatRoomWrapper.getParentProvider().getProtocolProvider(), - chatRoomWrapper.getChatRoomID(), - MUCActivator.getGlobalDisplayDetailsService() - .getDisplayName(chatRoomWrapper.getParentProvider() - .getProtocolProvider())); - } - }, - autoJoinRunnable, - autoJoinRunnable, - new MUCCustomActionRunnable() - { - - @Override - public void run() - { - MUCActivator.getUIService().showChatRoomAutoOpenConfigDialog( - chatRoomWrapper.getParentProvider().getProtocolProvider(), - chatRoomWrapper.getChatRoomID()); - } - }, - destroyActionRunnable - }; - - /** - * Array of EnableChecker objects for the custom menu items. They - * are used to check if the item is enabled or disabled. - */ - private EnableChecker[] actionsEnabledCheckers = { - null, - new JoinEnableChecker(), - new JoinEnableChecker(), - new LeaveEnableChecker(), - null, - null, - null, - null, - null, - null - }; - - /** - * The resource management service instance. - */ - ResourceManagementService resources = MUCActivator.getResources(); - - /** - * Constructs the custom actions. - */ - public MUCCustomContactActionService() - { - for(int i = 0; i < menuActionsLabels.length; i++) - { - MUCActionMenuItems item - = new MUCActionMenuItems( - menuActionsNames[i], - menuActionsLabels[i], - menuActionsIcons[i], - menuActionsRunnable[i]); - mucActionMenuItems.add(item); - if(actionsEnabledCheckers[i] != null) - item.setEnabled(actionsEnabledCheckers[i]); - } - - for(int i = 0; i < actionsLabels.length; i++) - { - MUCAction item = new MUCAction( - actionsNames[i], - actionsLabels[i], - actionsIcons[i], - actionsIconsRollover[i], - actionsIconsPressed[i], - actionsRunnable[i]); - mucActions.add(item); - } - - } - - /** - * Returns the template class that this service has been initialized with - * - * @return the template class - */ - public Class getContactSourceClass() - { - return SourceContact.class; - } - - @Override - public Iterator> - getCustomContactActionsMenuItems() - { - return mucActionMenuItems.iterator(); - } - - - @Override - public Iterator> getCustomContactActions() - { - return mucActions.iterator(); - } - - /** - * Implements the MUC custom action. - */ - private class MUCAction - implements ContactAction - { - /** - * The text of the action. - */ - private String text; - - /** - * The icon of the action - */ - private byte[] icon; - - /** - * The icon that is shown when the action is pressed. - */ - private byte[] iconPressed; - - /** - * The runnable that is executed when the action is pressed. - */ - private MUCCustomActionRunnable actionPerformed; - - /** - * The icon that is shown when the mouse is over the action. - */ - private byte[] iconRollover; - - /** - * The name of the action. - */ - private String name; - - /** - * Constructs MUCAction instance. - * - * @param textKey the key used to retrieve the label for the action. - * @param iconKey the key used to retrieve the icon for the action. - * @param actionPerformed the action executed when the action is - * pressed. - * @param iconRolloverKey the key used to retrieve the rollover icon for - * the action. - * @param iconPressedKey the key used to retrieve the pressed icon for - * the action. - */ - public MUCAction(String name, String textKey, String iconKey, - String iconRolloverKey, String iconPressedKey, - MUCCustomActionRunnable actionPerformed) - { - this.name = name; - this.text = resources.getI18NString(textKey); - this.icon = resources.getImageInBytes(iconKey); - this.iconRollover = resources.getImageInBytes(iconRolloverKey); - this.iconPressed = resources.getImageInBytes(iconPressedKey); - this.actionPerformed = actionPerformed; - } - - @Override - public void actionPerformed(SourceContact actionSource, int x, int y) - throws OperationFailedException - { - if(!(actionSource instanceof ChatRoomSourceContact)) - return; - actionPerformed.setContact(actionSource); - new Thread(actionPerformed).start(); - } - - @Override - public byte[] getIcon() - { - return icon; - } - - @Override - public byte[] getRolloverIcon() - { - return iconRollover; - } - - @Override - public byte[] getPressedIcon() - { - return iconPressed; - } - - @Override - public String getToolTipText() - { - return text; - } - - @Override - public boolean isVisible(SourceContact actionSource) - { - if(actionSource instanceof ChatRoomSourceContact) - { - if(name.equals("leave")) - { - return actionsEnabledCheckers[3].check(actionSource); - } - else if(name.equals("join")) - { - return actionsEnabledCheckers[1].check(actionSource); - } - else if(name.equals("destroy_chatroom")) - { - ChatRoomSourceContact contact - = (ChatRoomSourceContact) actionSource; - ChatRoomWrapper room = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - if(room == null || room.getChatRoom() == null) - return false; - if(room.getChatRoom().getUserRole().equals(ChatRoomMemberRole.OWNER)) - return true; - return false; - } - else - { - ChatRoomSourceContact contact - = (ChatRoomSourceContact) actionSource; - ChatRoomWrapper room = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - if(room == null) - return false; - - if(name.equals("autojoin")) - return room.isAutojoin(); - else if(name.equals("autojoin_pressed")) - return !room.isAutojoin(); - } - } - return false; - } - - } - - /** - * Implements the MUC custom menu items. - */ - private class MUCActionMenuItems - implements ContactActionMenuItem - { - /** - * The label for the menu item. - */ - private String text; - - /** - * The the icon for the menu item. - */ - private byte[] image; - - /** - * The action executed when the menu item is pressed. - */ - private MUCCustomActionRunnable actionPerformed; - - /** - * Object that is used to check if the item is enabled or disabled. - */ - private EnableChecker enabled; - - /** - * The name of the custom action menu item. - */ - private String name; - - /** - * The mnemonic for the action. - */ - private char mnemonics; - - /** - * Constructs MUCActionMenuItems instance. - * - * @param textKey the key used to retrieve the label for the menu item. - * @param imageKey the key used to retrieve the icon for the menu item. - * @param actionPerformed the action executed when the menu item is - * pressed. - */ - public MUCActionMenuItems(String name, String textKey, String imageKey, - MUCCustomActionRunnable actionPerformed) - { - this.text = resources.getI18NString(textKey); - this.image = (imageKey == null)? null : - resources.getImageInBytes(imageKey); - this.actionPerformed = actionPerformed; - this.enabled = new EnableChecker(); - this.name = name; - this.mnemonics = resources.getI18nMnemonic(textKey); - } - - @Override - public void actionPerformed(SourceContact actionSource) - throws OperationFailedException - { - if(!(actionSource instanceof ChatRoomSourceContact)) - return; - actionPerformed.setContact(actionSource); - new Thread(actionPerformed).start(); - } - - @Override - public byte[] getIcon() - { - return image; - } - - - @Override - public String getText(SourceContact actionSource) - { - if(!(actionSource instanceof ChatRoomSourceContact)) - return ""; - - if(!name.equals("open_automatically")) - return text; - - String openAutomaticallyValue - = MUCService.getChatRoomAutoOpenOption( - ((ChatRoomSourceContact)actionSource).getProvider(), - ((ChatRoomSourceContact)actionSource).getChatRoomID()); - if(openAutomaticallyValue == null) - openAutomaticallyValue = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR; - String openAutomaticallyKey = MUCService.autoOpenConfigValuesTexts - .get(openAutomaticallyValue); - return "" + text + "...

    (" - + resources.getI18NString(openAutomaticallyKey) - + ")
    "; - } - - @Override - public boolean isVisible(SourceContact actionSource) - { - if(!(actionSource instanceof ChatRoomSourceContact)) - return false; - - ChatRoomSourceContact contact - = (ChatRoomSourceContact) actionSource; - ChatRoomWrapper room = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - if(name.equals("autojoin") || name.equals("autojoin_pressed")) - { - if(room == null) - return true; - - if(name.equals("autojoin")) - return !room.isAutojoin(); - - if(name.equals("autojoin_pressed")) - return room.isAutojoin(); - } - else if(name.equals("remove")) - { - if(room == null || room.getChatRoom() == null) - return true; - - boolean ownerCannotRemoveRoom - = MUCActivator.getConfigurationService().getBoolean( - OWNER_CANT_REMOVE_CHATROOM_PROPERTY, false); - - // when joined role will be owner or member - // when not joined and if we never has entered the room role - // will be guest, if we joined and left the room the role - // will be owner or member - if(room.getChatRoom().getUserRole().equals( - ChatRoomMemberRole.MEMBER)) - { - return true; - } - else - { - if(ownerCannotRemoveRoom) - return false; - else - return true; - } - } - else if(name.equals("destroy_chatroom")) - { - if(room == null || room.getChatRoom() == null) - return false; - if(room.getChatRoom().getUserRole().equals( - ChatRoomMemberRole.OWNER)) - return true; - return false; - } - return true; - } - - @Override - public char getMnemonics() - { - return mnemonics; - } - - @Override - public boolean isEnabled(SourceContact actionSource) - { - return enabled.check(actionSource); - } - - /** - * Sets EnabledChecker instance that will be used to check if - * the item should be enabled or disabled. - * - * @param enabled the EnabledChecker instance. - */ - public void setEnabled(EnableChecker enabled) - { - this.enabled = enabled; - } - - @Override - public boolean isCheckBox() - { - return false; - } - - @Override - public boolean isSelected(SourceContact contact) - { - ChatRoomWrapper chatRoomWrapper = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - if(chatRoomWrapper == null) - return false; - return chatRoomWrapper.isAutojoin(); - } - - } - - /** - * Checks if the menu item should be enabled or disabled. This is default - * implementation. Always returns that the item should be enabled. - */ - private static class EnableChecker - { - /** - * Checks if the menu item should be enabled or disabled. - * - * @param contact the contact associated with the menu item. - * @return always true - */ - public boolean check(SourceContact contact) - { - return true; - } - } - - /** - * Implements EnableChecker for the join menu items. - */ - private static class JoinEnableChecker - extends EnableChecker - { - /** - * Checks if the menu item should be enabled or disabled. - * - * @param contact the contact associated with the menu item. - * @return true if the item should be enabled and - * false if not. - */ - public boolean check(SourceContact contact) - { - ChatRoomWrapper chatRoomWrapper = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - ChatRoom chatRoom = null; - if(chatRoomWrapper != null) - { - chatRoom = chatRoomWrapper.getChatRoom(); - } - - if((chatRoom != null) && chatRoom.isJoined()) - return false; - return true; - } - } - - /** - * Implements EnableChecker for the leave menu item. - */ - private static class LeaveEnableChecker - extends JoinEnableChecker - { - /** - * Checks if the menu item should be enabled or disabled. - * - * @param contact the contact associated with the menu item. - * @return true if the item should be enabled and - * false if not. - */ - public boolean check(SourceContact contact) - { - return !super.check(contact); - } - } - - /** - * Implements base properties for the MUC menu items.These properties are - * used when the menu item is pressed. - */ - private abstract class MUCCustomActionRunnable - implements Runnable - { - /** - * The contact associated with the menu item. - */ - protected SourceContact contact; - - /** - * The contact associated with the menu item. - */ - protected ChatRoomWrapper chatRoomWrapper; - - /** - * Sets the source contact. - * @param contact the contact to set - */ - public void setContact(SourceContact contact) - { - this.contact = contact; - chatRoomWrapper = MUCActivator.getMUCService() - .findChatRoomWrapperFromSourceContact(contact); - } - } -} +package net.java.sip.communicator.impl.muc; + +import java.util.*; + +import net.java.sip.communicator.plugin.desktoputil.chat.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.customcontactactions.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; + +/** + * Implements CustomContactActionsService for MUC contact source. + * + * @author Hristo Terezov + */ +public class MUCCustomContactActionService + implements CustomContactActionsService +{ + /** + * List of custom menu items. + */ + private final List> mucActionMenuItems + = new LinkedList>(); + + /** + * List of custom actions. + */ + private final List> mucActions + = new LinkedList>(); + + /** + * + */ + private static final String OWNER_CANT_REMOVE_CHATROOM_PROPERTY + = "net.java.sip.communicator.impl.muc.OWNER_CANT_REMOVE_CHATROOM"; + + /** + * Array of names for the custom actions. + */ + private String[] actionsNames = { + "leave", + "join", + "autojoin", + "autojoin_pressed", + "destroy_chatroom" + }; + + /** + * Array of labels for the custom actions. + */ + private String[] actionsLabels = { + "service.gui.LEAVE", + "service.gui.JOIN", + "service.gui.JOIN_AUTOMATICALLY", + "service.gui.JOIN_AUTOMATICALLY", + "service.gui.DESTROY_CHATROOM" + }; + + /** + * Array of icons for the custom actions. + */ + private String[] actionsIcons = { + "service.gui.icons.LEAVE_ICON_BUTTON", + "service.gui.icons.JOIN_ICON_BUTTON", + "service.gui.icons.AUTOJOIN_ON_ICON_BUTTON", + "service.gui.icons.AUTOJOIN_OFF_ICON_BUTTON", + "service.gui.icons.DESTROY_ICON_BUTTON" + }; + + /** + * Array of rollover icons for the custom actions. + */ + private String[] actionsIconsRollover = { + "service.gui.icons.LEAVE_ICON_ROLLOVER_BUTTON", + "service.gui.icons.JOIN_ICON_ROLLOVER_BUTTON", + "service.gui.icons.AUTOJOIN_ON_ICON_ROLLOVER_BUTTON", + "service.gui.icons.AUTOJOIN_OFF_ICON_ROLLOVER_BUTTON", + "service.gui.icons.DESTROY_ICON_ROLLOVER_BUTTON" + }; + + /** + * Array of pressed icons for the custom actions. + */ + private String[] actionsIconsPressed = { + "service.gui.icons.LEAVE_ICON_PRESSED_BUTTON", + "service.gui.icons.JOIN_ICON_PRESSED_BUTTON", + "service.gui.icons.AUTOJOIN_ON_ICON_PRESSED_BUTTON", + "service.gui.icons.AUTOJOIN_OFF_ICON_PRESSED_BUTTON", + "service.gui.icons.DESTROY_ICON_PRESSED_BUTTON" + }; + + /** + * Array of names for the custom menu items. + */ + private String[] menuActionsNames = { + "open", + "join", + "join_as", + "leave", + "remove", + "change_nick", + "autojoin", + "autojoin_pressed", + "open_automatically", + "destroy_chatroom" + }; + + /** + * Array of labels for the custom menu items. + */ + private String[] menuActionsLabels = { + "service.gui.OPEN", + "service.gui.JOIN", + "service.gui.JOIN_AS", + "service.gui.LEAVE", + "service.gui.REMOVE", + "service.gui.CHANGE_NICK", + "service.gui.JOIN_AUTOMATICALLY", + "service.gui.DONT_JOIN_AUTOMATICALLY", + "service.gui.OPEN_AUTOMATICALLY", + "service.gui.DESTROY_CHATROOM" + }; + + /** + * Array of icons for the custom menu items. + */ + private String[] menuActionsIcons = { + "service.gui.icons.CHAT_ROOM_16x16_ICON", + "service.gui.icons.JOIN_ICON", + "service.gui.icons.JOIN_AS_ICON", + "service.gui.icons.LEAVE_ICON", + "service.gui.icons.REMOVE_CHAT_ICON", + "service.gui.icons.RENAME_16x16_ICON", + "service.gui.icons.AUTOJOIN", + "service.gui.icons.AUTOJOIN", + "service.gui.icons.OPEN_AUTOMATICALLY", + "service.gui.icons.DESTROY_CHATROOM" + }; + + /** + * A runnable that leaves the chat room. + */ + private MUCCustomActionRunnable leaveRunnable + = new MUCCustomActionRunnable() + { + + @Override + public void run() + { + ChatRoomWrapper leavedRoomWrapped + = MUCActivator.getMUCService().leaveChatRoom( + chatRoomWrapper); + if(leavedRoomWrapped != null) + MUCActivator.getUIService().closeChatRoomWindow( + leavedRoomWrapped); + } + }; + + /** + * A runnable that joins the chat room. + */ + private MUCCustomActionRunnable joinRunnable + = new MUCCustomActionRunnable() + { + + @Override + public void run() + { + String[] joinOptions; + String subject = null; + String nickName = null; + + nickName = + ConfigurationUtils.getChatRoomProperty( + chatRoomWrapper.getParentProvider() + .getProtocolProvider(), chatRoomWrapper + .getChatRoomID(), "userNickName"); + if(nickName == null) + { + joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( + chatRoomWrapper.getParentProvider() + .getProtocolProvider(), + chatRoomWrapper.getChatRoomID(), + MUCActivator.getGlobalDisplayDetailsService() + .getDisplayName(chatRoomWrapper.getParentProvider() + .getProtocolProvider())); + nickName = joinOptions[0]; + subject = joinOptions[1]; + } + + if (nickName != null) + MUCActivator.getMUCService().joinChatRoom(chatRoomWrapper, + nickName, null, subject); + } + }; + + /** + * A runnable that sets / unsets auto join setting of the chat room. + */ + private MUCCustomActionRunnable autoJoinRunnable + = new MUCCustomActionRunnable() + { + + @Override + public void run() + { + chatRoomWrapper.setAutoJoin(!chatRoomWrapper.isAutojoin()); + + } + }; + + /** + * A runnable that destroys the chat room. + */ + private MUCCustomActionRunnable destroyActionRunnable + = new MUCCustomActionRunnable() + { + + @Override + public void run() + { + String destroyOptions[] + = ChatRoomDestroyReasonDialog.getDestroyOptions(); + if(destroyOptions == null) + return; + + MUCActivator.getMUCService().destroyChatRoom(chatRoomWrapper, + destroyOptions[0], destroyOptions[1]); + + } + }; + + /** + * Array of MUCCustomActionRunnable objects for the custom menu + * items. They will be executed when the item is pressed. + */ + private MUCCustomActionRunnable[] actionsRunnable = { + leaveRunnable, + joinRunnable, + autoJoinRunnable, + autoJoinRunnable, + destroyActionRunnable + }; + + /** + * Array of MUCCustomActionRunnable objects for the custom menu + * items. They will be executed when the item is pressed. + */ + private MUCCustomActionRunnable[] menuActionsRunnable = { + new MUCCustomActionRunnable() + { + @Override + public void run() + { + MUCActivator.getMUCService().openChatRoom(chatRoomWrapper); + } + }, + joinRunnable, + new MUCCustomActionRunnable() + { + + @Override + public void run() + { + String[] joinOptions; + joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( + chatRoomWrapper.getParentProvider().getProtocolProvider(), + chatRoomWrapper.getChatRoomID(), + MUCActivator.getGlobalDisplayDetailsService() + .getDisplayName(chatRoomWrapper.getParentProvider() + .getProtocolProvider())); + if(joinOptions[0] == null) + return; + MUCActivator.getMUCService() + .joinChatRoom(chatRoomWrapper, joinOptions[0], null, + joinOptions[1]); + } + }, + leaveRunnable, + new MUCCustomActionRunnable() + { + + @Override + public void run() + { + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if (chatRoom != null) + { + ChatRoomWrapper leavedRoomWrapped + = MUCActivator.getMUCService().leaveChatRoom( + chatRoomWrapper); + if(leavedRoomWrapped != null) + MUCActivator.getUIService().closeChatRoomWindow( + leavedRoomWrapped); + } + + MUCActivator.getUIService().closeChatRoomWindow(chatRoomWrapper); + + MUCActivator.getMUCService().removeChatRoom(chatRoomWrapper); + } + }, + new MUCCustomActionRunnable() + { + + @Override + public void run() + { + ChatRoomJoinOptionsDialog.getJoinOptions(true, + chatRoomWrapper.getParentProvider().getProtocolProvider(), + chatRoomWrapper.getChatRoomID(), + MUCActivator.getGlobalDisplayDetailsService() + .getDisplayName(chatRoomWrapper.getParentProvider() + .getProtocolProvider())); + } + }, + autoJoinRunnable, + autoJoinRunnable, + new MUCCustomActionRunnable() + { + + @Override + public void run() + { + MUCActivator.getUIService().showChatRoomAutoOpenConfigDialog( + chatRoomWrapper.getParentProvider().getProtocolProvider(), + chatRoomWrapper.getChatRoomID()); + } + }, + destroyActionRunnable + }; + + /** + * Array of EnableChecker objects for the custom menu items. They + * are used to check if the item is enabled or disabled. + */ + private EnableChecker[] actionsEnabledCheckers = { + null, + new JoinEnableChecker(), + new JoinEnableChecker(), + new LeaveEnableChecker(), + null, + null, + null, + null, + null, + null + }; + + /** + * The resource management service instance. + */ + ResourceManagementService resources = MUCActivator.getResources(); + + /** + * Constructs the custom actions. + */ + public MUCCustomContactActionService() + { + for(int i = 0; i < menuActionsLabels.length; i++) + { + MUCActionMenuItems item + = new MUCActionMenuItems( + menuActionsNames[i], + menuActionsLabels[i], + menuActionsIcons[i], + menuActionsRunnable[i]); + mucActionMenuItems.add(item); + if(actionsEnabledCheckers[i] != null) + item.setEnabled(actionsEnabledCheckers[i]); + } + + for(int i = 0; i < actionsLabels.length; i++) + { + MUCAction item = new MUCAction( + actionsNames[i], + actionsLabels[i], + actionsIcons[i], + actionsIconsRollover[i], + actionsIconsPressed[i], + actionsRunnable[i]); + mucActions.add(item); + } + + } + + /** + * Returns the template class that this service has been initialized with + * + * @return the template class + */ + public Class getContactSourceClass() + { + return SourceContact.class; + } + + @Override + public Iterator> + getCustomContactActionsMenuItems() + { + return mucActionMenuItems.iterator(); + } + + + @Override + public Iterator> getCustomContactActions() + { + return mucActions.iterator(); + } + + /** + * Implements the MUC custom action. + */ + private class MUCAction + implements ContactAction + { + /** + * The text of the action. + */ + private String text; + + /** + * The icon of the action + */ + private byte[] icon; + + /** + * The icon that is shown when the action is pressed. + */ + private byte[] iconPressed; + + /** + * The runnable that is executed when the action is pressed. + */ + private MUCCustomActionRunnable actionPerformed; + + /** + * The icon that is shown when the mouse is over the action. + */ + private byte[] iconRollover; + + /** + * The name of the action. + */ + private String name; + + /** + * Constructs MUCAction instance. + * + * @param textKey the key used to retrieve the label for the action. + * @param iconKey the key used to retrieve the icon for the action. + * @param actionPerformed the action executed when the action is + * pressed. + * @param iconRolloverKey the key used to retrieve the rollover icon for + * the action. + * @param iconPressedKey the key used to retrieve the pressed icon for + * the action. + */ + public MUCAction(String name, String textKey, String iconKey, + String iconRolloverKey, String iconPressedKey, + MUCCustomActionRunnable actionPerformed) + { + this.name = name; + this.text = resources.getI18NString(textKey); + this.icon = resources.getImageInBytes(iconKey); + this.iconRollover = resources.getImageInBytes(iconRolloverKey); + this.iconPressed = resources.getImageInBytes(iconPressedKey); + this.actionPerformed = actionPerformed; + } + + @Override + public void actionPerformed(SourceContact actionSource, int x, int y) + throws OperationFailedException + { + if(!(actionSource instanceof ChatRoomSourceContact)) + return; + actionPerformed.setContact(actionSource); + new Thread(actionPerformed).start(); + } + + @Override + public byte[] getIcon() + { + return icon; + } + + @Override + public byte[] getRolloverIcon() + { + return iconRollover; + } + + @Override + public byte[] getPressedIcon() + { + return iconPressed; + } + + @Override + public String getToolTipText() + { + return text; + } + + @Override + public boolean isVisible(SourceContact actionSource) + { + if(actionSource instanceof ChatRoomSourceContact) + { + if(name.equals("leave")) + { + return actionsEnabledCheckers[3].check(actionSource); + } + else if(name.equals("join")) + { + return actionsEnabledCheckers[1].check(actionSource); + } + else if(name.equals("destroy_chatroom")) + { + ChatRoomSourceContact contact + = (ChatRoomSourceContact) actionSource; + ChatRoomWrapper room = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + if(room == null || room.getChatRoom() == null) + return false; + if(room.getChatRoom().getUserRole().equals(ChatRoomMemberRole.OWNER)) + return true; + return false; + } + else + { + ChatRoomSourceContact contact + = (ChatRoomSourceContact) actionSource; + ChatRoomWrapper room = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + if(room == null) + return false; + + if(name.equals("autojoin")) + return room.isAutojoin(); + else if(name.equals("autojoin_pressed")) + return !room.isAutojoin(); + } + } + return false; + } + + } + + /** + * Implements the MUC custom menu items. + */ + private class MUCActionMenuItems + implements ContactActionMenuItem + { + /** + * The label for the menu item. + */ + private String text; + + /** + * The the icon for the menu item. + */ + private byte[] image; + + /** + * The action executed when the menu item is pressed. + */ + private MUCCustomActionRunnable actionPerformed; + + /** + * Object that is used to check if the item is enabled or disabled. + */ + private EnableChecker enabled; + + /** + * The name of the custom action menu item. + */ + private String name; + + /** + * The mnemonic for the action. + */ + private char mnemonics; + + /** + * Constructs MUCActionMenuItems instance. + * + * @param textKey the key used to retrieve the label for the menu item. + * @param imageKey the key used to retrieve the icon for the menu item. + * @param actionPerformed the action executed when the menu item is + * pressed. + */ + public MUCActionMenuItems(String name, String textKey, String imageKey, + MUCCustomActionRunnable actionPerformed) + { + this.text = resources.getI18NString(textKey); + this.image = (imageKey == null)? null : + resources.getImageInBytes(imageKey); + this.actionPerformed = actionPerformed; + this.enabled = new EnableChecker(); + this.name = name; + this.mnemonics = resources.getI18nMnemonic(textKey); + } + + @Override + public void actionPerformed(SourceContact actionSource) + throws OperationFailedException + { + if(!(actionSource instanceof ChatRoomSourceContact)) + return; + actionPerformed.setContact(actionSource); + new Thread(actionPerformed).start(); + } + + @Override + public byte[] getIcon() + { + return image; + } + + + @Override + public String getText(SourceContact actionSource) + { + if(!(actionSource instanceof ChatRoomSourceContact)) + return ""; + + if(!name.equals("open_automatically")) + return text; + + String openAutomaticallyValue + = MUCService.getChatRoomAutoOpenOption( + ((ChatRoomSourceContact)actionSource).getProvider(), + ((ChatRoomSourceContact)actionSource).getChatRoomID()); + if(openAutomaticallyValue == null) + openAutomaticallyValue = MUCService.DEFAULT_AUTO_OPEN_BEHAVIOUR; + String openAutomaticallyKey = MUCService.autoOpenConfigValuesTexts + .get(openAutomaticallyValue); + return "" + text + "...
    (" + + resources.getI18NString(openAutomaticallyKey) + + ")
    "; + } + + @Override + public boolean isVisible(SourceContact actionSource) + { + if(!(actionSource instanceof ChatRoomSourceContact)) + return false; + + ChatRoomSourceContact contact + = (ChatRoomSourceContact) actionSource; + ChatRoomWrapper room = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + if(name.equals("autojoin") || name.equals("autojoin_pressed")) + { + if(room == null) + return true; + + if(name.equals("autojoin")) + return !room.isAutojoin(); + + if(name.equals("autojoin_pressed")) + return room.isAutojoin(); + } + else if(name.equals("remove")) + { + if(room == null || room.getChatRoom() == null) + return true; + + boolean ownerCannotRemoveRoom + = MUCActivator.getConfigurationService().getBoolean( + OWNER_CANT_REMOVE_CHATROOM_PROPERTY, false); + + // when joined role will be owner or member + // when not joined and if we never has entered the room role + // will be guest, if we joined and left the room the role + // will be owner or member + if(room.getChatRoom().getUserRole().equals( + ChatRoomMemberRole.MEMBER)) + { + return true; + } + else + { + if(ownerCannotRemoveRoom) + return false; + else + return true; + } + } + else if(name.equals("destroy_chatroom")) + { + if(room == null || room.getChatRoom() == null) + return false; + if(room.getChatRoom().getUserRole().equals( + ChatRoomMemberRole.OWNER)) + return true; + return false; + } + return true; + } + + @Override + public char getMnemonics() + { + return mnemonics; + } + + @Override + public boolean isEnabled(SourceContact actionSource) + { + return enabled.check(actionSource); + } + + /** + * Sets EnabledChecker instance that will be used to check if + * the item should be enabled or disabled. + * + * @param enabled the EnabledChecker instance. + */ + public void setEnabled(EnableChecker enabled) + { + this.enabled = enabled; + } + + @Override + public boolean isCheckBox() + { + return false; + } + + @Override + public boolean isSelected(SourceContact contact) + { + ChatRoomWrapper chatRoomWrapper = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + if(chatRoomWrapper == null) + return false; + return chatRoomWrapper.isAutojoin(); + } + + } + + /** + * Checks if the menu item should be enabled or disabled. This is default + * implementation. Always returns that the item should be enabled. + */ + private static class EnableChecker + { + /** + * Checks if the menu item should be enabled or disabled. + * + * @param contact the contact associated with the menu item. + * @return always true + */ + public boolean check(SourceContact contact) + { + return true; + } + } + + /** + * Implements EnableChecker for the join menu items. + */ + private static class JoinEnableChecker + extends EnableChecker + { + /** + * Checks if the menu item should be enabled or disabled. + * + * @param contact the contact associated with the menu item. + * @return true if the item should be enabled and + * false if not. + */ + public boolean check(SourceContact contact) + { + ChatRoomWrapper chatRoomWrapper = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + ChatRoom chatRoom = null; + if(chatRoomWrapper != null) + { + chatRoom = chatRoomWrapper.getChatRoom(); + } + + if((chatRoom != null) && chatRoom.isJoined()) + return false; + return true; + } + } + + /** + * Implements EnableChecker for the leave menu item. + */ + private static class LeaveEnableChecker + extends JoinEnableChecker + { + /** + * Checks if the menu item should be enabled or disabled. + * + * @param contact the contact associated with the menu item. + * @return true if the item should be enabled and + * false if not. + */ + public boolean check(SourceContact contact) + { + return !super.check(contact); + } + } + + /** + * Implements base properties for the MUC menu items.These properties are + * used when the menu item is pressed. + */ + private abstract class MUCCustomActionRunnable + implements Runnable + { + /** + * The contact associated with the menu item. + */ + protected SourceContact contact; + + /** + * The contact associated with the menu item. + */ + protected ChatRoomWrapper chatRoomWrapper; + + /** + * Sets the source contact. + * @param contact the contact to set + */ + public void setContact(SourceContact contact) + { + this.contact = contact; + chatRoomWrapper = MUCActivator.getMUCService() + .findChatRoomWrapperFromSourceContact(contact); + } + } +} diff --git a/src/net/java/sip/communicator/impl/muc/MUCServiceImpl.java b/src/net/java/sip/communicator/impl/muc/MUCServiceImpl.java index f6dd1c7..be02255 100644 --- a/src/net/java/sip/communicator/impl/muc/MUCServiceImpl.java +++ b/src/net/java/sip/communicator/impl/muc/MUCServiceImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1117 +15,1117 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import static net.java.sip.communicator.service.muc.ChatRoomWrapper.*; - -import java.util.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.plugin.desktoputil.chat.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.globalstatus.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; - -/** - * The MUCServiceImpl class implements the service for the chat rooms. - * - * @author Hristo Terezov - */ -public class MUCServiceImpl - extends MUCService -{ - - /** - * The list of persistent chat rooms. - */ - private final ChatRoomListImpl chatRoomList = new ChatRoomListImpl(); - - /** - * The Logger used by the MUCServiceImpl class and its - * instances for logging output. - */ - private static Logger logger = Logger.getLogger(MUCServiceImpl.class); - - /** - * Called to accept an incoming invitation. Adds the invitation chat room - * to the list of chat rooms and joins it. - * - * @param invitation the invitation to accept. - */ - public void acceptInvitation(ChatRoomInvitation invitation) - { - ChatRoom chatRoom = invitation.getTargetChatRoom(); - byte[] password = invitation.getChatRoomPassword(); - - String nickName = - ConfigurationUtils.getChatRoomProperty( - chatRoom.getParentProvider(), - chatRoom.getIdentifier(), "userNickName"); - if(nickName == null) - { - String[] joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( - true, - chatRoom.getParentProvider(), - chatRoom.getIdentifier(), - MUCActivator.getGlobalDisplayDetailsService() - .getDisplayName(chatRoom.getParentProvider())); - nickName = joinOptions[0]; - } - - joinChatRoom(chatRoom, nickName, password); - } - - /** - * Adds a change listener to the ChatRoomList. - * - * @param l the listener. - */ - public void addChatRoomListChangeListener(ChatRoomListChangeListener l) - { - chatRoomList.addChatRoomListChangeListener(l); - } - - /** - * Removes a change listener to the ChatRoomList. - * - * @param l the listener. - */ - public void removeChatRoomListChangeListener(ChatRoomListChangeListener l) - { - chatRoomList.removeChatRoomListChangeListener(l); - } - - /** - * Fires a ChatRoomListChangedEvent event. - * - * @param chatRoomWrapper the chat room. - * @param eventID the id of the event. - */ - public void fireChatRoomListChangedEvent( ChatRoomWrapper chatRoomWrapper, - int eventID) - { - chatRoomList.fireChatRoomListChangedEvent(chatRoomWrapper, eventID); - } - - /** - * Joins the given chat room with the given password and manages all the - * exceptions that could occur during the join process. - * - * @param chatRoomWrapper the chat room to join. - * @param nickName the nickname we choose for the given chat room. - * @param password the password. - * @param rememberPassword if true the password should be saved. - * @param isFirstAttempt is this the first attempt to join room, used - * to check whether to show some error messages - * @param subject the subject which will be set to the room after the user - * join successful. - */ - private void joinChatRoom( ChatRoomWrapper chatRoomWrapper, - String nickName, - byte[] password, - boolean rememberPassword, - boolean isFirstAttempt, - String subject) - { - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if(chatRoom == null) - { - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.WARNING"), - MUCActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getChatRoomName()})); - return; - } - - new JoinChatRoomTask( - (ChatRoomWrapperImpl)chatRoomWrapper, - nickName, - password, - rememberPassword, - isFirstAttempt, - subject) - .start(); - } - - /** - * Joins the given chat room with the given password and manages all the - * exceptions that could occur during the join process. - * - * @param chatRoomWrapper the chat room to join. - * @param nickName the nickname we choose for the given chat room. - * @param password the password. - */ - public void joinChatRoom( ChatRoomWrapper chatRoomWrapper, - String nickName, - byte[] password) - { - if (chatRoomWrapper.getChatRoom() == null) - { - chatRoomWrapper = createChatRoom( - chatRoomWrapper.getChatRoomName(), - chatRoomWrapper.getParentProvider().getProtocolProvider(), - new ArrayList(), "", false, false, true); - } - - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if(chatRoom == null) - { - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.WARNING"), - MUCActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getChatRoomName()})); - return; - } - - new JoinChatRoomTask( - (ChatRoomWrapperImpl)chatRoomWrapper, nickName, password) - .start(); - } - - /** - * Joins the given chat room with the given password and manages all the - * exceptions that could occur during the join process. - * - * @param chatRoomWrapper the chat room to join. - * @param nickName the nickname we choose for the given chat room. - * @param password the password. - * @param subject the subject which will be set to the room after the user - * join successful. - */ - public void joinChatRoom( ChatRoomWrapper chatRoomWrapper, - String nickName, - byte[] password, - String subject) - { - if (chatRoomWrapper.getChatRoom() == null) - { - chatRoomWrapper = createChatRoom( - chatRoomWrapper.getChatRoomName(), - chatRoomWrapper.getParentProvider().getProtocolProvider(), - new ArrayList(), "", false, false, true); - } - - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - if (chatRoom == null) - { - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.WARNING"), - MUCActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getChatRoomName()})); - - return; - } - - // join from add chat room dialog - - new JoinChatRoomTask( - (ChatRoomWrapperImpl) chatRoomWrapper, - nickName, - password, - subject) - .start(); - } - - - /** - * Join chat room. - * @param chatRoomWrapper - */ - public void joinChatRoom(ChatRoomWrapper chatRoomWrapper) - { - if (chatRoomWrapper.getChatRoom() == null) - { - chatRoomWrapper = createChatRoom( - chatRoomWrapper.getChatRoomName(), - chatRoomWrapper.getParentProvider().getProtocolProvider(), - new ArrayList(), "", false, false, true); - } - - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if(chatRoom == null) - { - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.WARNING"), - MUCActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getChatRoomName()})); - - return; - } - - new JoinChatRoomTask((ChatRoomWrapperImpl)chatRoomWrapper, null, null) - .start(); - } - - - /** - * Joins the given chat room and manages all the exceptions that could - * occur during the join process. - * - * @param chatRoom the chat room to join - * @param nickname the nickname we're using to join - * @param password the password we're using to join - */ - public void joinChatRoom( ChatRoom chatRoom, - String nickname, - byte[] password) - { - ChatRoomWrapper chatRoomWrapper - = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - - if(chatRoomWrapper == null) - { - ChatRoomProviderWrapper parentProvider - = chatRoomList.findServerWrapperFromProvider( - chatRoom.getParentProvider()); - - chatRoomWrapper - = new ChatRoomWrapperImpl(parentProvider, chatRoom); - - chatRoomList.addChatRoom(chatRoomWrapper); - - } - - this.joinChatRoom(chatRoomWrapper, nickname, password); - } - - /** - * Joins the room with the given name though the given chat room provider. - * - * @param chatRoomName the name of the room to join. - * @param chatRoomProvider the chat room provider to join through. - */ - public void joinChatRoom( String chatRoomName, - ChatRoomProviderWrapper chatRoomProvider) - { - OperationSetMultiUserChat groupChatOpSet - = chatRoomProvider - .getProtocolProvider().getOperationSet( - OperationSetMultiUserChat.class); - - ChatRoom chatRoom = null; - try - { - chatRoom = groupChatOpSet.findRoom(chatRoomName); - } - catch (Exception e) - { - if (logger.isTraceEnabled()) - logger.trace("Un exception occurred while searching for room:" - + chatRoomName, e); - } - - if (chatRoom != null) - { - ChatRoomWrapper chatRoomWrapper - = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - - if(chatRoomWrapper == null) - { - ChatRoomProviderWrapper parentProvider - = chatRoomList - .findServerWrapperFromProvider( - chatRoom.getParentProvider()); - - chatRoomWrapper - = new ChatRoomWrapperImpl(parentProvider, chatRoom); - - chatRoomList.addChatRoom(chatRoomWrapper); - - fireChatRoomListChangedEvent( - chatRoomWrapper, - ChatRoomListChangeEvent.CHAT_ROOM_ADDED); - } - joinChatRoom(chatRoomWrapper); - } - else - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.ERROR"), - MUCActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_NOT_EXIST", - new String[]{chatRoomName, - chatRoomProvider.getProtocolProvider() - .getAccountID().getService()})); - } - - - /** - * Creates a chat room, by specifying the chat room name, the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param roomName the name of the room - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param persistent is the room persistent - * @param isPrivate whether the room will be private or public. - * @return the ChatRoomWrapper corresponding to the created room - */ - public ChatRoomWrapper createChatRoom( - String roomName, - ProtocolProviderService protocolProvider, - Collection contacts, - String reason, - boolean persistent, - boolean isPrivate) - { - return createChatRoom( - roomName, protocolProvider, contacts, reason, true, persistent, - isPrivate); - } - - /** - * Creates a chat room, by specifying the chat room name, the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param roomName the name of the room - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param persistent is the room persistent - * @return the ChatRoomWrapper corresponding to the created room - */ - public ChatRoomWrapper createChatRoom( - String roomName, - ProtocolProviderService protocolProvider, - Collection contacts, - String reason, - boolean persistent) - { - return createChatRoom( - roomName, protocolProvider, contacts, reason, true, persistent, - false); - } - - /** - * Creates a chat room, by specifying the chat room name, the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param roomName the name of the room - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param join whether we should join the room after creating it. - * @param persistent whether the newly created room will be persistent. - * @param isPrivate whether the room will be private or public. - * @return the ChatRoomWrapper corresponding to the created room or - * null if the protocol fails to create the chat room. - */ - public ChatRoomWrapper createChatRoom( - String roomName, - ProtocolProviderService protocolProvider, - Collection contacts, - String reason, - boolean join, - boolean persistent, - boolean isPrivate) - { - ChatRoomWrapper chatRoomWrapper = null; - OperationSetMultiUserChat groupChatOpSet - = protocolProvider.getOperationSet(OperationSetMultiUserChat.class); - - // If there's no group chat operation set we have nothing to do here. - if (groupChatOpSet == null) - return null; - - ChatRoom chatRoom = null; - try - { - - - HashMap roomProperties = - new HashMap(); - roomProperties.put("isPrivate", isPrivate); - chatRoom = groupChatOpSet.createChatRoom(roomName, roomProperties); - - if(join) - { - chatRoom.join(); - - for(String contact : contacts) - chatRoom.invite(contact, reason); - } - } - catch (OperationFailedException ex) - { - logger.error("Failed to create chat room.", ex); - - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.ERROR"), - MUCActivator.getResources().getI18NString( - "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{protocolProvider.getProtocolDisplayName()}), - ex); - } - catch (OperationNotSupportedException ex) - { - logger.error("Failed to create chat room.", ex); - - MUCActivator.getAlertUIService().showAlertDialog( - MUCActivator.getResources().getI18NString("service.gui.ERROR"), - MUCActivator.getResources().getI18NString( - "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{protocolProvider.getProtocolDisplayName()}), - ex); - } - - if(chatRoom != null) - { - ChatRoomProviderWrapper parentProvider - = chatRoomList.findServerWrapperFromProvider(protocolProvider); - - // if there is the same room ids don't add new wrapper as old one - // maybe already created - chatRoomWrapper = - chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - - if(chatRoomWrapper == null) - { - chatRoomWrapper - = new ChatRoomWrapperImpl(parentProvider, chatRoom); - chatRoomWrapper.setPersistent(persistent); - chatRoomList.addChatRoom(chatRoomWrapper); - } - } - - return chatRoomWrapper; - } - - /** - * Creates a private chat room, by specifying the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param persistent is the room persistent - * @return the ChatRoomWrapper corresponding to the created room - */ - public ChatRoomWrapper createPrivateChatRoom( - ProtocolProviderService protocolProvider, - Collection contacts, - String reason, - boolean persistent) - { - return this.createChatRoom( - null, protocolProvider, contacts, reason, persistent, true); - } - - - /** - * Returns existing chat rooms for the given chatRoomProvider. - * @param chatRoomProvider the ChatRoomProviderWrapper, which - * chat rooms we're looking for - * @return existing chat rooms for the given chatRoomProvider - */ - public List getExistingChatRooms( - ChatRoomProviderWrapper chatRoomProvider) - { - if (chatRoomProvider == null) - return null; - - ProtocolProviderService protocolProvider - = chatRoomProvider.getProtocolProvider(); - - if (protocolProvider == null) - return null; - - OperationSetMultiUserChat groupChatOpSet - = protocolProvider - .getOperationSet(OperationSetMultiUserChat.class); - - if (groupChatOpSet == null) - return null; - - List chatRooms = null; - try - { - chatRooms = groupChatOpSet.getExistingChatRooms(); - } - catch (OperationFailedException e) - { - if (logger.isTraceEnabled()) - logger.trace("Failed to obtain existing chat rooms for server: " - + protocolProvider.getAccountID().getService(), e); - } - catch (OperationNotSupportedException e) - { - if (logger.isTraceEnabled()) - logger.trace("Failed to obtain existing chat rooms for server: " - + protocolProvider.getAccountID().getService(), e); - } - - return chatRooms; - } - - /** - * Rejects the given invitation with the specified reason. - * - * @param multiUserChatOpSet the operation set to use for rejecting the - * invitation - * @param invitation the invitation to reject - * @param reason the reason for the rejection - */ - public void rejectInvitation( OperationSetMultiUserChat multiUserChatOpSet, - ChatRoomInvitation invitation, - String reason) - { - multiUserChatOpSet.rejectInvitation(invitation, reason); - } - - /** - * Leaves the given chat room. - * - * @param chatRoomWrapper the chat room to leave. - * @return ChatRoomWrapper instance associated with the chat room. - */ - public ChatRoomWrapper leaveChatRoom(ChatRoomWrapper chatRoomWrapper) - { - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - if (chatRoom == null) - { - ResourceManagementService resources = MUCActivator.getResources(); - - MUCActivator.getAlertUIService().showAlertDialog( - resources.getI18NString("service.gui.WARNING"), - resources - .getI18NString( - "service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED")); - - return null; - } - - if (chatRoom.isJoined()) - chatRoom.leave(); - - ChatRoomWrapper existChatRoomWrapper - = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - - if(existChatRoomWrapper == null) - return null; - - // We save the choice of the user, before the chat room is really - // joined, because even the join fails we want the next time when - // we login to join this chat room automatically. - ConfigurationUtils.updateChatRoomStatus( - chatRoomWrapper.getParentProvider().getProtocolProvider(), - chatRoomWrapper.getChatRoomID(), - GlobalStatusEnum.OFFLINE_STATUS); - - return existChatRoomWrapper; - } - - /** - * Joins a chat room in an asynchronous way. - */ - private class JoinChatRoomTask - extends Thread - { - private final ChatRoomWrapperImpl chatRoomWrapper; - - private final String nickName; - - private final byte[] password; - - private final boolean rememberPassword; - - private final boolean isFirstAttempt; - - private final String subject; - - private ResourceManagementService resources - = MUCActivator.getResources(); - - JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, - String nickName, - byte[] password, - boolean rememberPassword, - boolean isFirstAttempt, - String subject) - { - this.chatRoomWrapper = chatRoomWrapper; - this.nickName = nickName; - this.isFirstAttempt = isFirstAttempt; - this.subject = subject; - - if(password == null) - { - String passString = chatRoomWrapper.loadPassword(); - if(passString != null) - { - this.password = passString.getBytes(); - } - else - { - this.password = null; - } - } - else - { - this.password = password; - } - this.rememberPassword = rememberPassword; - } - - JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, - String nickName, - byte[] password) - { - this(chatRoomWrapper, nickName, password, false, true, null); - } - - JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, - String nickName, - byte[] password, - String subject) - { - this(chatRoomWrapper, nickName, password, false, true, subject); - } - - /** - * @override {@link Thread}{@link #run()} to perform all asynchronous - * tasks. - */ - @Override - public void run() - { - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); - - try - { - if(password != null && password.length > 0) - chatRoom.joinAs(nickName, password); - else if (nickName != null) - chatRoom.joinAs(nickName); - else - chatRoom.join(); - - done(JOIN_SUCCESS_PROP); - } - catch (OperationFailedException e) - { - if (logger.isTraceEnabled()) - logger.trace("Failed to join chat room: " - + chatRoom.getName(), e); - - switch (e.getErrorCode()) - { - case OperationFailedException.AUTHENTICATION_FAILED: - done(JOIN_AUTHENTICATION_FAILED_PROP); - break; - case OperationFailedException.REGISTRATION_REQUIRED: - done(JOIN_REGISTRATION_REQUIRED_PROP); - break; - case OperationFailedException.PROVIDER_NOT_REGISTERED: - done(JOIN_PROVIDER_NOT_REGISTERED_PROP); - break; - case OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS: - done(JOIN_SUBSCRIPTION_ALREADY_EXISTS_PROP); - break; - default: - done(JOIN_UNKNOWN_ERROR_PROP); - } - } - } - - /** - * Performs UI changes after the chat room join task has finished. - * @param returnCode the result code from the chat room join task. - */ - private void done(String returnCode) - { - ConfigurationUtils.updateChatRoomStatus( - chatRoomWrapper.getParentProvider().getProtocolProvider(), - chatRoomWrapper.getChatRoomID(), - GlobalStatusEnum.ONLINE_STATUS); - - String errorMessage = null; - if(JOIN_AUTHENTICATION_FAILED_PROP.equals(returnCode)) - { - chatRoomWrapper.removePassword(); - - AuthenticationWindowService authWindowsService - = ServiceUtils.getService( - MUCActivator.bundleContext, - AuthenticationWindowService.class); - - AuthenticationWindowService.AuthenticationWindow authWindow = - authWindowsService.create( - null, null, null, false, - chatRoomWrapper.isPersistent(), - AuthenticationWindow.getAuthenticationWindowIcon( - chatRoomWrapper.getParentProvider() - .getProtocolProvider()), - resources.getI18NString( - "service.gui.AUTHENTICATION_WINDOW_TITLE", - new String[]{chatRoomWrapper.getParentProvider() - .getName()}), - resources.getI18NString( - "service.gui.CHAT_ROOM_REQUIRES_PASSWORD", - new String[]{ - chatRoomWrapper.getChatRoomName()}), - "", null, - isFirstAttempt ? - null : - resources.getI18NString( - "service.gui.AUTHENTICATION_FAILED", - new String[]{chatRoomWrapper.getChatRoomName()}), - null); - - authWindow.setVisible(true); - - if (!authWindow.isCanceled()) - { - joinChatRoom( - chatRoomWrapper, - nickName, - new String(authWindow.getPassword()).getBytes(), - authWindow.isRememberPassword(), - false, - subject); - } - } - else if(JOIN_REGISTRATION_REQUIRED_PROP.equals(returnCode)) - { - errorMessage - = resources - .getI18NString( - "service.gui.CHAT_ROOM_REGISTRATION_REQUIRED", - new String[]{chatRoomWrapper.getChatRoomName()}); - } - else if(JOIN_PROVIDER_NOT_REGISTERED_PROP.equals(returnCode)) - { - errorMessage - = resources - .getI18NString("service.gui.CHAT_ROOM_NOT_CONNECTED", - new String[]{chatRoomWrapper.getChatRoomName()}); - } - else if(JOIN_SUBSCRIPTION_ALREADY_EXISTS_PROP.equals(returnCode)) - { - errorMessage - = resources - .getI18NString("service.gui.CHAT_ROOM_ALREADY_JOINED", - new String[]{chatRoomWrapper.getChatRoomName()}); - } - else - { - errorMessage - = resources - .getI18NString("service.gui.FAILED_TO_JOIN_CHAT_ROOM", - new String[]{chatRoomWrapper.getChatRoomName()}); - } - - if (!JOIN_SUCCESS_PROP.equals(returnCode) && - !JOIN_AUTHENTICATION_FAILED_PROP.equals(returnCode)) - { - MUCActivator.getAlertUIService().showAlertPopup( - resources.getI18NString("service.gui.ERROR"), errorMessage); - } - - if (JOIN_SUCCESS_PROP.equals(returnCode)) - { - if(rememberPassword) - { - chatRoomWrapper.savePassword(new String(password)); - } - - if(subject != null) - { - try - { - chatRoomWrapper.getChatRoom().setSubject(subject); - } - catch(OperationFailedException ex) - { - logger.warn("Failed to set subject."); - } - } - } - - chatRoomWrapper.firePropertyChange(returnCode); - } - } - - /** - * Finds the ChatRoomWrapper instance associated with the - * source contact. - * @param contact the source contact. - * @return the ChatRoomWrapper instance. - */ - public ChatRoomWrapper findChatRoomWrapperFromSourceContact( - SourceContact contact) - { - if(!(contact instanceof ChatRoomSourceContact)) - return null; - ChatRoomSourceContact chatRoomContact = (ChatRoomSourceContact) contact; - return chatRoomList.findChatRoomWrapperFromChatRoomID( - chatRoomContact.getChatRoomID(), chatRoomContact.getProvider()); - } - - /** - * Finds the ChatRoomWrapper instance associated with the - * chat room. - * @param chatRoomID the id of the chat room. - * @param pps the provider of the chat room. - * @return the ChatRoomWrapper instance. - */ - public ChatRoomWrapper findChatRoomWrapperFromChatRoomID(String chatRoomID, - ProtocolProviderService pps) - { - return chatRoomList.findChatRoomWrapperFromChatRoomID(chatRoomID, pps); - } - - /** - * Searches for chat room wrapper in chat room list by chat room. - * - * @param chatRoom the chat room. - * @param create if true and the chat room wrapper is not found new - * chatRoomWrapper is created. - * @return found chat room wrapper or the created chat room wrapper. - */ - @Override - public ChatRoomWrapper getChatRoomWrapperByChatRoom(ChatRoom chatRoom, - boolean create) - { - ChatRoomWrapper chatRoomWrapper - = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - - if ((chatRoomWrapper == null) && create) - { - ChatRoomProviderWrapper parentProvider - = chatRoomList.findServerWrapperFromProvider( - chatRoom.getParentProvider()); - - chatRoomWrapper - = new ChatRoomWrapperImpl( - parentProvider, chatRoom); - - chatRoomList.addChatRoom(chatRoomWrapper); - } - return chatRoomWrapper; - } - - /** - * Goes through the locally stored chat rooms list and for each - * {@link ChatRoomWrapper} tries to find the corresponding server stored - * {@link ChatRoom} in the specified operation set. Joins automatically all - * found chat rooms. - * - * @param protocolProvider the protocol provider for the account to - * synchronize - * @param opSet the multi user chat operation set, which give us access to - * chat room server - */ - public void synchronizeOpSetWithLocalContactList( - ProtocolProviderService protocolProvider, - final OperationSetMultiUserChat opSet) - { - ChatRoomProviderWrapper chatRoomProvider - = findServerWrapperFromProvider(protocolProvider); - - if(chatRoomProvider == null) - { - chatRoomProvider = chatRoomList.addRegisteredChatProvider(protocolProvider); - } - - if (chatRoomProvider != null) - { - chatRoomProvider.synchronizeProvider(); - } - } - - /** - * Returns an iterator to the list of chat room providers. - * - * @return an iterator to the list of chat room providers. - */ - public Iterator getChatRoomProviders() - { - return chatRoomList.getChatRoomProviders(); - } - - /** - * Removes the given ChatRoom from the list of all chat rooms. - * - * @param chatRoomWrapper the ChatRoomWrapper to remove - */ - public void removeChatRoom(ChatRoomWrapper chatRoomWrapper) - { - chatRoomList.removeChatRoom(chatRoomWrapper); - } - - /** - * Destroys the given ChatRoom from the list of all chat rooms. - * - * @param chatRoomWrapper the ChatRoomWrapper to be destroyed. - * @param reason the reason for destroying. - * @param alternateAddress the alternate address. - */ - public void destroyChatRoom(ChatRoomWrapper chatRoomWrapper, - String reason, String alternateAddress) - { - if(chatRoomWrapper.getChatRoom().destroy(reason, alternateAddress)) - { - MUCActivator.getUIService().closeChatRoomWindow( - chatRoomWrapper); - chatRoomList.removeChatRoom(chatRoomWrapper); - } - else - { - // if we leave a chat room which is not persistent - // the room can be destroyed on the server, and error is returned - // when we try to destroy it not-authorized(401) - if(!chatRoomWrapper.getChatRoom().isPersistent() - && !chatRoomWrapper.getChatRoom().isJoined()) - { - chatRoomList.removeChatRoom(chatRoomWrapper); - } - } - - } - - /** - * Adds a ChatRoomProviderWrapperListener to the listener list. - * - * @param listener the ChatRoomProviderWrapperListener to be added - */ - public void addChatRoomProviderWrapperListener( - ChatRoomProviderWrapperListener listener) - { - chatRoomList.addChatRoomProviderWrapperListener(listener); - } - - /** - * Removes the ChatRoomProviderWrapperListener to the listener list. - * - * @param listener the ChatRoomProviderWrapperListener to be removed - */ - public void removeChatRoomProviderWrapperListener( - ChatRoomProviderWrapperListener listener) - { - chatRoomList.removeChatRoomProviderWrapperListener(listener); - } - - /** - * Returns the ChatRoomProviderWrapper that correspond to the - * given ProtocolProviderService. If the list doesn't contain a - * corresponding wrapper - returns null. - * - * @param protocolProvider the protocol provider that we're looking for - * @return the ChatRoomProvider object corresponding to - * the given ProtocolProviderService - */ - public ChatRoomProviderWrapper findServerWrapperFromProvider( - ProtocolProviderService protocolProvider) - { - return chatRoomList.findServerWrapperFromProvider(protocolProvider); - } - - /** - * Returns the ChatRoomWrapper that correspond to the given - * ChatRoom. If the list of chat rooms doesn't contain a - * corresponding wrapper - returns null. - * - * @param chatRoom the ChatRoom that we're looking for - * @return the ChatRoomWrapper object corresponding to the given - * ChatRoom - */ - public ChatRoomWrapper findChatRoomWrapperFromChatRoom(ChatRoom chatRoom) - { - return chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); - } - - /** - * Opens a chat window for the chat room. - * - * @param room the chat room. - */ - public void openChatRoom(ChatRoomWrapper room) - { - if (room.getChatRoom() == null) - { - room = createChatRoom( - room.getChatRoomName(), - room.getParentProvider().getProtocolProvider(), - new ArrayList(),"", false, false, true); - - // leave the chatroom because getChatRoom().isJoined() returns true - // otherwise - if (room.getChatRoom().isJoined()) - room.getChatRoom().leave(); - - } - - if(!room.getChatRoom().isJoined()) - { - String savedNick = - ConfigurationUtils.getChatRoomProperty(room - .getParentProvider().getProtocolProvider(), room - .getChatRoomID(), "userNickName"); - String subject = null; - - if (savedNick == null) - { - String[] joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( - room.getParentProvider().getProtocolProvider(), - room.getChatRoomID(), - MUCActivator.getGlobalDisplayDetailsService() - .getDisplayName( - room.getParentProvider().getProtocolProvider())); - savedNick = joinOptions[0]; - subject = joinOptions[1]; - - } - - if (savedNick != null) - { - joinChatRoom(room, savedNick, null, - subject); - } - else - return; - } - - MUCActivator.getUIService().openChatRoomWindow(room); - } - - /** - * Returns instance of the ServerChatRoomContactSourceService - * contact source. - * @return instance of the ServerChatRoomContactSourceService - * contact source. - */ - public ContactSourceService getServerChatRoomsContactSourceForProvider( - ChatRoomProviderWrapper pps) - { - return new ServerChatRoomContactSourceService(pps); - } - - /** - * Returns true if the contact is ChatRoomSourceContact - * - * @param contact the contact - * @return true if the contact is ChatRoomSourceContact - */ - public boolean isMUCSourceContact(SourceContact contact) - { - return (contact instanceof ChatRoomSourceContact); - } -} +package net.java.sip.communicator.impl.muc; + +import static net.java.sip.communicator.service.muc.ChatRoomWrapper.*; + +import java.util.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.desktoputil.chat.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.globalstatus.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; + +/** + * The MUCServiceImpl class implements the service for the chat rooms. + * + * @author Hristo Terezov + */ +public class MUCServiceImpl + extends MUCService +{ + + /** + * The list of persistent chat rooms. + */ + private final ChatRoomListImpl chatRoomList = new ChatRoomListImpl(); + + /** + * The Logger used by the MUCServiceImpl class and its + * instances for logging output. + */ + private static Logger logger = Logger.getLogger(MUCServiceImpl.class); + + /** + * Called to accept an incoming invitation. Adds the invitation chat room + * to the list of chat rooms and joins it. + * + * @param invitation the invitation to accept. + */ + public void acceptInvitation(ChatRoomInvitation invitation) + { + ChatRoom chatRoom = invitation.getTargetChatRoom(); + byte[] password = invitation.getChatRoomPassword(); + + String nickName = + ConfigurationUtils.getChatRoomProperty( + chatRoom.getParentProvider(), + chatRoom.getIdentifier(), "userNickName"); + if(nickName == null) + { + String[] joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( + true, + chatRoom.getParentProvider(), + chatRoom.getIdentifier(), + MUCActivator.getGlobalDisplayDetailsService() + .getDisplayName(chatRoom.getParentProvider())); + nickName = joinOptions[0]; + } + + joinChatRoom(chatRoom, nickName, password); + } + + /** + * Adds a change listener to the ChatRoomList. + * + * @param l the listener. + */ + public void addChatRoomListChangeListener(ChatRoomListChangeListener l) + { + chatRoomList.addChatRoomListChangeListener(l); + } + + /** + * Removes a change listener to the ChatRoomList. + * + * @param l the listener. + */ + public void removeChatRoomListChangeListener(ChatRoomListChangeListener l) + { + chatRoomList.removeChatRoomListChangeListener(l); + } + + /** + * Fires a ChatRoomListChangedEvent event. + * + * @param chatRoomWrapper the chat room. + * @param eventID the id of the event. + */ + public void fireChatRoomListChangedEvent( ChatRoomWrapper chatRoomWrapper, + int eventID) + { + chatRoomList.fireChatRoomListChangedEvent(chatRoomWrapper, eventID); + } + + /** + * Joins the given chat room with the given password and manages all the + * exceptions that could occur during the join process. + * + * @param chatRoomWrapper the chat room to join. + * @param nickName the nickname we choose for the given chat room. + * @param password the password. + * @param rememberPassword if true the password should be saved. + * @param isFirstAttempt is this the first attempt to join room, used + * to check whether to show some error messages + * @param subject the subject which will be set to the room after the user + * join successful. + */ + private void joinChatRoom( ChatRoomWrapper chatRoomWrapper, + String nickName, + byte[] password, + boolean rememberPassword, + boolean isFirstAttempt, + String subject) + { + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if(chatRoom == null) + { + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.WARNING"), + MUCActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getChatRoomName()})); + return; + } + + new JoinChatRoomTask( + (ChatRoomWrapperImpl)chatRoomWrapper, + nickName, + password, + rememberPassword, + isFirstAttempt, + subject) + .start(); + } + + /** + * Joins the given chat room with the given password and manages all the + * exceptions that could occur during the join process. + * + * @param chatRoomWrapper the chat room to join. + * @param nickName the nickname we choose for the given chat room. + * @param password the password. + */ + public void joinChatRoom( ChatRoomWrapper chatRoomWrapper, + String nickName, + byte[] password) + { + if (chatRoomWrapper.getChatRoom() == null) + { + chatRoomWrapper = createChatRoom( + chatRoomWrapper.getChatRoomName(), + chatRoomWrapper.getParentProvider().getProtocolProvider(), + new ArrayList(), "", false, false, true); + } + + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if(chatRoom == null) + { + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.WARNING"), + MUCActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getChatRoomName()})); + return; + } + + new JoinChatRoomTask( + (ChatRoomWrapperImpl)chatRoomWrapper, nickName, password) + .start(); + } + + /** + * Joins the given chat room with the given password and manages all the + * exceptions that could occur during the join process. + * + * @param chatRoomWrapper the chat room to join. + * @param nickName the nickname we choose for the given chat room. + * @param password the password. + * @param subject the subject which will be set to the room after the user + * join successful. + */ + public void joinChatRoom( ChatRoomWrapper chatRoomWrapper, + String nickName, + byte[] password, + String subject) + { + if (chatRoomWrapper.getChatRoom() == null) + { + chatRoomWrapper = createChatRoom( + chatRoomWrapper.getChatRoomName(), + chatRoomWrapper.getParentProvider().getProtocolProvider(), + new ArrayList(), "", false, false, true); + } + + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + if (chatRoom == null) + { + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.WARNING"), + MUCActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getChatRoomName()})); + + return; + } + + // join from add chat room dialog + + new JoinChatRoomTask( + (ChatRoomWrapperImpl) chatRoomWrapper, + nickName, + password, + subject) + .start(); + } + + + /** + * Join chat room. + * @param chatRoomWrapper + */ + public void joinChatRoom(ChatRoomWrapper chatRoomWrapper) + { + if (chatRoomWrapper.getChatRoom() == null) + { + chatRoomWrapper = createChatRoom( + chatRoomWrapper.getChatRoomName(), + chatRoomWrapper.getParentProvider().getProtocolProvider(), + new ArrayList(), "", false, false, true); + } + + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if(chatRoom == null) + { + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.WARNING"), + MUCActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getChatRoomName()})); + + return; + } + + new JoinChatRoomTask((ChatRoomWrapperImpl)chatRoomWrapper, null, null) + .start(); + } + + + /** + * Joins the given chat room and manages all the exceptions that could + * occur during the join process. + * + * @param chatRoom the chat room to join + * @param nickname the nickname we're using to join + * @param password the password we're using to join + */ + public void joinChatRoom( ChatRoom chatRoom, + String nickname, + byte[] password) + { + ChatRoomWrapper chatRoomWrapper + = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + + if(chatRoomWrapper == null) + { + ChatRoomProviderWrapper parentProvider + = chatRoomList.findServerWrapperFromProvider( + chatRoom.getParentProvider()); + + chatRoomWrapper + = new ChatRoomWrapperImpl(parentProvider, chatRoom); + + chatRoomList.addChatRoom(chatRoomWrapper); + + } + + this.joinChatRoom(chatRoomWrapper, nickname, password); + } + + /** + * Joins the room with the given name though the given chat room provider. + * + * @param chatRoomName the name of the room to join. + * @param chatRoomProvider the chat room provider to join through. + */ + public void joinChatRoom( String chatRoomName, + ChatRoomProviderWrapper chatRoomProvider) + { + OperationSetMultiUserChat groupChatOpSet + = chatRoomProvider + .getProtocolProvider().getOperationSet( + OperationSetMultiUserChat.class); + + ChatRoom chatRoom = null; + try + { + chatRoom = groupChatOpSet.findRoom(chatRoomName); + } + catch (Exception e) + { + if (logger.isTraceEnabled()) + logger.trace("Un exception occurred while searching for room:" + + chatRoomName, e); + } + + if (chatRoom != null) + { + ChatRoomWrapper chatRoomWrapper + = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + + if(chatRoomWrapper == null) + { + ChatRoomProviderWrapper parentProvider + = chatRoomList + .findServerWrapperFromProvider( + chatRoom.getParentProvider()); + + chatRoomWrapper + = new ChatRoomWrapperImpl(parentProvider, chatRoom); + + chatRoomList.addChatRoom(chatRoomWrapper); + + fireChatRoomListChangedEvent( + chatRoomWrapper, + ChatRoomListChangeEvent.CHAT_ROOM_ADDED); + } + joinChatRoom(chatRoomWrapper); + } + else + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.ERROR"), + MUCActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_NOT_EXIST", + new String[]{chatRoomName, + chatRoomProvider.getProtocolProvider() + .getAccountID().getService()})); + } + + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param persistent is the room persistent + * @param isPrivate whether the room will be private or public. + * @return the ChatRoomWrapper corresponding to the created room + */ + public ChatRoomWrapper createChatRoom( + String roomName, + ProtocolProviderService protocolProvider, + Collection contacts, + String reason, + boolean persistent, + boolean isPrivate) + { + return createChatRoom( + roomName, protocolProvider, contacts, reason, true, persistent, + isPrivate); + } + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param persistent is the room persistent + * @return the ChatRoomWrapper corresponding to the created room + */ + public ChatRoomWrapper createChatRoom( + String roomName, + ProtocolProviderService protocolProvider, + Collection contacts, + String reason, + boolean persistent) + { + return createChatRoom( + roomName, protocolProvider, contacts, reason, true, persistent, + false); + } + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param join whether we should join the room after creating it. + * @param persistent whether the newly created room will be persistent. + * @param isPrivate whether the room will be private or public. + * @return the ChatRoomWrapper corresponding to the created room or + * null if the protocol fails to create the chat room. + */ + public ChatRoomWrapper createChatRoom( + String roomName, + ProtocolProviderService protocolProvider, + Collection contacts, + String reason, + boolean join, + boolean persistent, + boolean isPrivate) + { + ChatRoomWrapper chatRoomWrapper = null; + OperationSetMultiUserChat groupChatOpSet + = protocolProvider.getOperationSet(OperationSetMultiUserChat.class); + + // If there's no group chat operation set we have nothing to do here. + if (groupChatOpSet == null) + return null; + + ChatRoom chatRoom = null; + try + { + + + HashMap roomProperties = + new HashMap(); + roomProperties.put("isPrivate", isPrivate); + chatRoom = groupChatOpSet.createChatRoom(roomName, roomProperties); + + if(join) + { + chatRoom.join(); + + for(String contact : contacts) + chatRoom.invite(contact, reason); + } + } + catch (OperationFailedException ex) + { + logger.error("Failed to create chat room.", ex); + + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.ERROR"), + MUCActivator.getResources().getI18NString( + "service.gui.CREATE_CHAT_ROOM_ERROR", + new String[]{protocolProvider.getProtocolDisplayName()}), + ex); + } + catch (OperationNotSupportedException ex) + { + logger.error("Failed to create chat room.", ex); + + MUCActivator.getAlertUIService().showAlertDialog( + MUCActivator.getResources().getI18NString("service.gui.ERROR"), + MUCActivator.getResources().getI18NString( + "service.gui.CREATE_CHAT_ROOM_ERROR", + new String[]{protocolProvider.getProtocolDisplayName()}), + ex); + } + + if(chatRoom != null) + { + ChatRoomProviderWrapper parentProvider + = chatRoomList.findServerWrapperFromProvider(protocolProvider); + + // if there is the same room ids don't add new wrapper as old one + // maybe already created + chatRoomWrapper = + chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + + if(chatRoomWrapper == null) + { + chatRoomWrapper + = new ChatRoomWrapperImpl(parentProvider, chatRoom); + chatRoomWrapper.setPersistent(persistent); + chatRoomList.addChatRoom(chatRoomWrapper); + } + } + + return chatRoomWrapper; + } + + /** + * Creates a private chat room, by specifying the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param persistent is the room persistent + * @return the ChatRoomWrapper corresponding to the created room + */ + public ChatRoomWrapper createPrivateChatRoom( + ProtocolProviderService protocolProvider, + Collection contacts, + String reason, + boolean persistent) + { + return this.createChatRoom( + null, protocolProvider, contacts, reason, persistent, true); + } + + + /** + * Returns existing chat rooms for the given chatRoomProvider. + * @param chatRoomProvider the ChatRoomProviderWrapper, which + * chat rooms we're looking for + * @return existing chat rooms for the given chatRoomProvider + */ + public List getExistingChatRooms( + ChatRoomProviderWrapper chatRoomProvider) + { + if (chatRoomProvider == null) + return null; + + ProtocolProviderService protocolProvider + = chatRoomProvider.getProtocolProvider(); + + if (protocolProvider == null) + return null; + + OperationSetMultiUserChat groupChatOpSet + = protocolProvider + .getOperationSet(OperationSetMultiUserChat.class); + + if (groupChatOpSet == null) + return null; + + List chatRooms = null; + try + { + chatRooms = groupChatOpSet.getExistingChatRooms(); + } + catch (OperationFailedException e) + { + if (logger.isTraceEnabled()) + logger.trace("Failed to obtain existing chat rooms for server: " + + protocolProvider.getAccountID().getService(), e); + } + catch (OperationNotSupportedException e) + { + if (logger.isTraceEnabled()) + logger.trace("Failed to obtain existing chat rooms for server: " + + protocolProvider.getAccountID().getService(), e); + } + + return chatRooms; + } + + /** + * Rejects the given invitation with the specified reason. + * + * @param multiUserChatOpSet the operation set to use for rejecting the + * invitation + * @param invitation the invitation to reject + * @param reason the reason for the rejection + */ + public void rejectInvitation( OperationSetMultiUserChat multiUserChatOpSet, + ChatRoomInvitation invitation, + String reason) + { + multiUserChatOpSet.rejectInvitation(invitation, reason); + } + + /** + * Leaves the given chat room. + * + * @param chatRoomWrapper the chat room to leave. + * @return ChatRoomWrapper instance associated with the chat room. + */ + public ChatRoomWrapper leaveChatRoom(ChatRoomWrapper chatRoomWrapper) + { + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + if (chatRoom == null) + { + ResourceManagementService resources = MUCActivator.getResources(); + + MUCActivator.getAlertUIService().showAlertDialog( + resources.getI18NString("service.gui.WARNING"), + resources + .getI18NString( + "service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED")); + + return null; + } + + if (chatRoom.isJoined()) + chatRoom.leave(); + + ChatRoomWrapper existChatRoomWrapper + = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + + if(existChatRoomWrapper == null) + return null; + + // We save the choice of the user, before the chat room is really + // joined, because even the join fails we want the next time when + // we login to join this chat room automatically. + ConfigurationUtils.updateChatRoomStatus( + chatRoomWrapper.getParentProvider().getProtocolProvider(), + chatRoomWrapper.getChatRoomID(), + GlobalStatusEnum.OFFLINE_STATUS); + + return existChatRoomWrapper; + } + + /** + * Joins a chat room in an asynchronous way. + */ + private class JoinChatRoomTask + extends Thread + { + private final ChatRoomWrapperImpl chatRoomWrapper; + + private final String nickName; + + private final byte[] password; + + private final boolean rememberPassword; + + private final boolean isFirstAttempt; + + private final String subject; + + private ResourceManagementService resources + = MUCActivator.getResources(); + + JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, + String nickName, + byte[] password, + boolean rememberPassword, + boolean isFirstAttempt, + String subject) + { + this.chatRoomWrapper = chatRoomWrapper; + this.nickName = nickName; + this.isFirstAttempt = isFirstAttempt; + this.subject = subject; + + if(password == null) + { + String passString = chatRoomWrapper.loadPassword(); + if(passString != null) + { + this.password = passString.getBytes(); + } + else + { + this.password = null; + } + } + else + { + this.password = password; + } + this.rememberPassword = rememberPassword; + } + + JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, + String nickName, + byte[] password) + { + this(chatRoomWrapper, nickName, password, false, true, null); + } + + JoinChatRoomTask( ChatRoomWrapperImpl chatRoomWrapper, + String nickName, + byte[] password, + String subject) + { + this(chatRoomWrapper, nickName, password, false, true, subject); + } + + /** + * @override {@link Thread}{@link #run()} to perform all asynchronous + * tasks. + */ + @Override + public void run() + { + ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + + try + { + if(password != null && password.length > 0) + chatRoom.joinAs(nickName, password); + else if (nickName != null) + chatRoom.joinAs(nickName); + else + chatRoom.join(); + + done(JOIN_SUCCESS_PROP); + } + catch (OperationFailedException e) + { + if (logger.isTraceEnabled()) + logger.trace("Failed to join chat room: " + + chatRoom.getName(), e); + + switch (e.getErrorCode()) + { + case OperationFailedException.AUTHENTICATION_FAILED: + done(JOIN_AUTHENTICATION_FAILED_PROP); + break; + case OperationFailedException.REGISTRATION_REQUIRED: + done(JOIN_REGISTRATION_REQUIRED_PROP); + break; + case OperationFailedException.PROVIDER_NOT_REGISTERED: + done(JOIN_PROVIDER_NOT_REGISTERED_PROP); + break; + case OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS: + done(JOIN_SUBSCRIPTION_ALREADY_EXISTS_PROP); + break; + default: + done(JOIN_UNKNOWN_ERROR_PROP); + } + } + } + + /** + * Performs UI changes after the chat room join task has finished. + * @param returnCode the result code from the chat room join task. + */ + private void done(String returnCode) + { + ConfigurationUtils.updateChatRoomStatus( + chatRoomWrapper.getParentProvider().getProtocolProvider(), + chatRoomWrapper.getChatRoomID(), + GlobalStatusEnum.ONLINE_STATUS); + + String errorMessage = null; + if(JOIN_AUTHENTICATION_FAILED_PROP.equals(returnCode)) + { + chatRoomWrapper.removePassword(); + + AuthenticationWindowService authWindowsService + = ServiceUtils.getService( + MUCActivator.bundleContext, + AuthenticationWindowService.class); + + AuthenticationWindowService.AuthenticationWindow authWindow = + authWindowsService.create( + null, null, null, false, + chatRoomWrapper.isPersistent(), + AuthenticationWindow.getAuthenticationWindowIcon( + chatRoomWrapper.getParentProvider() + .getProtocolProvider()), + resources.getI18NString( + "service.gui.AUTHENTICATION_WINDOW_TITLE", + new String[]{chatRoomWrapper.getParentProvider() + .getName()}), + resources.getI18NString( + "service.gui.CHAT_ROOM_REQUIRES_PASSWORD", + new String[]{ + chatRoomWrapper.getChatRoomName()}), + "", null, + isFirstAttempt ? + null : + resources.getI18NString( + "service.gui.AUTHENTICATION_FAILED", + new String[]{chatRoomWrapper.getChatRoomName()}), + null); + + authWindow.setVisible(true); + + if (!authWindow.isCanceled()) + { + joinChatRoom( + chatRoomWrapper, + nickName, + new String(authWindow.getPassword()).getBytes(), + authWindow.isRememberPassword(), + false, + subject); + } + } + else if(JOIN_REGISTRATION_REQUIRED_PROP.equals(returnCode)) + { + errorMessage + = resources + .getI18NString( + "service.gui.CHAT_ROOM_REGISTRATION_REQUIRED", + new String[]{chatRoomWrapper.getChatRoomName()}); + } + else if(JOIN_PROVIDER_NOT_REGISTERED_PROP.equals(returnCode)) + { + errorMessage + = resources + .getI18NString("service.gui.CHAT_ROOM_NOT_CONNECTED", + new String[]{chatRoomWrapper.getChatRoomName()}); + } + else if(JOIN_SUBSCRIPTION_ALREADY_EXISTS_PROP.equals(returnCode)) + { + errorMessage + = resources + .getI18NString("service.gui.CHAT_ROOM_ALREADY_JOINED", + new String[]{chatRoomWrapper.getChatRoomName()}); + } + else + { + errorMessage + = resources + .getI18NString("service.gui.FAILED_TO_JOIN_CHAT_ROOM", + new String[]{chatRoomWrapper.getChatRoomName()}); + } + + if (!JOIN_SUCCESS_PROP.equals(returnCode) && + !JOIN_AUTHENTICATION_FAILED_PROP.equals(returnCode)) + { + MUCActivator.getAlertUIService().showAlertPopup( + resources.getI18NString("service.gui.ERROR"), errorMessage); + } + + if (JOIN_SUCCESS_PROP.equals(returnCode)) + { + if(rememberPassword) + { + chatRoomWrapper.savePassword(new String(password)); + } + + if(subject != null) + { + try + { + chatRoomWrapper.getChatRoom().setSubject(subject); + } + catch(OperationFailedException ex) + { + logger.warn("Failed to set subject."); + } + } + } + + chatRoomWrapper.firePropertyChange(returnCode); + } + } + + /** + * Finds the ChatRoomWrapper instance associated with the + * source contact. + * @param contact the source contact. + * @return the ChatRoomWrapper instance. + */ + public ChatRoomWrapper findChatRoomWrapperFromSourceContact( + SourceContact contact) + { + if(!(contact instanceof ChatRoomSourceContact)) + return null; + ChatRoomSourceContact chatRoomContact = (ChatRoomSourceContact) contact; + return chatRoomList.findChatRoomWrapperFromChatRoomID( + chatRoomContact.getChatRoomID(), chatRoomContact.getProvider()); + } + + /** + * Finds the ChatRoomWrapper instance associated with the + * chat room. + * @param chatRoomID the id of the chat room. + * @param pps the provider of the chat room. + * @return the ChatRoomWrapper instance. + */ + public ChatRoomWrapper findChatRoomWrapperFromChatRoomID(String chatRoomID, + ProtocolProviderService pps) + { + return chatRoomList.findChatRoomWrapperFromChatRoomID(chatRoomID, pps); + } + + /** + * Searches for chat room wrapper in chat room list by chat room. + * + * @param chatRoom the chat room. + * @param create if true and the chat room wrapper is not found new + * chatRoomWrapper is created. + * @return found chat room wrapper or the created chat room wrapper. + */ + @Override + public ChatRoomWrapper getChatRoomWrapperByChatRoom(ChatRoom chatRoom, + boolean create) + { + ChatRoomWrapper chatRoomWrapper + = chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + + if ((chatRoomWrapper == null) && create) + { + ChatRoomProviderWrapper parentProvider + = chatRoomList.findServerWrapperFromProvider( + chatRoom.getParentProvider()); + + chatRoomWrapper + = new ChatRoomWrapperImpl( + parentProvider, chatRoom); + + chatRoomList.addChatRoom(chatRoomWrapper); + } + return chatRoomWrapper; + } + + /** + * Goes through the locally stored chat rooms list and for each + * {@link ChatRoomWrapper} tries to find the corresponding server stored + * {@link ChatRoom} in the specified operation set. Joins automatically all + * found chat rooms. + * + * @param protocolProvider the protocol provider for the account to + * synchronize + * @param opSet the multi user chat operation set, which give us access to + * chat room server + */ + public void synchronizeOpSetWithLocalContactList( + ProtocolProviderService protocolProvider, + final OperationSetMultiUserChat opSet) + { + ChatRoomProviderWrapper chatRoomProvider + = findServerWrapperFromProvider(protocolProvider); + + if(chatRoomProvider == null) + { + chatRoomProvider = chatRoomList.addRegisteredChatProvider(protocolProvider); + } + + if (chatRoomProvider != null) + { + chatRoomProvider.synchronizeProvider(); + } + } + + /** + * Returns an iterator to the list of chat room providers. + * + * @return an iterator to the list of chat room providers. + */ + public Iterator getChatRoomProviders() + { + return chatRoomList.getChatRoomProviders(); + } + + /** + * Removes the given ChatRoom from the list of all chat rooms. + * + * @param chatRoomWrapper the ChatRoomWrapper to remove + */ + public void removeChatRoom(ChatRoomWrapper chatRoomWrapper) + { + chatRoomList.removeChatRoom(chatRoomWrapper); + } + + /** + * Destroys the given ChatRoom from the list of all chat rooms. + * + * @param chatRoomWrapper the ChatRoomWrapper to be destroyed. + * @param reason the reason for destroying. + * @param alternateAddress the alternate address. + */ + public void destroyChatRoom(ChatRoomWrapper chatRoomWrapper, + String reason, String alternateAddress) + { + if(chatRoomWrapper.getChatRoom().destroy(reason, alternateAddress)) + { + MUCActivator.getUIService().closeChatRoomWindow( + chatRoomWrapper); + chatRoomList.removeChatRoom(chatRoomWrapper); + } + else + { + // if we leave a chat room which is not persistent + // the room can be destroyed on the server, and error is returned + // when we try to destroy it not-authorized(401) + if(!chatRoomWrapper.getChatRoom().isPersistent() + && !chatRoomWrapper.getChatRoom().isJoined()) + { + chatRoomList.removeChatRoom(chatRoomWrapper); + } + } + + } + + /** + * Adds a ChatRoomProviderWrapperListener to the listener list. + * + * @param listener the ChatRoomProviderWrapperListener to be added + */ + public void addChatRoomProviderWrapperListener( + ChatRoomProviderWrapperListener listener) + { + chatRoomList.addChatRoomProviderWrapperListener(listener); + } + + /** + * Removes the ChatRoomProviderWrapperListener to the listener list. + * + * @param listener the ChatRoomProviderWrapperListener to be removed + */ + public void removeChatRoomProviderWrapperListener( + ChatRoomProviderWrapperListener listener) + { + chatRoomList.removeChatRoomProviderWrapperListener(listener); + } + + /** + * Returns the ChatRoomProviderWrapper that correspond to the + * given ProtocolProviderService. If the list doesn't contain a + * corresponding wrapper - returns null. + * + * @param protocolProvider the protocol provider that we're looking for + * @return the ChatRoomProvider object corresponding to + * the given ProtocolProviderService + */ + public ChatRoomProviderWrapper findServerWrapperFromProvider( + ProtocolProviderService protocolProvider) + { + return chatRoomList.findServerWrapperFromProvider(protocolProvider); + } + + /** + * Returns the ChatRoomWrapper that correspond to the given + * ChatRoom. If the list of chat rooms doesn't contain a + * corresponding wrapper - returns null. + * + * @param chatRoom the ChatRoom that we're looking for + * @return the ChatRoomWrapper object corresponding to the given + * ChatRoom + */ + public ChatRoomWrapper findChatRoomWrapperFromChatRoom(ChatRoom chatRoom) + { + return chatRoomList.findChatRoomWrapperFromChatRoom(chatRoom); + } + + /** + * Opens a chat window for the chat room. + * + * @param room the chat room. + */ + public void openChatRoom(ChatRoomWrapper room) + { + if (room.getChatRoom() == null) + { + room = createChatRoom( + room.getChatRoomName(), + room.getParentProvider().getProtocolProvider(), + new ArrayList(),"", false, false, true); + + // leave the chatroom because getChatRoom().isJoined() returns true + // otherwise + if (room.getChatRoom().isJoined()) + room.getChatRoom().leave(); + + } + + if(!room.getChatRoom().isJoined()) + { + String savedNick = + ConfigurationUtils.getChatRoomProperty(room + .getParentProvider().getProtocolProvider(), room + .getChatRoomID(), "userNickName"); + String subject = null; + + if (savedNick == null) + { + String[] joinOptions = ChatRoomJoinOptionsDialog.getJoinOptions( + room.getParentProvider().getProtocolProvider(), + room.getChatRoomID(), + MUCActivator.getGlobalDisplayDetailsService() + .getDisplayName( + room.getParentProvider().getProtocolProvider())); + savedNick = joinOptions[0]; + subject = joinOptions[1]; + + } + + if (savedNick != null) + { + joinChatRoom(room, savedNick, null, + subject); + } + else + return; + } + + MUCActivator.getUIService().openChatRoomWindow(room); + } + + /** + * Returns instance of the ServerChatRoomContactSourceService + * contact source. + * @return instance of the ServerChatRoomContactSourceService + * contact source. + */ + public ContactSourceService getServerChatRoomsContactSourceForProvider( + ChatRoomProviderWrapper pps) + { + return new ServerChatRoomContactSourceService(pps); + } + + /** + * Returns true if the contact is ChatRoomSourceContact + * + * @param contact the contact + * @return true if the contact is ChatRoomSourceContact + */ + public boolean isMUCSourceContact(SourceContact contact) + { + return (contact instanceof ChatRoomSourceContact); + } +} diff --git a/src/net/java/sip/communicator/impl/muc/ServerChatRoomQuery.java b/src/net/java/sip/communicator/impl/muc/ServerChatRoomQuery.java index 47785ee..a98e5ed 100644 --- a/src/net/java/sip/communicator/impl/muc/ServerChatRoomQuery.java +++ b/src/net/java/sip/communicator/impl/muc/ServerChatRoomQuery.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,331 +15,331 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.muc; - -import java.util.*; -import java.util.regex.*; - -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.muc.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * The ServerChatRoomQuery is a query over the - * ServerChatRoomContactSourceService. - * - * @author Hristo Terezov - */ -public class ServerChatRoomQuery - extends AsyncContactQuery - implements ChatRoomProviderWrapperListener -{ - /** - * The query string. - */ - private String queryString; - - /** - * List with the current results for the query. - */ - private Set contactResults - = new TreeSet(); - - /** - * MUC service. - */ - private MUCServiceImpl mucService; - - /** - * The number of contact query listeners. - */ - private int contactQueryListenersCount = 0; - - /** - * The provider associated with the query. - */ - private ChatRoomProviderWrapper provider = null; - - /** - * Creates an instance of ChatRoomQuery by specifying - * the parent contact source, the query string to match and the maximum - * result contacts to return. - * - * @param contactSource the parent contact source - * @param queryString the query string to match - * @param provider the provider associated with the query - */ - public ServerChatRoomQuery(String queryString, - ServerChatRoomContactSourceService contactSource, - ChatRoomProviderWrapper provider) - { - super(contactSource, - Pattern.compile(queryString, Pattern.CASE_INSENSITIVE - | Pattern.LITERAL), true); - this.queryString = queryString; - - mucService = MUCActivator.getMUCService(); - - this.provider = provider; - } - - /** - * Adds listeners for the query - */ - private void initListeners() - { - mucService.addChatRoomProviderWrapperListener(this); - } - - @Override - protected void run() - { - if(provider == null) - { - Iterator chatRoomProviders - = mucService.getChatRoomProviders(); - while (chatRoomProviders.hasNext()) - { - ChatRoomProviderWrapper provider = chatRoomProviders.next(); - providerAdded(provider, true); - } - } - else - { - providerAdded(provider, true); - } - - if (getStatus() != QUERY_CANCELED) - setStatus(QUERY_COMPLETED); - } - - /** - * Handles adding a chat room provider. - * @param provider the provider. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the results. - */ - private void providerAdded(final ChatRoomProviderWrapper provider, - final boolean addQueryResult) - { - final ProtocolProviderService pps = provider.getProtocolProvider(); - List chatRoomNames = - MUCActivator.getMUCService().getExistingChatRooms(provider); - if (chatRoomNames == null) - { - return; - } - - // Already create all the BaseChatRoomSourceContact instances since all - // the data is already available. - final Set chatRooms = - new HashSet(chatRoomNames.size()); - for (final String name : chatRoomNames) - { - chatRooms.add(new BaseChatRoomSourceContact(name, name, this, pps)); - } - addChatRooms(pps, chatRooms, addQueryResult); - } - - - /** - * Adds found result to the query results. - * - * @param pps the protocol provider associated with the found chat room. - * @param chatRoomName the name of the chat room. - * @param chatRoomID the id of the chat room. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the results. - */ - private void addChatRoom(ProtocolProviderService pps, - String chatRoomName, String chatRoomID, boolean addQueryResult) - { - if((queryString == null - || ((chatRoomName.contains( - queryString) - || chatRoomID.contains(queryString) - ))) && isMatching(chatRoomID, pps)) - { - BaseChatRoomSourceContact contact - = new BaseChatRoomSourceContact(chatRoomName, chatRoomID, this, - pps); - synchronized (contactResults) - { - contactResults.add(contact); - } - - if(addQueryResult) - { - addQueryResult(contact, false); - } - else - { - fireContactReceived(contact, false); - } - } - } - - /** - * Adds found results to the query results. - * - * @param pps the protocol provider associated with the found chat room. - * @param chatRooms The set of chat rooms based on - * BaseChatRoomSourceContact. This is the full set and it will be - * filtered according to demands of the queryString. - * @param addQueryResult indicates whether we should add the chat room to - * the query results or fire an event without adding it to the - * results. - */ - private void addChatRooms(final ProtocolProviderService pps, - final Set chatRooms, - final boolean addQueryResult) - { - BaseChatRoomSourceContact room; - Iterator iterator = chatRooms.iterator(); - while (iterator.hasNext()) - { - room = iterator.next(); - - // Notice the NOT operator at the start ... - if (!((queryString == null || (room.getChatRoomName().contains( - queryString) || room.getChatRoomID().contains(queryString))) - && isMatching(room.getChatRoomID(), pps))) - { - iterator.remove(); - } - } - - synchronized (contactResults) - { - contactResults.addAll(chatRooms); - } - - if (addQueryResult) - { - addQueryResults(chatRooms); - } - else - { - // TODO Need something to fire one event for multiple contacts. - for (SourceContact contact : chatRooms) - { - fireContactReceived(contact, false); - } - } - } - - @Override - public void chatRoomProviderWrapperAdded(ChatRoomProviderWrapper provider) - { - providerAdded(provider, false); - } - - @Override - public void chatRoomProviderWrapperRemoved(ChatRoomProviderWrapper provider) - { - LinkedList tmpContactResults; - synchronized (contactResults) - { - tmpContactResults - = new LinkedList(contactResults); - - for(BaseChatRoomSourceContact contact : tmpContactResults) - { - if(contact.getProvider().equals(provider.getProtocolProvider())) - { - contactResults.remove(contact); - fireContactRemoved(contact); - } - } - } - } - - - /** - * Clears any listener we used. - */ - private void clearListeners() - { - mucService.removeChatRoomProviderWrapperListener(this); - } - - /** - * Cancels this ContactQuery. - * - * @see ContactQuery#cancel() - */ - public void cancel() - { - clearListeners(); - - super.cancel(); - } - - /** - * If query has status changed to cancel, let's clear listeners. - * @param status {@link ContactQuery#QUERY_CANCELED}, - * {@link ContactQuery#QUERY_COMPLETED} - */ - public void setStatus(int status) - { - if(status == QUERY_CANCELED) - clearListeners(); - - super.setStatus(status); - } - - @Override - public void addContactQueryListener(ContactQueryListener l) - { - super.addContactQueryListener(l); - contactQueryListenersCount++; - if(contactQueryListenersCount == 1) - { - initListeners(); - } - } - - @Override - public void removeContactQueryListener(ContactQueryListener l) - { - super.removeContactQueryListener(l); - contactQueryListenersCount--; - if(contactQueryListenersCount == 0) - { - clearListeners(); - } - } - - /** - * Checks if the contact should be added to results or not. - * @param chatRoomID the chat room id associated with the contact. - * @param pps the provider of the chat room contact. - * @return true if the result should be added to the results and - * false if not. - */ - public boolean isMatching(String chatRoomID, ProtocolProviderService pps) - { - return (MUCActivator.getMUCService().findChatRoomWrapperFromChatRoomID( - chatRoomID, pps) == null); - } - - /** - * Returns the index of the contact in the contact results list. - * @param contact the contact. - * @return the index of the contact in the contact results list. - */ - public int indexOf(BaseChatRoomSourceContact contact) - { - Iterator it = contactResults.iterator(); - int i = 0; - while(it.hasNext()) - { - if(contact.equals(it.next())) - { - return i; - } - i++; - } - return -1; - } -} +package net.java.sip.communicator.impl.muc; + +import java.util.*; +import java.util.regex.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.muc.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * The ServerChatRoomQuery is a query over the + * ServerChatRoomContactSourceService. + * + * @author Hristo Terezov + */ +public class ServerChatRoomQuery + extends AsyncContactQuery + implements ChatRoomProviderWrapperListener +{ + /** + * The query string. + */ + private String queryString; + + /** + * List with the current results for the query. + */ + private Set contactResults + = new TreeSet(); + + /** + * MUC service. + */ + private MUCServiceImpl mucService; + + /** + * The number of contact query listeners. + */ + private int contactQueryListenersCount = 0; + + /** + * The provider associated with the query. + */ + private ChatRoomProviderWrapper provider = null; + + /** + * Creates an instance of ChatRoomQuery by specifying + * the parent contact source, the query string to match and the maximum + * result contacts to return. + * + * @param contactSource the parent contact source + * @param queryString the query string to match + * @param provider the provider associated with the query + */ + public ServerChatRoomQuery(String queryString, + ServerChatRoomContactSourceService contactSource, + ChatRoomProviderWrapper provider) + { + super(contactSource, + Pattern.compile(queryString, Pattern.CASE_INSENSITIVE + | Pattern.LITERAL), true); + this.queryString = queryString; + + mucService = MUCActivator.getMUCService(); + + this.provider = provider; + } + + /** + * Adds listeners for the query + */ + private void initListeners() + { + mucService.addChatRoomProviderWrapperListener(this); + } + + @Override + protected void run() + { + if(provider == null) + { + Iterator chatRoomProviders + = mucService.getChatRoomProviders(); + while (chatRoomProviders.hasNext()) + { + ChatRoomProviderWrapper provider = chatRoomProviders.next(); + providerAdded(provider, true); + } + } + else + { + providerAdded(provider, true); + } + + if (getStatus() != QUERY_CANCELED) + setStatus(QUERY_COMPLETED); + } + + /** + * Handles adding a chat room provider. + * @param provider the provider. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the results. + */ + private void providerAdded(final ChatRoomProviderWrapper provider, + final boolean addQueryResult) + { + final ProtocolProviderService pps = provider.getProtocolProvider(); + List chatRoomNames = + MUCActivator.getMUCService().getExistingChatRooms(provider); + if (chatRoomNames == null) + { + return; + } + + // Already create all the BaseChatRoomSourceContact instances since all + // the data is already available. + final Set chatRooms = + new HashSet(chatRoomNames.size()); + for (final String name : chatRoomNames) + { + chatRooms.add(new BaseChatRoomSourceContact(name, name, this, pps)); + } + addChatRooms(pps, chatRooms, addQueryResult); + } + + + /** + * Adds found result to the query results. + * + * @param pps the protocol provider associated with the found chat room. + * @param chatRoomName the name of the chat room. + * @param chatRoomID the id of the chat room. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the results. + */ + private void addChatRoom(ProtocolProviderService pps, + String chatRoomName, String chatRoomID, boolean addQueryResult) + { + if((queryString == null + || ((chatRoomName.contains( + queryString) + || chatRoomID.contains(queryString) + ))) && isMatching(chatRoomID, pps)) + { + BaseChatRoomSourceContact contact + = new BaseChatRoomSourceContact(chatRoomName, chatRoomID, this, + pps); + synchronized (contactResults) + { + contactResults.add(contact); + } + + if(addQueryResult) + { + addQueryResult(contact, false); + } + else + { + fireContactReceived(contact, false); + } + } + } + + /** + * Adds found results to the query results. + * + * @param pps the protocol provider associated with the found chat room. + * @param chatRooms The set of chat rooms based on + * BaseChatRoomSourceContact. This is the full set and it will be + * filtered according to demands of the queryString. + * @param addQueryResult indicates whether we should add the chat room to + * the query results or fire an event without adding it to the + * results. + */ + private void addChatRooms(final ProtocolProviderService pps, + final Set chatRooms, + final boolean addQueryResult) + { + BaseChatRoomSourceContact room; + Iterator iterator = chatRooms.iterator(); + while (iterator.hasNext()) + { + room = iterator.next(); + + // Notice the NOT operator at the start ... + if (!((queryString == null || (room.getChatRoomName().contains( + queryString) || room.getChatRoomID().contains(queryString))) + && isMatching(room.getChatRoomID(), pps))) + { + iterator.remove(); + } + } + + synchronized (contactResults) + { + contactResults.addAll(chatRooms); + } + + if (addQueryResult) + { + addQueryResults(chatRooms); + } + else + { + // TODO Need something to fire one event for multiple contacts. + for (SourceContact contact : chatRooms) + { + fireContactReceived(contact, false); + } + } + } + + @Override + public void chatRoomProviderWrapperAdded(ChatRoomProviderWrapper provider) + { + providerAdded(provider, false); + } + + @Override + public void chatRoomProviderWrapperRemoved(ChatRoomProviderWrapper provider) + { + LinkedList tmpContactResults; + synchronized (contactResults) + { + tmpContactResults + = new LinkedList(contactResults); + + for(BaseChatRoomSourceContact contact : tmpContactResults) + { + if(contact.getProvider().equals(provider.getProtocolProvider())) + { + contactResults.remove(contact); + fireContactRemoved(contact); + } + } + } + } + + + /** + * Clears any listener we used. + */ + private void clearListeners() + { + mucService.removeChatRoomProviderWrapperListener(this); + } + + /** + * Cancels this ContactQuery. + * + * @see ContactQuery#cancel() + */ + public void cancel() + { + clearListeners(); + + super.cancel(); + } + + /** + * If query has status changed to cancel, let's clear listeners. + * @param status {@link ContactQuery#QUERY_CANCELED}, + * {@link ContactQuery#QUERY_COMPLETED} + */ + public void setStatus(int status) + { + if(status == QUERY_CANCELED) + clearListeners(); + + super.setStatus(status); + } + + @Override + public void addContactQueryListener(ContactQueryListener l) + { + super.addContactQueryListener(l); + contactQueryListenersCount++; + if(contactQueryListenersCount == 1) + { + initListeners(); + } + } + + @Override + public void removeContactQueryListener(ContactQueryListener l) + { + super.removeContactQueryListener(l); + contactQueryListenersCount--; + if(contactQueryListenersCount == 0) + { + clearListeners(); + } + } + + /** + * Checks if the contact should be added to results or not. + * @param chatRoomID the chat room id associated with the contact. + * @param pps the provider of the chat room contact. + * @return true if the result should be added to the results and + * false if not. + */ + public boolean isMatching(String chatRoomID, ProtocolProviderService pps) + { + return (MUCActivator.getMUCService().findChatRoomWrapperFromChatRoomID( + chatRoomID, pps) == null); + } + + /** + * Returns the index of the contact in the contact results list. + * @param contact the contact. + * @return the index of the contact in the contact results list. + */ + public int indexOf(BaseChatRoomSourceContact contact) + { + Iterator it = contactResults.iterator(); + int i = 0; + while(it.hasNext()) + { + if(contact.equals(it.next())) + { + return i; + } + i++; + } + return -1; + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java b/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java index 1c5bf93..9bacb4c 100644 --- a/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java +++ b/src/net/java/sip/communicator/impl/neomedia/DeviceConfigurationComboBoxModel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,456 +15,456 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.neomedia; - -import java.beans.*; -import java.util.*; - -import javax.media.*; -import javax.swing.*; -import javax.swing.event.*; - -import org.jitsi.impl.neomedia.device.*; -import org.jitsi.service.neomedia.*; - -/** - * Implements ComboBoxModel for a specific DeviceConfiguration - * so that the latter may be displayed and manipulated in the user interface as - * a combo box. - * - * @author Lyubomir Marinov - * @author Damian Minkov - */ -public class DeviceConfigurationComboBoxModel - implements ComboBoxModel, - ListModel, - PropertyChangeListener -{ - /** - * Type of the model - audio. - */ - public static final int AUDIO = 1; - - /** - * Audio Capture Device. - */ - public static final int AUDIO_CAPTURE = 3; - - /** - * Audio device for notification sounds. - */ - public static final int AUDIO_NOTIFY = 5; - - /** - * Audio playback device. - */ - public static final int AUDIO_PLAYBACK = 4; - - /** - * Type of the model - video. - */ - public static final int VIDEO = 2; - - private AudioSystem[] audioSystems; - - /** - * The current device configuration. - */ - private final DeviceConfiguration deviceConfiguration; - - /** - * All the devices. - */ - private CaptureDevice[] devices; - - /** - * The ListDataListeners registered with this instance. - */ - private final List listeners - = new ArrayList(); - - /** - * The type of the media for this combo. - */ - private final int type; - - /** - * Creates device combobox model - * @param parent the parent component - * @param deviceConfiguration the current device configuration - * @param type the device - audio/video - */ - public DeviceConfigurationComboBoxModel( - DeviceConfiguration deviceConfiguration, - int type) - { - if (deviceConfiguration == null) - throw new IllegalArgumentException("deviceConfiguration"); - if ((type != AUDIO) - && (type != AUDIO_CAPTURE) - && (type != AUDIO_NOTIFY) - && (type != AUDIO_PLAYBACK) - && (type != VIDEO)) - throw new IllegalArgumentException("type"); - - this.deviceConfiguration = deviceConfiguration; - this.type = type; - - if (type == AUDIO - || type == AUDIO_CAPTURE - || type == AUDIO_NOTIFY - || type == AUDIO_PLAYBACK) - { - deviceConfiguration.addPropertyChangeListener(this); - } - } - - public void addListDataListener(ListDataListener listener) - { - if (listener == null) - throw new IllegalArgumentException("listener"); - - if (!listeners.contains(listener)) - listeners.add(listener); - } - - /** - * Change of the content. - * @param index0 from index. - * @param index1 to index. - */ - protected void fireContentsChanged(int index0, int index1) - { - ListDataListener[] listeners - = this.listeners.toArray( - new ListDataListener[this.listeners.size()]); - ListDataEvent event - = new ListDataEvent( - this, - ListDataEvent.CONTENTS_CHANGED, - index0, - index1); - - for (ListDataListener listener : listeners) - listener.contentsChanged(event); - } - - private AudioSystem[] getAudioSystems() - { - if (type != AUDIO) - throw new IllegalStateException("type"); - - audioSystems = deviceConfiguration.getAvailableAudioSystems(); - return audioSystems; - } - - /** - * Extracts the devices for the current type. - * @return the devices. - */ - private CaptureDevice[] getDevices() - { - if (type == AUDIO) - throw new IllegalStateException("type"); - - if (devices != null) - return devices; - - AudioSystem audioSystem; - List infos = null; - - switch (type) - { - case AUDIO_CAPTURE: - audioSystem = deviceConfiguration.getAudioSystem(); - infos = (audioSystem == null) - ? null - : audioSystem.getDevices(AudioSystem.DataFlow.CAPTURE); - break; - case AUDIO_NOTIFY: - audioSystem = deviceConfiguration.getAudioSystem(); - infos = (audioSystem == null) - ? null - : audioSystem.getDevices(AudioSystem.DataFlow.NOTIFY); - break; - case AUDIO_PLAYBACK: - audioSystem = deviceConfiguration.getAudioSystem(); - infos = (audioSystem == null) - ? null - : audioSystem.getDevices(AudioSystem.DataFlow.PLAYBACK); - break; - case VIDEO: - infos = deviceConfiguration.getAvailableVideoCaptureDevices( - MediaUseCase.CALL); - break; - default: - throw new IllegalStateException("type"); - } - - final int deviceCount = (infos == null) ? 0 : infos.size(); - devices = new CaptureDevice[deviceCount + 1]; - - if (deviceCount > 0) - { - for (int i = 0; i < deviceCount; i++) - devices[i] = new CaptureDevice(infos.get(i)); - } - devices[deviceCount] = new CaptureDevice(null); - - return devices; - } - - public Object getElementAt(int index) - { - if (type == AUDIO) - return getAudioSystems()[index]; - else - return getDevices()[index]; - } - - /** - * Extracts the devices selected by the configuration. - * @return CaptureDevice selected - */ - private CaptureDevice getSelectedDevice() - { - AudioSystem audioSystem; - CaptureDeviceInfo info; - - switch (type) - { - case AUDIO_CAPTURE: - audioSystem = deviceConfiguration.getAudioSystem(); - info = (audioSystem == null) - ? null - : audioSystem.getSelectedDevice(AudioSystem.DataFlow.CAPTURE); - break; - case AUDIO_NOTIFY: - audioSystem = deviceConfiguration.getAudioSystem(); - info = (audioSystem == null) - ? null - : audioSystem.getSelectedDevice(AudioSystem.DataFlow.NOTIFY); - break; - case AUDIO_PLAYBACK: - audioSystem = deviceConfiguration.getAudioSystem(); - info = (audioSystem == null) - ? null - : audioSystem.getSelectedDevice(AudioSystem.DataFlow.PLAYBACK); - break; - case VIDEO: - info = deviceConfiguration.getVideoCaptureDevice(MediaUseCase.ANY); - break; - default: - throw new IllegalStateException("type"); - } - - for (CaptureDevice device : getDevices()) - { - if (device.equals(info)) - return device; - } - return null; - } - - public Object getSelectedItem() - { - if (type == AUDIO) - return deviceConfiguration.getAudioSystem(); - else - return getSelectedDevice(); - } - - public int getSize() - { - if (type == AUDIO) - return getAudioSystems().length; - else - return getDevices().length; - } - - /** - * Notifies this instance about changes in the values of the properties of - * {@link #deviceConfiguration} so that this instance keeps itself - * up-to-date with respect to the list of devices. - * - * @param ev a PropertyChangeEvent which describes the name of the - * property whose value has changed and the old and new values of that - * property - */ - public void propertyChange(final PropertyChangeEvent ev) - { - if (DeviceConfiguration.PROP_AUDIO_SYSTEM_DEVICES.equals( - ev.getPropertyName())) - { - if (SwingUtilities.isEventDispatchThread()) - { - audioSystems = null; - devices = null; - fireContentsChanged(0, getSize() - 1); - } - else - { - SwingUtilities.invokeLater( - new Runnable() - { - public void run() - { - propertyChange(ev); - } - }); - } - } - } - - public void removeListDataListener(ListDataListener listener) - { - if (listener == null) - throw new IllegalArgumentException("listener"); - - listeners.remove(listener); - } - - /** - * Selects and saves the new choice. - * @param device the device we choose. - */ - private void setSelectedDevice(CaptureDevice device) - { - // We cannot clear the selection of DeviceConfiguration. - if (device == null) - return; - - CaptureDevice selectedDevice = getSelectedDevice(); - - if (selectedDevice != device) - { - AudioSystem audioSystem; - - switch (type) - { - case AUDIO_CAPTURE: - audioSystem = deviceConfiguration.getAudioSystem(); - if (audioSystem != null) - { - audioSystem.setDevice( - AudioSystem.DataFlow.CAPTURE, - ((CaptureDeviceInfo2) device.info), - true); - } - break; - case AUDIO_NOTIFY: - audioSystem = deviceConfiguration.getAudioSystem(); - if (audioSystem != null) - { - audioSystem.setDevice( - AudioSystem.DataFlow.NOTIFY, - ((CaptureDeviceInfo2) device.info), - true); - } - break; - case AUDIO_PLAYBACK: - audioSystem = deviceConfiguration.getAudioSystem(); - if (audioSystem != null) - { - audioSystem.setDevice( - AudioSystem.DataFlow.PLAYBACK, - ((CaptureDeviceInfo2) device.info), - true); - } - break; - case VIDEO: - deviceConfiguration.setVideoCaptureDevice(device.info, true); - break; - } - - fireContentsChanged(-1, -1); - } - } - - public void setSelectedItem(Object item) - { - if (type == AUDIO) - { - AudioSystem audioSystem = (AudioSystem) item; - - if(!audioSystem.equals(deviceConfiguration.getAudioSystem())) - { - deviceConfiguration.setAudioSystem(audioSystem, true); - fireContentsChanged(-1, -1); - } - } - else - setSelectedDevice((CaptureDevice) item); - } - - /** - * Encapsulates a CaptureDeviceInfo for the purposes of its display - * in the user interface. - */ - public static class CaptureDevice - { - /** - * The encapsulated info. - */ - public final CaptureDeviceInfo info; - - /** - * Creates the wrapper. - * @param info the info object we wrap. - */ - public CaptureDevice(CaptureDeviceInfo info) - { - this.info = info; - } - - /** - * Determines whether the CaptureDeviceInfo encapsulated by - * this instance is equal (by value) to a specific - * CaptureDeviceInfo. - * - * @param cdi the CaptureDeviceInfo to be determined whether it - * is equal (by value) to the CaptureDeviceInfo encapsulated by - * this instance - * @return true if the CaptureDeviceInfo encapsulated - * by this instance is equal (by value) to the specified cdi; - * otherwise, false - */ - public boolean equals(CaptureDeviceInfo cdi) - { - return (info == null) ? (cdi == null) : info.equals(cdi); - } - - /** - * Gets a human-readable String representation of this - * instance. - * - * @return a String value which is a human-readable - * representation of this instance - */ - @Override - public String toString() - { - String s; - - if(info == null) - { - s - = NeomediaActivator.getResources().getI18NString( - "impl.media.configform.NO_DEVICE"); - } - else - { - s = info.getName(); - if(info instanceof CaptureDeviceInfo2) - { - String transportType - = ((CaptureDeviceInfo2) info).getTransportType(); - - if(transportType != null) - s += " (" + transportType + ")"; - } - } - return s; - } - } -} +package net.java.sip.communicator.impl.neomedia; + +import java.beans.*; +import java.util.*; + +import javax.media.*; +import javax.swing.*; +import javax.swing.event.*; + +import org.jitsi.impl.neomedia.device.*; +import org.jitsi.service.neomedia.*; + +/** + * Implements ComboBoxModel for a specific DeviceConfiguration + * so that the latter may be displayed and manipulated in the user interface as + * a combo box. + * + * @author Lyubomir Marinov + * @author Damian Minkov + */ +public class DeviceConfigurationComboBoxModel + implements ComboBoxModel, + ListModel, + PropertyChangeListener +{ + /** + * Type of the model - audio. + */ + public static final int AUDIO = 1; + + /** + * Audio Capture Device. + */ + public static final int AUDIO_CAPTURE = 3; + + /** + * Audio device for notification sounds. + */ + public static final int AUDIO_NOTIFY = 5; + + /** + * Audio playback device. + */ + public static final int AUDIO_PLAYBACK = 4; + + /** + * Type of the model - video. + */ + public static final int VIDEO = 2; + + private AudioSystem[] audioSystems; + + /** + * The current device configuration. + */ + private final DeviceConfiguration deviceConfiguration; + + /** + * All the devices. + */ + private CaptureDevice[] devices; + + /** + * The ListDataListeners registered with this instance. + */ + private final List listeners + = new ArrayList(); + + /** + * The type of the media for this combo. + */ + private final int type; + + /** + * Creates device combobox model + * @param parent the parent component + * @param deviceConfiguration the current device configuration + * @param type the device - audio/video + */ + public DeviceConfigurationComboBoxModel( + DeviceConfiguration deviceConfiguration, + int type) + { + if (deviceConfiguration == null) + throw new IllegalArgumentException("deviceConfiguration"); + if ((type != AUDIO) + && (type != AUDIO_CAPTURE) + && (type != AUDIO_NOTIFY) + && (type != AUDIO_PLAYBACK) + && (type != VIDEO)) + throw new IllegalArgumentException("type"); + + this.deviceConfiguration = deviceConfiguration; + this.type = type; + + if (type == AUDIO + || type == AUDIO_CAPTURE + || type == AUDIO_NOTIFY + || type == AUDIO_PLAYBACK) + { + deviceConfiguration.addPropertyChangeListener(this); + } + } + + public void addListDataListener(ListDataListener listener) + { + if (listener == null) + throw new IllegalArgumentException("listener"); + + if (!listeners.contains(listener)) + listeners.add(listener); + } + + /** + * Change of the content. + * @param index0 from index. + * @param index1 to index. + */ + protected void fireContentsChanged(int index0, int index1) + { + ListDataListener[] listeners + = this.listeners.toArray( + new ListDataListener[this.listeners.size()]); + ListDataEvent event + = new ListDataEvent( + this, + ListDataEvent.CONTENTS_CHANGED, + index0, + index1); + + for (ListDataListener listener : listeners) + listener.contentsChanged(event); + } + + private AudioSystem[] getAudioSystems() + { + if (type != AUDIO) + throw new IllegalStateException("type"); + + audioSystems = deviceConfiguration.getAvailableAudioSystems(); + return audioSystems; + } + + /** + * Extracts the devices for the current type. + * @return the devices. + */ + private CaptureDevice[] getDevices() + { + if (type == AUDIO) + throw new IllegalStateException("type"); + + if (devices != null) + return devices; + + AudioSystem audioSystem; + List infos = null; + + switch (type) + { + case AUDIO_CAPTURE: + audioSystem = deviceConfiguration.getAudioSystem(); + infos = (audioSystem == null) + ? null + : audioSystem.getDevices(AudioSystem.DataFlow.CAPTURE); + break; + case AUDIO_NOTIFY: + audioSystem = deviceConfiguration.getAudioSystem(); + infos = (audioSystem == null) + ? null + : audioSystem.getDevices(AudioSystem.DataFlow.NOTIFY); + break; + case AUDIO_PLAYBACK: + audioSystem = deviceConfiguration.getAudioSystem(); + infos = (audioSystem == null) + ? null + : audioSystem.getDevices(AudioSystem.DataFlow.PLAYBACK); + break; + case VIDEO: + infos = deviceConfiguration.getAvailableVideoCaptureDevices( + MediaUseCase.CALL); + break; + default: + throw new IllegalStateException("type"); + } + + final int deviceCount = (infos == null) ? 0 : infos.size(); + devices = new CaptureDevice[deviceCount + 1]; + + if (deviceCount > 0) + { + for (int i = 0; i < deviceCount; i++) + devices[i] = new CaptureDevice(infos.get(i)); + } + devices[deviceCount] = new CaptureDevice(null); + + return devices; + } + + public Object getElementAt(int index) + { + if (type == AUDIO) + return getAudioSystems()[index]; + else + return getDevices()[index]; + } + + /** + * Extracts the devices selected by the configuration. + * @return CaptureDevice selected + */ + private CaptureDevice getSelectedDevice() + { + AudioSystem audioSystem; + CaptureDeviceInfo info; + + switch (type) + { + case AUDIO_CAPTURE: + audioSystem = deviceConfiguration.getAudioSystem(); + info = (audioSystem == null) + ? null + : audioSystem.getSelectedDevice(AudioSystem.DataFlow.CAPTURE); + break; + case AUDIO_NOTIFY: + audioSystem = deviceConfiguration.getAudioSystem(); + info = (audioSystem == null) + ? null + : audioSystem.getSelectedDevice(AudioSystem.DataFlow.NOTIFY); + break; + case AUDIO_PLAYBACK: + audioSystem = deviceConfiguration.getAudioSystem(); + info = (audioSystem == null) + ? null + : audioSystem.getSelectedDevice(AudioSystem.DataFlow.PLAYBACK); + break; + case VIDEO: + info = deviceConfiguration.getVideoCaptureDevice(MediaUseCase.ANY); + break; + default: + throw new IllegalStateException("type"); + } + + for (CaptureDevice device : getDevices()) + { + if (device.equals(info)) + return device; + } + return null; + } + + public Object getSelectedItem() + { + if (type == AUDIO) + return deviceConfiguration.getAudioSystem(); + else + return getSelectedDevice(); + } + + public int getSize() + { + if (type == AUDIO) + return getAudioSystems().length; + else + return getDevices().length; + } + + /** + * Notifies this instance about changes in the values of the properties of + * {@link #deviceConfiguration} so that this instance keeps itself + * up-to-date with respect to the list of devices. + * + * @param ev a PropertyChangeEvent which describes the name of the + * property whose value has changed and the old and new values of that + * property + */ + public void propertyChange(final PropertyChangeEvent ev) + { + if (DeviceConfiguration.PROP_AUDIO_SYSTEM_DEVICES.equals( + ev.getPropertyName())) + { + if (SwingUtilities.isEventDispatchThread()) + { + audioSystems = null; + devices = null; + fireContentsChanged(0, getSize() - 1); + } + else + { + SwingUtilities.invokeLater( + new Runnable() + { + public void run() + { + propertyChange(ev); + } + }); + } + } + } + + public void removeListDataListener(ListDataListener listener) + { + if (listener == null) + throw new IllegalArgumentException("listener"); + + listeners.remove(listener); + } + + /** + * Selects and saves the new choice. + * @param device the device we choose. + */ + private void setSelectedDevice(CaptureDevice device) + { + // We cannot clear the selection of DeviceConfiguration. + if (device == null) + return; + + CaptureDevice selectedDevice = getSelectedDevice(); + + if (selectedDevice != device) + { + AudioSystem audioSystem; + + switch (type) + { + case AUDIO_CAPTURE: + audioSystem = deviceConfiguration.getAudioSystem(); + if (audioSystem != null) + { + audioSystem.setDevice( + AudioSystem.DataFlow.CAPTURE, + ((CaptureDeviceInfo2) device.info), + true); + } + break; + case AUDIO_NOTIFY: + audioSystem = deviceConfiguration.getAudioSystem(); + if (audioSystem != null) + { + audioSystem.setDevice( + AudioSystem.DataFlow.NOTIFY, + ((CaptureDeviceInfo2) device.info), + true); + } + break; + case AUDIO_PLAYBACK: + audioSystem = deviceConfiguration.getAudioSystem(); + if (audioSystem != null) + { + audioSystem.setDevice( + AudioSystem.DataFlow.PLAYBACK, + ((CaptureDeviceInfo2) device.info), + true); + } + break; + case VIDEO: + deviceConfiguration.setVideoCaptureDevice(device.info, true); + break; + } + + fireContentsChanged(-1, -1); + } + } + + public void setSelectedItem(Object item) + { + if (type == AUDIO) + { + AudioSystem audioSystem = (AudioSystem) item; + + if(!audioSystem.equals(deviceConfiguration.getAudioSystem())) + { + deviceConfiguration.setAudioSystem(audioSystem, true); + fireContentsChanged(-1, -1); + } + } + else + setSelectedDevice((CaptureDevice) item); + } + + /** + * Encapsulates a CaptureDeviceInfo for the purposes of its display + * in the user interface. + */ + public static class CaptureDevice + { + /** + * The encapsulated info. + */ + public final CaptureDeviceInfo info; + + /** + * Creates the wrapper. + * @param info the info object we wrap. + */ + public CaptureDevice(CaptureDeviceInfo info) + { + this.info = info; + } + + /** + * Determines whether the CaptureDeviceInfo encapsulated by + * this instance is equal (by value) to a specific + * CaptureDeviceInfo. + * + * @param cdi the CaptureDeviceInfo to be determined whether it + * is equal (by value) to the CaptureDeviceInfo encapsulated by + * this instance + * @return true if the CaptureDeviceInfo encapsulated + * by this instance is equal (by value) to the specified cdi; + * otherwise, false + */ + public boolean equals(CaptureDeviceInfo cdi) + { + return (info == null) ? (cdi == null) : info.equals(cdi); + } + + /** + * Gets a human-readable String representation of this + * instance. + * + * @return a String value which is a human-readable + * representation of this instance + */ + @Override + public String toString() + { + String s; + + if(info == null) + { + s + = NeomediaActivator.getResources().getI18NString( + "impl.media.configform.NO_DEVICE"); + } + else + { + s = info.getName(); + if(info instanceof CaptureDeviceInfo2) + { + String transportType + = ((CaptureDeviceInfo2) info).getTransportType(); + + if(transportType != null) + s += " (" + transportType + ")"; + } + } + return s; + } + } +} diff --git a/src/net/java/sip/communicator/impl/neomedia/EncodingConfigurationTableModel.java b/src/net/java/sip/communicator/impl/neomedia/EncodingConfigurationTableModel.java index 925184c..f8cf447 100644 --- a/src/net/java/sip/communicator/impl/neomedia/EncodingConfigurationTableModel.java +++ b/src/net/java/sip/communicator/impl/neomedia/EncodingConfigurationTableModel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,272 +15,272 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.neomedia; - -import java.util.*; - -import javax.swing.table.*; - -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.jitsi.impl.neomedia.*; -import org.jitsi.impl.neomedia.format.*; -import org.jitsi.service.neomedia.*; -import org.jitsi.service.neomedia.codec.*; -import org.jitsi.service.neomedia.format.*; - -/** - * Implements {@link TableModel} for {@link EncodingConfiguration}. - * - * @author Lyubomir Marinov - */ -public class EncodingConfigurationTableModel - extends MoveableTableModel -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private final EncodingConfiguration encodingConfiguration; - - private MediaFormat[] encodings; - - private final MediaType type; - - /** - * Constructor. - * - * @param encodingConfiguration the encoding configuration - * @param type media type - */ - public EncodingConfigurationTableModel(int type, - EncodingConfiguration encodingConfiguration) - { - if (encodingConfiguration == null) - throw new IllegalArgumentException("encodingConfiguration"); - this.encodingConfiguration = encodingConfiguration; - - switch (type) - { - case DeviceConfigurationComboBoxModel.AUDIO: - this.type = MediaType.AUDIO; - break; - case DeviceConfigurationComboBoxModel.VIDEO: - this.type = MediaType.VIDEO; - break; - default: - throw new IllegalArgumentException("type"); - } - } - - @Override - public Class getColumnClass(int columnIndex) - { - return - (columnIndex == 0) - ? Boolean.class - : super.getColumnClass(columnIndex); - } - - public int getColumnCount() - { - return 2; - } - - private MediaFormat[] getEncodings() - { - if (encodings != null) - return encodings; - - MediaFormat[] availableEncodings - = encodingConfiguration.getAllEncodings(type); - int encodingCount = availableEncodings.length; - - if (encodingCount < 1) - encodings = MediaUtils.EMPTY_MEDIA_FORMATS; - else - { - /* - * The MediaFormats will be displayed by encoding (name) and clock - * rate and EncodingConfiguration will store them that way so this - * TableModel should better display unique encoding-clock rate - * pairs. - */ - HashMap availableEncodingSet - = new HashMap(); - - for (MediaFormat availableEncoding : availableEncodings) - { - availableEncodingSet.put( - availableEncoding.getEncoding() - + "/" - + availableEncoding.getClockRateString(), - availableEncoding); - } - availableEncodings - = availableEncodingSet.values().toArray( - MediaUtils.EMPTY_MEDIA_FORMATS); - encodingCount = availableEncodings.length; - - encodings = new MediaFormat[encodingCount]; - System - .arraycopy(availableEncodings, 0, encodings, 0, encodingCount); - // Display the encodings in decreasing priority. - Arrays - .sort(encodings, 0, encodingCount, new Comparator() - { - public int compare(MediaFormat format0, MediaFormat format1) - { - int ret - = encodingConfiguration.getPriority(format1) - - encodingConfiguration.getPriority(format0); - - if (ret == 0) - { - /* - * In the cases of equal priorities, display them - * sorted by encoding name in increasing order. - */ - ret - = format0.getEncoding().compareToIgnoreCase( - format1.getEncoding()); - if (ret == 0) - { - /* - * In the cases of equal priorities and equal - * encoding names, display them sorted by clock - * rate in decreasing order. - */ - ret - = Double.compare( - format1.getClockRate(), - format0.getClockRate()); - } - } - return ret; - } - }); - } - return encodings; - } - - private int[] getPriorities() - { - MediaFormat[] encodings = getEncodings(); - final int count = encodings.length; - int[] priorities = new int[count]; - - for (int i = 0; i < count; i++) - { - int priority = encodingConfiguration.getPriority(encodings[i]); - - priorities[i] = (priority > 0) ? (count - i) : 0; - } - return priorities; - } - - public int getRowCount() - { - return getEncodings().length; - } - - public Object getValueAt(int rowIndex, int columnIndex) - { - MediaFormat encoding = getEncodings()[rowIndex]; - - switch (columnIndex) - { - case 0: - return (encodingConfiguration.getPriority(encoding) > 0); - case 1: - if (MediaType.VIDEO.equals(encoding.getMediaType()) - && (VideoMediaFormatImpl.DEFAULT_CLOCK_RATE - == encoding.getClockRate())) - return encoding.getEncoding(); - else - { - return encoding.getEncoding() - + "/" - + encoding.getRealUsedClockRateString(); - } - default: - return null; - } - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) - { - return (columnIndex == 0); - } - - /** - * Move the row. - * - * @param rowIndex index of the row - * @param up true to move up, false to move down - * @return the next row index - */ - @Override - public int move(int rowIndex, boolean up) - { - if (up) - { - if (rowIndex <= 0) - throw new IllegalArgumentException("rowIndex"); - - return move(rowIndex - 1, false) - 1; - } - - if (rowIndex >= (getRowCount() - 1)) - throw new IllegalArgumentException("rowIndex"); - - int[] priorities = getPriorities(); - final int nextRowIndex = rowIndex + 1; - - if (priorities[rowIndex] > 0) - priorities[rowIndex] = priorities.length - nextRowIndex; - if (priorities[nextRowIndex] > 0) - priorities[nextRowIndex] = priorities.length - rowIndex; - setPriorities(priorities); - - MediaFormat swap = encodings[rowIndex]; - - encodings[rowIndex] = encodings[nextRowIndex]; - encodings[nextRowIndex] = swap; - - fireTableRowsUpdated(rowIndex, nextRowIndex); - return nextRowIndex; - } - - private void setPriorities(int[] priorities) - { - final int count = encodings.length; - - if (priorities.length != count) - throw new IllegalArgumentException("priorities"); - for (int i = 0; i < count; i++) - { - encodingConfiguration.setPriority(encodings[i], priorities[i]); - } - } - - @Override - public void setValueAt(Object value, int rowIndex, int columnIndex) - { - if ((columnIndex == 0) && (value instanceof Boolean)) - { - int priority - = ((Boolean) value) ? (getPriorities().length - rowIndex) : 0; - MediaFormat encoding = encodings[rowIndex]; - - - // We fire the update event before setting the configuration - // property in order to have more reactive user interface. - fireTableCellUpdated(rowIndex, columnIndex); - - encodingConfiguration.setPriority(encoding, priority); - } - } -} +package net.java.sip.communicator.impl.neomedia; + +import java.util.*; + +import javax.swing.table.*; + +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.impl.neomedia.*; +import org.jitsi.impl.neomedia.format.*; +import org.jitsi.service.neomedia.*; +import org.jitsi.service.neomedia.codec.*; +import org.jitsi.service.neomedia.format.*; + +/** + * Implements {@link TableModel} for {@link EncodingConfiguration}. + * + * @author Lyubomir Marinov + */ +public class EncodingConfigurationTableModel + extends MoveableTableModel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private final EncodingConfiguration encodingConfiguration; + + private MediaFormat[] encodings; + + private final MediaType type; + + /** + * Constructor. + * + * @param encodingConfiguration the encoding configuration + * @param type media type + */ + public EncodingConfigurationTableModel(int type, + EncodingConfiguration encodingConfiguration) + { + if (encodingConfiguration == null) + throw new IllegalArgumentException("encodingConfiguration"); + this.encodingConfiguration = encodingConfiguration; + + switch (type) + { + case DeviceConfigurationComboBoxModel.AUDIO: + this.type = MediaType.AUDIO; + break; + case DeviceConfigurationComboBoxModel.VIDEO: + this.type = MediaType.VIDEO; + break; + default: + throw new IllegalArgumentException("type"); + } + } + + @Override + public Class getColumnClass(int columnIndex) + { + return + (columnIndex == 0) + ? Boolean.class + : super.getColumnClass(columnIndex); + } + + public int getColumnCount() + { + return 2; + } + + private MediaFormat[] getEncodings() + { + if (encodings != null) + return encodings; + + MediaFormat[] availableEncodings + = encodingConfiguration.getAllEncodings(type); + int encodingCount = availableEncodings.length; + + if (encodingCount < 1) + encodings = MediaUtils.EMPTY_MEDIA_FORMATS; + else + { + /* + * The MediaFormats will be displayed by encoding (name) and clock + * rate and EncodingConfiguration will store them that way so this + * TableModel should better display unique encoding-clock rate + * pairs. + */ + HashMap availableEncodingSet + = new HashMap(); + + for (MediaFormat availableEncoding : availableEncodings) + { + availableEncodingSet.put( + availableEncoding.getEncoding() + + "/" + + availableEncoding.getClockRateString(), + availableEncoding); + } + availableEncodings + = availableEncodingSet.values().toArray( + MediaUtils.EMPTY_MEDIA_FORMATS); + encodingCount = availableEncodings.length; + + encodings = new MediaFormat[encodingCount]; + System + .arraycopy(availableEncodings, 0, encodings, 0, encodingCount); + // Display the encodings in decreasing priority. + Arrays + .sort(encodings, 0, encodingCount, new Comparator() + { + public int compare(MediaFormat format0, MediaFormat format1) + { + int ret + = encodingConfiguration.getPriority(format1) + - encodingConfiguration.getPriority(format0); + + if (ret == 0) + { + /* + * In the cases of equal priorities, display them + * sorted by encoding name in increasing order. + */ + ret + = format0.getEncoding().compareToIgnoreCase( + format1.getEncoding()); + if (ret == 0) + { + /* + * In the cases of equal priorities and equal + * encoding names, display them sorted by clock + * rate in decreasing order. + */ + ret + = Double.compare( + format1.getClockRate(), + format0.getClockRate()); + } + } + return ret; + } + }); + } + return encodings; + } + + private int[] getPriorities() + { + MediaFormat[] encodings = getEncodings(); + final int count = encodings.length; + int[] priorities = new int[count]; + + for (int i = 0; i < count; i++) + { + int priority = encodingConfiguration.getPriority(encodings[i]); + + priorities[i] = (priority > 0) ? (count - i) : 0; + } + return priorities; + } + + public int getRowCount() + { + return getEncodings().length; + } + + public Object getValueAt(int rowIndex, int columnIndex) + { + MediaFormat encoding = getEncodings()[rowIndex]; + + switch (columnIndex) + { + case 0: + return (encodingConfiguration.getPriority(encoding) > 0); + case 1: + if (MediaType.VIDEO.equals(encoding.getMediaType()) + && (VideoMediaFormatImpl.DEFAULT_CLOCK_RATE + == encoding.getClockRate())) + return encoding.getEncoding(); + else + { + return encoding.getEncoding() + + "/" + + encoding.getRealUsedClockRateString(); + } + default: + return null; + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) + { + return (columnIndex == 0); + } + + /** + * Move the row. + * + * @param rowIndex index of the row + * @param up true to move up, false to move down + * @return the next row index + */ + @Override + public int move(int rowIndex, boolean up) + { + if (up) + { + if (rowIndex <= 0) + throw new IllegalArgumentException("rowIndex"); + + return move(rowIndex - 1, false) - 1; + } + + if (rowIndex >= (getRowCount() - 1)) + throw new IllegalArgumentException("rowIndex"); + + int[] priorities = getPriorities(); + final int nextRowIndex = rowIndex + 1; + + if (priorities[rowIndex] > 0) + priorities[rowIndex] = priorities.length - nextRowIndex; + if (priorities[nextRowIndex] > 0) + priorities[nextRowIndex] = priorities.length - rowIndex; + setPriorities(priorities); + + MediaFormat swap = encodings[rowIndex]; + + encodings[rowIndex] = encodings[nextRowIndex]; + encodings[nextRowIndex] = swap; + + fireTableRowsUpdated(rowIndex, nextRowIndex); + return nextRowIndex; + } + + private void setPriorities(int[] priorities) + { + final int count = encodings.length; + + if (priorities.length != count) + throw new IllegalArgumentException("priorities"); + for (int i = 0; i < count; i++) + { + encodingConfiguration.setPriority(encodings[i], priorities[i]); + } + } + + @Override + public void setValueAt(Object value, int rowIndex, int columnIndex) + { + if ((columnIndex == 0) && (value instanceof Boolean)) + { + int priority + = ((Boolean) value) ? (getPriorities().length - rowIndex) : 0; + MediaFormat encoding = encodings[rowIndex]; + + + // We fire the update event before setting the configuration + // property in order to have more reactive user interface. + fireTableCellUpdated(rowIndex, columnIndex); + + encodingConfiguration.setPriority(encoding, priority); + } + } +} diff --git a/src/net/java/sip/communicator/impl/osdependent/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/SystemTray.java index 0c0a4a2..b9d4d45 100644 --- a/src/net/java/sip/communicator/impl/osdependent/SystemTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/SystemTray.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,201 +15,201 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.osdependent; - -import java.awt.*; -import java.lang.reflect.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.osdependent.TrayIcon.AWTTrayIconPeer; -import net.java.sip.communicator.impl.osdependent.TrayIcon.TrayIconPeer; -import net.java.sip.communicator.util.*; - -/** - * @author Lubomir Marinov - */ -public class SystemTray -{ - /** - * The Logger used by the SystemTray class and its - * instances for logging output. - */ - private static final Logger logger = Logger.getLogger(SystemTray.class); - - private static SystemTray defaultSystemTray; - - public static SystemTray getDefaultSystemTray() - throws UnsupportedOperationException, - HeadlessException, - SecurityException - { - if (defaultSystemTray != null) - return defaultSystemTray; - - Class awtSystemTrayClass = null; - try - { - awtSystemTrayClass = Class.forName("java.awt.SystemTray"); - } - catch (ClassNotFoundException ex) - { - // We'll try org.jdesktop.jdic.tray then. - } - SystemTrayPeer peer = null; - if (awtSystemTrayClass != null) - try - { - peer = new AWTSystemTrayPeer(awtSystemTrayClass); - } - catch (Exception ex) - { - if(!GraphicsEnvironment.isHeadless()) - logger.error("Failed to initialize java.awt.SystemTray", - ex); - - // We'll try org.jdesktop.jdic.tray then. - } - if (peer == null) - { - logger.error( - "Failed to initialize the desktop.tray implementation."); - throw new UnsupportedOperationException( - "Failed to initialize the desktop.tray implementation."); - } - return (defaultSystemTray = new SystemTray(peer)); - } - - private final SystemTrayPeer peer; - - private SystemTray(SystemTrayPeer peer) - { - this.peer = peer; - } - - public void addTrayIcon(TrayIcon trayIcon) - throws NullPointerException, - IllegalArgumentException - { - if (peer != null) - peer.addTrayIcon(trayIcon.getPeer()); - } - - SystemTrayPeer getPeer() - { - return peer; - } - - public boolean isSwing() - { - if (peer != null) - return getPeer().isSwing(); - return false; - } - - static interface SystemTrayPeer - { - void addTrayIcon(TrayIconPeer trayIconPeer) - throws NullPointerException, - IllegalArgumentException; - - TrayIconPeer createTrayIcon(ImageIcon icon, - String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException; - - boolean isSwing(); - } - - private static class AWTSystemTrayPeer - implements SystemTrayPeer - { - private final Method addTrayIcon; - - private final Object impl; - - private final Class trayIconClass; - - public AWTSystemTrayPeer(Class clazz) - throws UnsupportedOperationException, - HeadlessException, - SecurityException - { - Method getDefaultSystemTray; - try - { - getDefaultSystemTray = - clazz.getMethod("getSystemTray", (Class[]) null); - trayIconClass = Class.forName("java.awt.TrayIcon"); - addTrayIcon = clazz.getMethod("add", new Class[] - { trayIconClass }); - } - catch (ClassNotFoundException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (NoSuchMethodException ex) - { - throw new UnsupportedOperationException(ex); - } - - try - { - impl = getDefaultSystemTray.invoke(null, (Object[]) null); - } - catch (IllegalAccessException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InvocationTargetException ex) - { - throw new UnsupportedOperationException(ex); - } - } - - public void addTrayIcon(TrayIconPeer trayIconPeer) - throws NullPointerException, - IllegalArgumentException - { - try - { - addTrayIcon.invoke(impl, new Object[] - { ((AWTTrayIconPeer) trayIconPeer).getImpl() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause == null) - throw new UndeclaredThrowableException(ex); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - if (cause instanceof IllegalArgumentException) - throw (IllegalArgumentException) cause; - throw new UndeclaredThrowableException(cause); - } - } - - public TrayIconPeer createTrayIcon(ImageIcon icon, String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - return new AWTTrayIconPeer(trayIconClass, (icon == null) ? null - : icon.getImage(), tooltip, popup); - } - - public boolean isSwing() - { - return false; - } - } -} +package net.java.sip.communicator.impl.osdependent; + +import java.awt.*; +import java.lang.reflect.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.osdependent.TrayIcon.AWTTrayIconPeer; +import net.java.sip.communicator.impl.osdependent.TrayIcon.TrayIconPeer; +import net.java.sip.communicator.util.*; + +/** + * @author Lubomir Marinov + */ +public class SystemTray +{ + /** + * The Logger used by the SystemTray class and its + * instances for logging output. + */ + private static final Logger logger = Logger.getLogger(SystemTray.class); + + private static SystemTray defaultSystemTray; + + public static SystemTray getDefaultSystemTray() + throws UnsupportedOperationException, + HeadlessException, + SecurityException + { + if (defaultSystemTray != null) + return defaultSystemTray; + + Class awtSystemTrayClass = null; + try + { + awtSystemTrayClass = Class.forName("java.awt.SystemTray"); + } + catch (ClassNotFoundException ex) + { + // We'll try org.jdesktop.jdic.tray then. + } + SystemTrayPeer peer = null; + if (awtSystemTrayClass != null) + try + { + peer = new AWTSystemTrayPeer(awtSystemTrayClass); + } + catch (Exception ex) + { + if(!GraphicsEnvironment.isHeadless()) + logger.error("Failed to initialize java.awt.SystemTray", + ex); + + // We'll try org.jdesktop.jdic.tray then. + } + if (peer == null) + { + logger.error( + "Failed to initialize the desktop.tray implementation."); + throw new UnsupportedOperationException( + "Failed to initialize the desktop.tray implementation."); + } + return (defaultSystemTray = new SystemTray(peer)); + } + + private final SystemTrayPeer peer; + + private SystemTray(SystemTrayPeer peer) + { + this.peer = peer; + } + + public void addTrayIcon(TrayIcon trayIcon) + throws NullPointerException, + IllegalArgumentException + { + if (peer != null) + peer.addTrayIcon(trayIcon.getPeer()); + } + + SystemTrayPeer getPeer() + { + return peer; + } + + public boolean isSwing() + { + if (peer != null) + return getPeer().isSwing(); + return false; + } + + static interface SystemTrayPeer + { + void addTrayIcon(TrayIconPeer trayIconPeer) + throws NullPointerException, + IllegalArgumentException; + + TrayIconPeer createTrayIcon(ImageIcon icon, + String tooltip, + Object popup) + throws IllegalArgumentException, + UnsupportedOperationException, + HeadlessException, + SecurityException; + + boolean isSwing(); + } + + private static class AWTSystemTrayPeer + implements SystemTrayPeer + { + private final Method addTrayIcon; + + private final Object impl; + + private final Class trayIconClass; + + public AWTSystemTrayPeer(Class clazz) + throws UnsupportedOperationException, + HeadlessException, + SecurityException + { + Method getDefaultSystemTray; + try + { + getDefaultSystemTray = + clazz.getMethod("getSystemTray", (Class[]) null); + trayIconClass = Class.forName("java.awt.TrayIcon"); + addTrayIcon = clazz.getMethod("add", new Class[] + { trayIconClass }); + } + catch (ClassNotFoundException ex) + { + throw new UnsupportedOperationException(ex); + } + catch (NoSuchMethodException ex) + { + throw new UnsupportedOperationException(ex); + } + + try + { + impl = getDefaultSystemTray.invoke(null, (Object[]) null); + } + catch (IllegalAccessException ex) + { + throw new UnsupportedOperationException(ex); + } + catch (InvocationTargetException ex) + { + throw new UnsupportedOperationException(ex); + } + } + + public void addTrayIcon(TrayIconPeer trayIconPeer) + throws NullPointerException, + IllegalArgumentException + { + try + { + addTrayIcon.invoke(impl, new Object[] + { ((AWTTrayIconPeer) trayIconPeer).getImpl() }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + if (cause == null) + throw new UndeclaredThrowableException(ex); + if (cause instanceof NullPointerException) + throw (NullPointerException) cause; + if (cause instanceof IllegalArgumentException) + throw (IllegalArgumentException) cause; + throw new UndeclaredThrowableException(cause); + } + } + + public TrayIconPeer createTrayIcon(ImageIcon icon, String tooltip, + Object popup) + throws IllegalArgumentException, + UnsupportedOperationException, + HeadlessException, + SecurityException + { + return new AWTTrayIconPeer(trayIconClass, (icon == null) ? null + : icon.getImage(), tooltip, popup); + } + + public boolean isSwing() + { + return false; + } + } +} diff --git a/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java index 974ed96..d338dc4 100644 --- a/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,398 +15,398 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.osdependent; - -import java.awt.*; -import java.awt.event.*; -import java.lang.reflect.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.impl.osdependent.SystemTray.SystemTrayPeer; - -import org.jitsi.util.*; - -/** - * @author Lubomir Marinov - */ -public class TrayIcon -{ - private final TrayIconPeer peer; - - public TrayIcon(ImageIcon icon, String tooltip, Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - SystemTrayPeer systemTrayPeer = - SystemTray.getDefaultSystemTray().getPeer(); - if (systemTrayPeer != null) - peer = systemTrayPeer.createTrayIcon(icon, tooltip, popup); - else - peer = null; - } - - public void addActionListener(ActionListener listener) - { - if (peer != null) - peer.addActionListener(listener); - } - - public void addBalloonActionListener(ActionListener listener) - { - if (peer != null) - peer.addBalloonActionListener(listener); - } - - public void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException - { - if (peer != null) - peer.displayMessage(caption, text, messageType); - } - - TrayIconPeer getPeer() - { - return peer; - } - - public void setIcon(ImageIcon icon) throws NullPointerException - { - if (peer != null) - peer.setIcon(icon); - } - - public void setIconAutoSize(boolean autoSize) - { - if (peer != null) - peer.setIconAutoSize(autoSize); - } - - static interface TrayIconPeer - { - void addActionListener(ActionListener listener); - - void addBalloonActionListener(ActionListener listener); - - void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException; - - void setIcon(ImageIcon icon) throws NullPointerException; - - void setIconAutoSize(boolean autoSize); - } - - static class AWTTrayIconPeer - implements TrayIconPeer - { - private final Method addActionListener; - - private final Method addMouseListener; - - private final Method displayMessage; - - private final Object impl; - - private final Class messageTypeClass; - - private final Method setIcon; - - private final Method setIconAutoSize; - - public AWTTrayIconPeer(Class clazz, Image image, String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - Constructor constructor; - try - { - if (popup instanceof JPopupMenu) - { - constructor = clazz.getConstructor(new Class[] - { Image.class, String.class }); - } - else - { - constructor = clazz.getConstructor(new Class[] - { Image.class, String.class, PopupMenu.class }); - } - addActionListener = - clazz.getMethod("addActionListener", new Class[] - { ActionListener.class }); - addMouseListener = - clazz.getMethod("addMouseListener", new Class[] - { MouseListener.class }); - messageTypeClass = - Class.forName("java.awt.TrayIcon$MessageType"); - displayMessage = - clazz.getMethod("displayMessage", new Class[] - { String.class, String.class, messageTypeClass }); - setIcon = clazz.getMethod("setImage", new Class[] - { Image.class }); - setIconAutoSize = - clazz.getMethod("setImageAutoSize", new Class[] - { boolean.class }); - } - catch (ClassNotFoundException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (NoSuchMethodException ex) - { - throw new UnsupportedOperationException(ex); - } - - try - { - if (popup instanceof JPopupMenu) - { - impl = constructor.newInstance( - new Object[] { image, tooltip }); - addMouseListener(new AWTMouseAdapter((JPopupMenu) popup)); - } - else - { - impl = constructor.newInstance( - new Object[] { image, tooltip, popup }); - } - } - catch (IllegalAccessException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InstantiationException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause == null) - throw new UnsupportedOperationException(ex); - if (cause instanceof IllegalArgumentException) - throw (IllegalArgumentException) cause; - if (cause instanceof UnsupportedOperationException) - throw (UnsupportedOperationException) cause; - if (cause instanceof HeadlessException) - throw (HeadlessException) cause; - if (cause instanceof SecurityException) - throw (SecurityException) cause; - throw new UnsupportedOperationException(cause); - } - } - - public void addActionListener(ActionListener listener) - { - try - { - addActionListener.invoke(getImpl(), new Object[] - { listener }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void addMouseListener(MouseListener listener) - { - try - { - addMouseListener.invoke(getImpl(), new Object[] { listener }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void addBalloonActionListener(ActionListener listener) - { - // java.awt.TrayIcon doesn't support addBalloonActionListener() - } - - public void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException - { - try - { - displayMessage.invoke(getImpl(), new Object[] - { caption, text, messageType.name() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public Object getImpl() - { - return impl; - } - - public void setIcon(ImageIcon icon) throws NullPointerException - { - try - { - setIcon.invoke(getImpl(), new Object[] - { (icon == null) ? null : icon.getImage() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void setIconAutoSize(boolean autoSize) - { - try - { - setIconAutoSize.invoke(getImpl(), new Object[] - { autoSize }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - } - - /** - * Extended mouse adapter to show the JPopupMenu in Java 6 - * Based on : http://weblogs.java.net/blog/ixmal/archive/2006/05/using_jpopupmen.html - * And : http://weblogs.java.net/blog/alexfromsun/archive/2008/02/jtrayicon_updat.html - * - * Use a hidden JWindow (JDialog for Windows) to manage the JPopupMenu. - * - * @author Damien Roth - */ - private static class AWTMouseAdapter - extends MouseAdapter - { - private JPopupMenu popup = null; - private Window hiddenWindow = null; - - public AWTMouseAdapter(JPopupMenu p) - { - this.popup = p; - this.popup.addPopupMenuListener(new PopupMenuListener() - { - public void popupMenuWillBecomeVisible(PopupMenuEvent e) - {} - - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) - { - if (hiddenWindow != null) - { - hiddenWindow.dispose(); - hiddenWindow = null; - } - } - - public void popupMenuCanceled(PopupMenuEvent e) - { - if (hiddenWindow != null) - { - hiddenWindow.dispose(); - hiddenWindow = null; - } - } - }); - } - - @Override - public void mouseReleased(MouseEvent e) - { - showPopupMenu(e); - } - - @Override - public void mousePressed(MouseEvent e) - { - showPopupMenu(e); - } - - private void showPopupMenu(MouseEvent e) - { - if (e.isPopupTrigger() && popup != null) - { - if (hiddenWindow == null) - { - if (OSUtils.IS_WINDOWS) - { - hiddenWindow = new JDialog((Frame) null); - ((JDialog) hiddenWindow).setUndecorated(true); - } - else - hiddenWindow = new JWindow((Frame) null); - - hiddenWindow.setAlwaysOnTop(true); - Dimension size = popup.getPreferredSize(); - - Point centerPoint = GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getCenterPoint(); - - if(e.getY() > centerPoint.getY()) - hiddenWindow - .setLocation(e.getX(), e.getY() - size.height); - else - hiddenWindow - .setLocation(e.getX(), e.getY()); - - hiddenWindow.setVisible(true); - - popup.show( - ((RootPaneContainer)hiddenWindow).getContentPane(), - 0, 0); - - // popup works only for focused windows - hiddenWindow.toFront(); - } - } - } - } -} +package net.java.sip.communicator.impl.osdependent; + +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.*; + +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.impl.osdependent.SystemTray.SystemTrayPeer; + +import org.jitsi.util.*; + +/** + * @author Lubomir Marinov + */ +public class TrayIcon +{ + private final TrayIconPeer peer; + + public TrayIcon(ImageIcon icon, String tooltip, Object popup) + throws IllegalArgumentException, + UnsupportedOperationException, + HeadlessException, + SecurityException + { + SystemTrayPeer systemTrayPeer = + SystemTray.getDefaultSystemTray().getPeer(); + if (systemTrayPeer != null) + peer = systemTrayPeer.createTrayIcon(icon, tooltip, popup); + else + peer = null; + } + + public void addActionListener(ActionListener listener) + { + if (peer != null) + peer.addActionListener(listener); + } + + public void addBalloonActionListener(ActionListener listener) + { + if (peer != null) + peer.addBalloonActionListener(listener); + } + + public void displayMessage(String caption, String text, + java.awt.TrayIcon.MessageType messageType) + throws NullPointerException + { + if (peer != null) + peer.displayMessage(caption, text, messageType); + } + + TrayIconPeer getPeer() + { + return peer; + } + + public void setIcon(ImageIcon icon) throws NullPointerException + { + if (peer != null) + peer.setIcon(icon); + } + + public void setIconAutoSize(boolean autoSize) + { + if (peer != null) + peer.setIconAutoSize(autoSize); + } + + static interface TrayIconPeer + { + void addActionListener(ActionListener listener); + + void addBalloonActionListener(ActionListener listener); + + void displayMessage(String caption, String text, + java.awt.TrayIcon.MessageType messageType) + throws NullPointerException; + + void setIcon(ImageIcon icon) throws NullPointerException; + + void setIconAutoSize(boolean autoSize); + } + + static class AWTTrayIconPeer + implements TrayIconPeer + { + private final Method addActionListener; + + private final Method addMouseListener; + + private final Method displayMessage; + + private final Object impl; + + private final Class messageTypeClass; + + private final Method setIcon; + + private final Method setIconAutoSize; + + public AWTTrayIconPeer(Class clazz, Image image, String tooltip, + Object popup) + throws IllegalArgumentException, + UnsupportedOperationException, + HeadlessException, + SecurityException + { + Constructor constructor; + try + { + if (popup instanceof JPopupMenu) + { + constructor = clazz.getConstructor(new Class[] + { Image.class, String.class }); + } + else + { + constructor = clazz.getConstructor(new Class[] + { Image.class, String.class, PopupMenu.class }); + } + addActionListener = + clazz.getMethod("addActionListener", new Class[] + { ActionListener.class }); + addMouseListener = + clazz.getMethod("addMouseListener", new Class[] + { MouseListener.class }); + messageTypeClass = + Class.forName("java.awt.TrayIcon$MessageType"); + displayMessage = + clazz.getMethod("displayMessage", new Class[] + { String.class, String.class, messageTypeClass }); + setIcon = clazz.getMethod("setImage", new Class[] + { Image.class }); + setIconAutoSize = + clazz.getMethod("setImageAutoSize", new Class[] + { boolean.class }); + } + catch (ClassNotFoundException ex) + { + throw new UnsupportedOperationException(ex); + } + catch (NoSuchMethodException ex) + { + throw new UnsupportedOperationException(ex); + } + + try + { + if (popup instanceof JPopupMenu) + { + impl = constructor.newInstance( + new Object[] { image, tooltip }); + addMouseListener(new AWTMouseAdapter((JPopupMenu) popup)); + } + else + { + impl = constructor.newInstance( + new Object[] { image, tooltip, popup }); + } + } + catch (IllegalAccessException ex) + { + throw new UnsupportedOperationException(ex); + } + catch (InstantiationException ex) + { + throw new UnsupportedOperationException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + if (cause == null) + throw new UnsupportedOperationException(ex); + if (cause instanceof IllegalArgumentException) + throw (IllegalArgumentException) cause; + if (cause instanceof UnsupportedOperationException) + throw (UnsupportedOperationException) cause; + if (cause instanceof HeadlessException) + throw (HeadlessException) cause; + if (cause instanceof SecurityException) + throw (SecurityException) cause; + throw new UnsupportedOperationException(cause); + } + } + + public void addActionListener(ActionListener listener) + { + try + { + addActionListener.invoke(getImpl(), new Object[] + { listener }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + throw new UndeclaredThrowableException((cause == null) ? ex + : cause); + } + } + + public void addMouseListener(MouseListener listener) + { + try + { + addMouseListener.invoke(getImpl(), new Object[] { listener }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + throw new UndeclaredThrowableException((cause == null) ? ex + : cause); + } + } + + public void addBalloonActionListener(ActionListener listener) + { + // java.awt.TrayIcon doesn't support addBalloonActionListener() + } + + public void displayMessage(String caption, String text, + java.awt.TrayIcon.MessageType messageType) + throws NullPointerException + { + try + { + displayMessage.invoke(getImpl(), new Object[] + { caption, text, messageType.name() }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + if (cause instanceof NullPointerException) + throw (NullPointerException) cause; + throw new UndeclaredThrowableException((cause == null) ? ex + : cause); + } + } + + public Object getImpl() + { + return impl; + } + + public void setIcon(ImageIcon icon) throws NullPointerException + { + try + { + setIcon.invoke(getImpl(), new Object[] + { (icon == null) ? null : icon.getImage() }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + if (cause instanceof NullPointerException) + throw (NullPointerException) cause; + throw new UndeclaredThrowableException((cause == null) ? ex + : cause); + } + } + + public void setIconAutoSize(boolean autoSize) + { + try + { + setIconAutoSize.invoke(getImpl(), new Object[] + { autoSize }); + } + catch (IllegalAccessException ex) + { + throw new UndeclaredThrowableException(ex); + } + catch (InvocationTargetException ex) + { + Throwable cause = ex.getCause(); + throw new UndeclaredThrowableException((cause == null) ? ex + : cause); + } + } + } + + /** + * Extended mouse adapter to show the JPopupMenu in Java 6 + * Based on : http://weblogs.java.net/blog/ixmal/archive/2006/05/using_jpopupmen.html + * And : http://weblogs.java.net/blog/alexfromsun/archive/2008/02/jtrayicon_updat.html + * + * Use a hidden JWindow (JDialog for Windows) to manage the JPopupMenu. + * + * @author Damien Roth + */ + private static class AWTMouseAdapter + extends MouseAdapter + { + private JPopupMenu popup = null; + private Window hiddenWindow = null; + + public AWTMouseAdapter(JPopupMenu p) + { + this.popup = p; + this.popup.addPopupMenuListener(new PopupMenuListener() + { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) + {} + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) + { + if (hiddenWindow != null) + { + hiddenWindow.dispose(); + hiddenWindow = null; + } + } + + public void popupMenuCanceled(PopupMenuEvent e) + { + if (hiddenWindow != null) + { + hiddenWindow.dispose(); + hiddenWindow = null; + } + } + }); + } + + @Override + public void mouseReleased(MouseEvent e) + { + showPopupMenu(e); + } + + @Override + public void mousePressed(MouseEvent e) + { + showPopupMenu(e); + } + + private void showPopupMenu(MouseEvent e) + { + if (e.isPopupTrigger() && popup != null) + { + if (hiddenWindow == null) + { + if (OSUtils.IS_WINDOWS) + { + hiddenWindow = new JDialog((Frame) null); + ((JDialog) hiddenWindow).setUndecorated(true); + } + else + hiddenWindow = new JWindow((Frame) null); + + hiddenWindow.setAlwaysOnTop(true); + Dimension size = popup.getPreferredSize(); + + Point centerPoint = GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getCenterPoint(); + + if(e.getY() > centerPoint.getY()) + hiddenWindow + .setLocation(e.getX(), e.getY() - size.height); + else + hiddenWindow + .setLocation(e.getX(), e.getY()); + + hiddenWindow.setVisible(true); + + popup.show( + ((RootPaneContainer)hiddenWindow).getContentPane(), + 0, 0); + + // popup works only for focused windows + hiddenWindow.toFront(); + } + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java index 64eb5fa..ef78202 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1647 +15,1647 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber; - -import java.lang.reflect.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; -import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; -import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.ContentPacketExtension.SendersEnum; -import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.neomedia.*; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.*; -import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.util.*; -import org.jivesoftware.smackx.packet.*; - -/** - * Implements a Jabber CallPeer. - * - * @author Emil Ivov - * @author Lyubomir Marinov - * @author Boris Grozev - */ -public class CallPeerJabberImpl - extends AbstractCallPeerJabberGTalkImpl - -{ - /** - * The Logger used by the CallPeerJabberImpl class and its - * instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(CallPeerJabberImpl.class); - - /** - * If the call is cancelled before session-initiate is sent. - */ - private boolean cancelled = false; - - /** - * Synchronization object for candidates available. - */ - private final Object candSyncRoot = new Object(); - - /** - * If the content-add does not contains candidates. - */ - private boolean contentAddWithNoCands = false; - - /** - * If we have processed the session initiate. - */ - private boolean sessionInitiateProcessed = false; - - /** - * Synchronization object. Synchronization object? Wow, who would have - * thought! ;) Would be great to have a word on what we are syncing with it - */ - private final Object sessionInitiateSyncRoot = new Object(); - - /** - * Synchronization object for SID. - */ - private final Object sidSyncRoot = new Object(); - - /** - * The current value of the 'senders' field of the audio content in the - * Jingle session with this CallPeer. - * null should be interpreted as 'both', which is the default in - * Jingle if the XML attribute is missing. - */ - private SendersEnum audioSenders = SendersEnum.none; - - /** - * The current value of the 'senders' field of the video content in the - * Jingle session with this CallPeer. - * null should be interpreted as 'both', which is the default in - * Jingle if the XML attribute is missing. - */ - private SendersEnum videoSenders = SendersEnum.none; - - /** - * Creates a new call peer with address peerAddress. - * - * @param peerAddress the Jabber address of the new call peer. - * @param owningCall the call that contains this call peer. - */ - public CallPeerJabberImpl(String peerAddress, - CallJabberImpl owningCall) - { - super(peerAddress, owningCall); - - setMediaHandler(new CallPeerMediaHandlerJabberImpl(this)); - } - - /** - * Creates a new call peer with address peerAddress. - * - * @param peerAddress the Jabber address of the new call peer. - * @param owningCall the call that contains this call peer. - * @param sessionIQ The session-initiate JingleIQ which was - * received from peerAddress and caused the creation of this - * CallPeerJabberImpl - */ - public CallPeerJabberImpl(String peerAddress, - CallJabberImpl owningCall, - JingleIQ sessionIQ) - { - this(peerAddress, owningCall); - this.sessionInitIQ = sessionIQ; - } - - /** - * Send a session-accept JingleIQ to this CallPeer - * @throws OperationFailedException if we fail to create or send the - * response. - */ - public synchronized void answer() - throws OperationFailedException - { - Iterable answer; - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - try - { - mediaHandler - .getTransportManager() - .wrapupConnectivityEstablishment(); - answer = mediaHandler.generateSessionAccept(); - for (ContentPacketExtension c : answer) - setSenders(getMediaType(c), c.getSenders()); - } - catch(Exception exc) - { - logger.info("Failed to answer an incoming call", exc); - - //send an error response - String reasonText = "Error: " + exc.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - sessionInitIQ.getTo(), - sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), - Reason.FAILED_APPLICATION, - reasonText); - - setState(CallPeerState.FAILED, reasonText); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - - JingleIQ response - = JinglePacketFactory.createSessionAccept( - sessionInitIQ.getTo(), - sessionInitIQ.getFrom(), - getSID(), - answer); - - //send the packet first and start the stream later in case the media - //relay needs to see it before letting hole punching techniques through. - getProtocolProvider().getConnection().sendPacket(response); - - try - { - mediaHandler.start(); - } - catch(UndeclaredThrowableException e) - { - Throwable exc = e.getUndeclaredThrowable(); - - logger.info("Failed to establish a connection", exc); - - //send an error response - String reasonText = "Error: " + exc.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - sessionInitIQ.getTo(), - sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), - Reason.GENERAL_ERROR, - reasonText); - - setState(CallPeerState.FAILED, reasonText); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - - //tell everyone we are connected so that the audio notifications would - //stop - setState(CallPeerState.CONNECTED); - } - - /** - * Returns the session ID of the Jingle session associated with this call. - * - * @return the session ID of the Jingle session associated with this call. - */ - @Override - public String getSID() - { - return sessionInitIQ != null ? sessionInitIQ.getSID() : null; - } - - /** - * Returns the IQ ID of the Jingle session-initiate packet associated with - * this call. - * - * @return the IQ ID of the Jingle session-initiate packet associated with - * this call. - */ - public JingleIQ getSessionIQ() - { - return sessionInitIQ; - } - - /** - * Ends the call with this CallPeer. Depending on the state - * of the peer the method would send a CANCEL, BYE, or BUSY_HERE message - * and set the new state to DISCONNECTED. - * - * @param failed indicates if the hangup is following to a call failure or - * simply a disconnect - * @param reasonText the text, if any, to be set on the - * ReasonPacketExtension as the value of its - * @param reasonOtherExtension the PacketExtension, if any, to be - * set on the ReasonPacketExtension as the value of its - * otherExtension property - */ - public void hangup(boolean failed, - String reasonText, - PacketExtension reasonOtherExtension) - { - CallPeerState prevPeerState = getState(); - - // do nothing if the call is already ended - if (CallPeerState.DISCONNECTED.equals(prevPeerState) - || CallPeerState.FAILED.equals(prevPeerState)) - { - if (logger.isDebugEnabled()) - logger.debug("Ignoring a request to hangup a call peer " - + "that is already DISCONNECTED"); - return; - } - - setState( - failed ? CallPeerState.FAILED : CallPeerState.DISCONNECTED, - reasonText); - - JingleIQ responseIQ = null; - - if (prevPeerState.equals(CallPeerState.CONNECTED) - || CallPeerState.isOnHold(prevPeerState)) - { - responseIQ = JinglePacketFactory.createBye( - getProtocolProvider().getOurJID(), peerJID, getSID()); - } - else if (CallPeerState.CONNECTING.equals(prevPeerState) - || CallPeerState.CONNECTING_WITH_EARLY_MEDIA.equals(prevPeerState) - || CallPeerState.ALERTING_REMOTE_SIDE.equals(prevPeerState)) - { - String jingleSID = getSID(); - - if(jingleSID == null) - { - synchronized(sidSyncRoot) - { - // we cancelled the call too early because the jingleSID - // is null (i.e. the session-initiate has not been created) - // and no need to send the session-terminate - cancelled = true; - return; - } - } - - responseIQ = JinglePacketFactory.createCancel( - getProtocolProvider().getOurJID(), peerJID, getSID()); - } - else if (prevPeerState.equals(CallPeerState.INCOMING_CALL)) - { - responseIQ = JinglePacketFactory.createBusy( - getProtocolProvider().getOurJID(), peerJID, getSID()); - } - else if (prevPeerState.equals(CallPeerState.BUSY) - || prevPeerState.equals(CallPeerState.FAILED)) - { - // For FAILED and BUSY we only need to update CALL_STATUS - // as everything else has been done already. - } - else - { - logger.info("Could not determine call peer state!"); - } - - if (responseIQ != null) - { - if (reasonOtherExtension != null) - { - ReasonPacketExtension reason - = (ReasonPacketExtension) - responseIQ.getExtension( - ReasonPacketExtension.ELEMENT_NAME, - ReasonPacketExtension.NAMESPACE); - - if (reason != null) - { - reason.setOtherExtension(reasonOtherExtension); - } - else if(reasonOtherExtension instanceof ReasonPacketExtension) - { - responseIQ.setReason( - (ReasonPacketExtension)reasonOtherExtension); - } - } - - getProtocolProvider().getConnection().sendPacket(responseIQ); - } - } - - /** - * Creates and sends a session-initiate {@link JingleIQ}. - * - * @param sessionInitiateExtensions a collection of additional and optional - * PacketExtensions to be added to the session-initiate - * {@link JingleIQ} which is to initiate the session with this - * CallPeerJabberImpl - * @throws OperationFailedException exception - */ - protected synchronized void initiateSession( - Iterable sessionInitiateExtensions) - throws OperationFailedException - { - initiator = false; - - //Create the media description that we'd like to send to the other side. - List offer - = getMediaHandler().createContentList(); - - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - - synchronized(sidSyncRoot) - { - sessionInitIQ - = JinglePacketFactory.createSessionInitiate( - protocolProvider.getOurJID(), - this.peerJID, - JingleIQ.generateSID(), - offer); - - if(cancelled) - { - // we cancelled the call too early so no need to send the - // session-initiate to peer - getMediaHandler().getTransportManager().close(); - return; - } - } - - if (sessionInitiateExtensions != null) - { - for (PacketExtension sessionInitiateExtension - : sessionInitiateExtensions) - { - sessionInitIQ.addExtension(sessionInitiateExtension); - } - } - - protocolProvider.getConnection().sendPacket(sessionInitIQ); - } - - /** - * Notifies this instance that a specific ColibriConferenceIQ has - * been received. This CallPeerJabberImpl uses the part of the - * information provided in the specified conferenceIQ which - * concerns it only. - * - * @param conferenceIQ the ColibriConferenceIQ which has been - * received - */ - void processColibriConferenceIQ(ColibriConferenceIQ conferenceIQ) - { - /* - * CallPeerJabberImpl does not itself/directly know the specifics - * related to the channels allocated on the Jitsi Videobridge server. - * The channels contain transport and media-related information so - * forward the notification to CallPeerMediaHandlerJabberImpl. - */ - getMediaHandler().processColibriConferenceIQ(conferenceIQ); - } - - /** - * Processes the content-accept {@link JingleIQ}. - * - * @param content The {@link JingleIQ} that contains content that remote - * peer has accepted - */ - public void processContentAccept(JingleIQ content) - { - List contents = content.getContentList(); - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - try - { - mediaHandler - .getTransportManager() - .wrapupConnectivityEstablishment(); - mediaHandler.processAnswer(contents); - for (ContentPacketExtension c : contents) - setSenders(getMediaType(c), c.getSenders()); - } - catch (Exception e) - { - logger.warn("Failed to process a content-accept", e); - - // Send an error response. - String reason = "Error: " + e.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - getProtocolProvider().getOurJID(), - peerJID, - sessionInitIQ.getSID(), - Reason.INCOMPATIBLE_PARAMETERS, - reason); - - setState(CallPeerState.FAILED, reason); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - - mediaHandler.start(); - } - - /** - * Processes the content-add {@link JingleIQ}. - * - * @param content The {@link JingleIQ} that contains content that remote - * peer wants to be added - */ - public void processContentAdd(final JingleIQ content) - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - List contents = content.getContentList(); - Iterable answerContents; - JingleIQ contentIQ; - boolean noCands = false; - MediaStream oldVideoStream = mediaHandler.getStream(MediaType.VIDEO); - - if(logger.isInfoEnabled()) - logger.info("Looking for candidates in content-add."); - try - { - if(!contentAddWithNoCands) - { - mediaHandler.processOffer(contents); - - /* - * Gingle transport will not put candidate in session-initiate - * and content-add. - */ - for(ContentPacketExtension c : contents) - { - if(JingleUtils.getFirstCandidate(c, 1) == null) - { - contentAddWithNoCands = true; - noCands = true; - } - } - } - - // if no candidates are present, launch a new Thread which will - // process and wait for the connectivity establishment (otherwise - // the existing thread will be blocked and thus cannot receive - // transport-info with candidates - if(noCands) - { - new Thread() - { - @Override - public void run() - { - try - { - synchronized(candSyncRoot) - { - candSyncRoot.wait(); - } - } - catch(InterruptedException e) - { - } - - processContentAdd(content); - contentAddWithNoCands = false; - } - }.start(); - if(logger.isInfoEnabled()) - logger.info("No candidates found in content-add, started " - + "new thread."); - return; - } - - mediaHandler - .getTransportManager() - .wrapupConnectivityEstablishment(); - if(logger.isInfoEnabled()) - logger.info("Wrapping up connectivity establishment"); - answerContents = mediaHandler.generateSessionAccept(); - contentIQ = null; - } - catch(Exception e) - { - logger.warn("Exception occurred", e); - - answerContents = null; - contentIQ - = JinglePacketFactory.createContentReject( - getProtocolProvider().getOurJID(), - this.peerJID, - getSID(), - answerContents); - } - - if(contentIQ == null) - { - /* send content-accept */ - contentIQ - = JinglePacketFactory.createContentAccept( - getProtocolProvider().getOurJID(), - this.peerJID, - getSID(), - answerContents); - for (ContentPacketExtension c : answerContents) - setSenders(getMediaType(c), c.getSenders()); - } - - getProtocolProvider().getConnection().sendPacket(contentIQ); - mediaHandler.start(); - - /* - * If a remote peer turns her video on in a conference which is hosted - * by the local peer and the local peer is not streaming her local - * video, reinvite the other remote peers to enable RTP translation. - */ - if (oldVideoStream == null) - { - MediaStream newVideoStream - = mediaHandler.getStream(MediaType.VIDEO); - - if ((newVideoStream != null) - && mediaHandler.isRTPTranslationEnabled(MediaType.VIDEO)) - { - try - { - getCall().modifyVideoContent(); - } - catch (OperationFailedException ofe) - { - logger.error("Failed to enable RTP translation", ofe); - } - } - } - } - - /** - * Processes the content-modify {@link JingleIQ}. - * - * @param content The {@link JingleIQ} that contains content that remote - * peer wants to be modified - */ - public void processContentModify(JingleIQ content) - { - ContentPacketExtension ext = content.getContentList().get(0); - MediaType mediaType = getMediaType(ext); - - try - { - boolean modify - = (ext.getFirstChildOfType(RtpDescriptionPacketExtension.class) - != null); - - getMediaHandler().reinitContent(ext.getName(), ext, modify); - - setSenders(mediaType, ext.getSenders()); - - if (MediaType.VIDEO.equals(mediaType)) - getCall().modifyVideoContent(); - } - catch(Exception e) - { - logger.info("Failed to process an incoming content-modify", e); - - // Send an error response. - String reason = "Error: " + e.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - getProtocolProvider().getOurJID(), - peerJID, - sessionInitIQ.getSID(), - Reason.INCOMPATIBLE_PARAMETERS, - reason); - - setState(CallPeerState.FAILED, reason); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - } - - /** - * Processes the content-reject {@link JingleIQ}. - * - * @param content The {@link JingleIQ} - */ - public void processContentReject(JingleIQ content) - { - if(content.getContentList().isEmpty()) - { - //send an error response; - JingleIQ errResp = JinglePacketFactory.createSessionTerminate( - sessionInitIQ.getTo(), sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS, - "Error: content rejected"); - - setState(CallPeerState.FAILED, "Error: content rejected"); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - } - - /** - * Processes the content-remove {@link JingleIQ}. - * - * @param content The {@link JingleIQ} that contains content that remote - * peer wants to be removed - */ - public void processContentRemove(JingleIQ content) - { - List contents = content.getContentList(); - boolean videoContentRemoved = false; - - if (!contents.isEmpty()) - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - for(ContentPacketExtension c : contents) - { - mediaHandler.removeContent(c.getName()); - - MediaType mediaType = getMediaType(c); - setSenders(mediaType, SendersEnum.none); - - if (MediaType.VIDEO.equals(mediaType)) - videoContentRemoved = true; - } - - /* - * TODO XEP-0166: Jingle says: If the content-remove results in zero - * content definitions for the session, the entity that receives the - * content-remove SHOULD send a session-terminate action to the - * other party (since a session with no content definitions is - * void). - */ - } - - if (videoContentRemoved) - { - // removing of the video content might affect the other sessions - // in the call - try - { - getCall().modifyVideoContent(); - } - catch (Exception e) - { - logger.warn("Failed to update Jingle sessions"); - } - } - } - - /** - * Processes a session-accept {@link JingleIQ}. - * - * @param sessionInitIQ The session-accept {@link JingleIQ} to process. - */ - public void processSessionAccept(JingleIQ sessionInitIQ) - { - this.sessionInitIQ = sessionInitIQ; - - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - List answer = sessionInitIQ.getContentList(); - - try - { - mediaHandler - .getTransportManager() - .wrapupConnectivityEstablishment(); - mediaHandler.processAnswer(answer); - for (ContentPacketExtension c : answer) - setSenders(getMediaType(c), c.getSenders()); - } - catch(Exception exc) - { - if (logger.isInfoEnabled()) - logger.info("Failed to process a session-accept", exc); - - //send an error response; - JingleIQ errResp = JinglePacketFactory.createSessionTerminate( - sessionInitIQ.getTo(), sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS, - exc.getClass().getName() + ": " + exc.getMessage()); - - setState(CallPeerState.FAILED, "Error: " + exc.getMessage()); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - - //tell everyone we are connected so that the audio notifications would - //stop - setState(CallPeerState.CONNECTED); - - mediaHandler.start(); - - /* - * If video was added to the call after we sent the session-initiate - * to this peer, it needs to be added to this peer's session with a - * content-add. - */ - sendModifyVideoContent(); - } - - /** - * Handles the specified session info packet according to its - * content. - * - * @param info the {@link SessionInfoPacketExtension} that we just received. - */ - public void processSessionInfo(SessionInfoPacketExtension info) - { - switch (info.getType()) - { - case ringing: - setState(CallPeerState.ALERTING_REMOTE_SIDE); - break; - case hold: - getMediaHandler().setRemotelyOnHold(true); - reevalRemoteHoldStatus(); - break; - case unhold: - case active: - getMediaHandler().setRemotelyOnHold(false); - reevalRemoteHoldStatus(); - break; - default: - logger.warn("Received SessionInfoPacketExtension of unknown type"); - } - } - - /** - * Processes the session initiation {@link JingleIQ} that we were created - * with, passing its content to the media handler and then sends either a - * "session-info/ringing" or a "session-terminate" response. - * - * @param sessionInitIQ The {@link JingleIQ} that created the session that - * we are handling here. - */ - protected synchronized void processSessionInitiate(JingleIQ sessionInitIQ) - { - // Do initiate the session. - this.sessionInitIQ = sessionInitIQ; - this.initiator = true; - - // This is the SDP offer that came from the initial session-initiate. - // Contrary to SIP, we are guaranteed to have content because XEP-0166 - // says: "A session consists of at least one content type at a time." - List offer = sessionInitIQ.getContentList(); - - try - { - getMediaHandler().processOffer(offer); - - CoinPacketExtension coin = null; - - for(PacketExtension ext : sessionInitIQ.getExtensions()) - { - if(ext.getElementName().equals( - CoinPacketExtension.ELEMENT_NAME)) - { - coin = (CoinPacketExtension)ext; - break; - } - } - - /* does the call peer acts as a conference focus ? */ - if(coin != null) - { - setConferenceFocus(Boolean.parseBoolean( - (String)coin.getAttribute("isfocus"))); - } - } - catch(Exception ex) - { - logger.info("Failed to process an incoming session initiate", ex); - - //send an error response; - String reasonText = "Error: " + ex.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - sessionInitIQ.getTo(), - sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), - Reason.INCOMPATIBLE_PARAMETERS, - reasonText); - - setState(CallPeerState.FAILED, reasonText); - getProtocolProvider().getConnection().sendPacket(errResp); - return; - } - - // If we do not get the info about the remote peer yet. Get it right - // now. - if(this.getDiscoveryInfo() == null) - { - String calleeURI = sessionInitIQ.getFrom(); - retrieveDiscoveryInfo(calleeURI); - } - - //send a ringing response - if (logger.isTraceEnabled()) - logger.trace("will send ringing response: "); - - getProtocolProvider().getConnection().sendPacket( - JinglePacketFactory.createRinging(sessionInitIQ)); - - synchronized(sessionInitiateSyncRoot) - { - sessionInitiateProcessed = true; - sessionInitiateSyncRoot.notify(); - } - - //if this is a 3264 initiator, let's give them an early peek at our - //answer so that they could start ICE (SIP-2-Jingle gateways won't - //be able to send their candidates unless they have this) - DiscoverInfo discoverInfo = getDiscoveryInfo(); - if ((discoverInfo != null) - && discoverInfo.containsFeature( - ProtocolProviderServiceJabberImpl.URN_IETF_RFC_3264)) - { - getProtocolProvider().getConnection().sendPacket( - JinglePacketFactory.createDescriptionInfo( - sessionInitIQ.getTo(), - sessionInitIQ.getFrom(), - sessionInitIQ.getSID(), - getMediaHandler().getLocalContentList())); - } - } - - /** - * Puts this peer into a {@link CallPeerState#DISCONNECTED}, indicating a - * reason to the user, if there is one. - * - * @param jingleIQ the {@link JingleIQ} that's terminating our session. - */ - public void processSessionTerminate(JingleIQ jingleIQ) - { - String reasonStr = "Call ended by remote side."; - ReasonPacketExtension reasonExt = jingleIQ.getReason(); - - if(reasonExt != null) - { - Reason reason = reasonExt.getReason(); - - if(reason != null) - reasonStr += " Reason: " + reason.toString() + "."; - - String text = reasonExt.getText(); - - if(text != null) - reasonStr += " " + text; - } - - setState(CallPeerState.DISCONNECTED, reasonStr); - } - - /** - * Processes a specific "XEP-0251: Jingle Session Transfer" - * transfer packet (extension). - * - * @param transfer the "XEP-0251: Jingle Session Transfer" transfer packet - * (extension) to process - * @throws OperationFailedException if anything goes wrong while processing - * the specified transfer packet (extension) - */ - public void processTransfer(TransferPacketExtension transfer) - throws OperationFailedException - { - String attendantAddress = transfer.getFrom(); - - if (attendantAddress == null) - { - throw new OperationFailedException( - "Session transfer must contain a \'from\' attribute value.", - OperationFailedException.ILLEGAL_ARGUMENT); - } - - String calleeAddress = transfer.getTo(); - - if (calleeAddress == null) - { - throw new OperationFailedException( - "Session transfer must contain a \'to\' attribute value.", - OperationFailedException.ILLEGAL_ARGUMENT); - } - - // Checks if the transfer remote peer is contained by the roster of this - // account. - Roster roster = getProtocolProvider().getConnection().getRoster(); - if(!roster.contains(StringUtils.parseBareAddress(calleeAddress))) - { - String failedMessage = - "Transfer impossible:\n" - + "Account roster does not contain transfer peer: " - + StringUtils.parseBareAddress(calleeAddress); - setState(CallPeerState.FAILED, failedMessage); - logger.info(failedMessage); - } - - OperationSetBasicTelephonyJabberImpl basicTelephony - = (OperationSetBasicTelephonyJabberImpl) - getProtocolProvider() - .getOperationSet(OperationSetBasicTelephony.class); - CallJabberImpl calleeCall = new CallJabberImpl(basicTelephony); - TransferPacketExtension calleeTransfer = new TransferPacketExtension(); - String sid = transfer.getSID(); - - calleeTransfer.setFrom(attendantAddress); - if (sid != null) - { - calleeTransfer.setSID(sid); - calleeTransfer.setTo(calleeAddress); - } - basicTelephony.createOutgoingCall( - calleeCall, - calleeAddress, - Arrays.asList(new PacketExtension[] { calleeTransfer })); - } - - /** - * Processes the transport-info {@link JingleIQ}. - * - * @param jingleIQ the transport-info {@link JingleIQ} to process - */ - public void processTransportInfo(JingleIQ jingleIQ) - { - /* - * The transport-info action is used to exchange transport candidates so - * it only concerns the mediaHandler. - */ - try - { - if(isInitiator()) - { - synchronized(sessionInitiateSyncRoot) - { - if(!sessionInitiateProcessed) - { - try - { - sessionInitiateSyncRoot.wait(); - } - catch(InterruptedException e) - { - } - } - } - } - - getMediaHandler().processTransportInfo( - jingleIQ.getContentList()); - } - catch (OperationFailedException ofe) - { - logger.warn("Failed to process an incoming transport-info", ofe); - - //send an error response - String reasonText = "Error: " + ofe.getMessage(); - JingleIQ errResp - = JinglePacketFactory.createSessionTerminate( - getProtocolProvider().getOurJID(), - peerJID, - sessionInitIQ.getSID(), - Reason.GENERAL_ERROR, - reasonText); - - setState(CallPeerState.FAILED, reasonText); - getProtocolProvider().getConnection().sendPacket(errResp); - - return; - } - - synchronized(candSyncRoot) - { - candSyncRoot.notify(); - } - } - - /** - * Puts the CallPeer represented by this instance on or off hold. - * - * @param onHold true to have the CallPeer put on hold; - * false, otherwise - * - * @throws OperationFailedException if we fail to construct or send the - * INVITE request putting the remote side on/off hold. - */ - public void putOnHold(boolean onHold) - throws OperationFailedException - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - mediaHandler.setLocallyOnHold(onHold); - - SessionInfoType type; - - if(onHold) - type = SessionInfoType.hold; - else - { - type = SessionInfoType.unhold; - getMediaHandler().reinitAllContents(); - } - - //we are now on hold and need to realize this before potentially - //spoiling it all with an exception while sending the packet :). - reevalLocalHoldStatus(); - - JingleIQ onHoldIQ = JinglePacketFactory.createSessionInfo( - getProtocolProvider().getOurJID(), - peerJID, - getSID(), - type); - - getProtocolProvider().getConnection().sendPacket(onHoldIQ); - } - - /** - * Send a content-add to add video setup. - */ - private void sendAddVideoContent() - { - List contents; - - try - { - contents = getMediaHandler().createContentList(MediaType.VIDEO); - } - catch(Exception exc) - { - logger.warn("Failed to gather content for video type", exc); - return; - } - - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - JingleIQ contentIQ - = JinglePacketFactory.createContentAdd( - protocolProvider.getOurJID(), - this.peerJID, - getSID(), - contents); - - protocolProvider.getConnection().sendPacket(contentIQ); - } - - /** - * Sends a content message to reflect changes in the setup such as - * the local peer/user becoming a conference focus. - */ - public void sendCoinSessionInfo() - { - JingleIQ sessionInfoIQ - = JinglePacketFactory.createSessionInfo( - getProtocolProvider().getOurJID(), - this.peerJID, - getSID()); - CoinPacketExtension coinExt - = new CoinPacketExtension(getCall().isConferenceFocus()); - - sessionInfoIQ.addExtension(coinExt); - getProtocolProvider().getConnection().sendPacket(sessionInfoIQ); - } - - /** - * Returns the MediaDirection that should be set for the content - * of type mediaType in the Jingle session for this - * CallPeer. - * If we are the focus of a conference and are doing RTP translation, - * takes into account the other CallPeers in the Call. - * - * @param mediaType the MediaType for which to return the - * MediaDirection - * @return the MediaDirection that should be used for the content - * of type mediaType in the Jingle session for this - * CallPeer. - */ - private MediaDirection getDirectionForJingle(MediaType mediaType) - { - MediaDirection direction = MediaDirection.INACTIVE; - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - // If we are streaming media, the direction should allow sending - if ( (MediaType.AUDIO == mediaType && - mediaHandler.isLocalAudioTransmissionEnabled()) || - (MediaType.VIDEO == mediaType && - isLocalVideoStreaming())) - direction = direction.or(MediaDirection.SENDONLY); - - // If we are receiving media from this CallPeer, the direction should - // allow receiving - SendersEnum senders = getSenders(mediaType); - if (senders == null || senders == SendersEnum.both || - (isInitiator() && senders == SendersEnum.initiator) || - (!isInitiator() && senders == SendersEnum.responder)) - direction = direction.or(MediaDirection.RECVONLY); - - // If we are the focus of a conference and we are receiving media from - // another CallPeer in the same Call, the direction should allow sending - CallJabberImpl call = getCall(); - if (call != null && call.isConferenceFocus()) - { - for (CallPeerJabberImpl peer : call.getCallPeerList()) - { - if (peer != this) - { - senders = peer.getSenders(mediaType); - if (senders == null || senders == SendersEnum.both || - (peer.isInitiator() - && senders == SendersEnum.initiator) || - (!peer.isInitiator() - && senders == SendersEnum.responder)) - { - direction = direction.or(MediaDirection.SENDONLY); - break; - } - } - } - } - - return direction; - } - - /** - * Send, if necessary, a jingle content message to reflect change - * in video setup. Whether the jingle session should have a video content, - * and if so, the value of the senders field is determined - * based on whether we are streaming local video and, if we are the focus - * of a conference, on the other peers in the conference. - * The message can be content-modify if video content exists (and the - * senders field changes), content-add or content-remove. - * - * @return true if a jingle content message was sent. - */ - public boolean sendModifyVideoContent() - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - MediaDirection direction = getDirectionForJingle(MediaType.VIDEO); - - ContentPacketExtension remoteContent - = mediaHandler.getLocalContent(MediaType.VIDEO.toString()); - - if (remoteContent == null) - { - if (direction == MediaDirection.INACTIVE) - { - // no video content, none needed - return false; - } - else - { - if (getState() == CallPeerState.CONNECTED) - { - if (logger.isInfoEnabled()) - logger.info("Adding video content for " + this); - sendAddVideoContent(); - return true; - } - return false; - } - } - else - { - if (direction == MediaDirection.INACTIVE) - { - sendRemoveVideoContent(); - return true; - } - } - - SendersEnum senders = getSenders(MediaType.VIDEO); - if (senders == null) - senders = SendersEnum.both; - - SendersEnum newSenders = SendersEnum.none; - if (MediaDirection.SENDRECV == direction) - newSenders = SendersEnum.both; - else if (MediaDirection.RECVONLY == direction) - newSenders = isInitiator() - ? SendersEnum.initiator : SendersEnum.responder; - else if (MediaDirection.SENDONLY == direction) - newSenders = isInitiator() - ? SendersEnum.responder : SendersEnum.initiator; - - /* - * Send Content-Modify - */ - ContentPacketExtension ext = new ContentPacketExtension(); - String remoteContentName = remoteContent.getName(); - - ext.setSenders(newSenders); - ext.setCreator(remoteContent.getCreator()); - ext.setName(remoteContentName); - - if (newSenders != senders) - { - if (logger.isInfoEnabled()) - logger.info("Sending content modify, senders: " - + senders + "->" + newSenders); - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - JingleIQ contentIQ - = JinglePacketFactory.createContentModify( - protocolProvider.getOurJID(), - this.peerJID, - getSID(), - ext); - - protocolProvider.getConnection().sendPacket(contentIQ); - } - - try - { - mediaHandler.reinitContent(remoteContentName, ext, false); - mediaHandler.start(); - } - catch(Exception e) - { - logger.warn("Exception occurred during media reinitialization", e); - } - - return (newSenders != senders); - } - - /** - * Send a content message to reflect change in video setup (start - * or stop). - */ - public void sendModifyVideoResolutionContent() - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - ContentPacketExtension remoteContent - = mediaHandler.getRemoteContent(MediaType.VIDEO.toString()); - ContentPacketExtension content; - - logger.info("send modify-content to change resolution"); - - // send content-modify with RTP description - - // create content list with resolution - try - { - content = mediaHandler.createContentForMedia(MediaType.VIDEO); - } - catch (Exception e) - { - logger.warn("Failed to gather content for video type", e); - return; - } - - // if we are only receiving video senders is null - SendersEnum senders = remoteContent.getSenders(); - - if (senders != null) - content.setSenders(senders); - - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - JingleIQ contentIQ - = JinglePacketFactory.createContentModify( - protocolProvider.getOurJID(), - this.peerJID, - getSID(), - content); - - protocolProvider.getConnection().sendPacket(contentIQ); - - try - { - mediaHandler.reinitContent(remoteContent.getName(), content, false); - mediaHandler.start(); - } - catch(Exception e) - { - logger.warn("Exception occurred when media reinitialization", e); - } - } - - /** - * Send a content-remove to remove video setup. - */ - private void sendRemoveVideoContent() - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - - ContentPacketExtension content = new ContentPacketExtension(); - ContentPacketExtension remoteContent - = mediaHandler.getRemoteContent(MediaType.VIDEO.toString()); - if (remoteContent == null) - return; - String remoteContentName = remoteContent.getName(); - - content.setName(remoteContentName); - content.setCreator(remoteContent.getCreator()); - content.setSenders(remoteContent.getSenders()); - - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - JingleIQ contentIQ - = JinglePacketFactory.createContentRemove( - protocolProvider.getOurJID(), - this.peerJID, - getSID(), - Arrays.asList(content)); - - protocolProvider.getConnection().sendPacket(contentIQ); - mediaHandler.removeContent(remoteContentName); - setSenders(MediaType.VIDEO, SendersEnum.none); - } - - /** - * Sends local candidate addresses from the local peer to the remote peer - * using the transport-info {@link JingleIQ}. - * - * @param contents the local candidate addresses to be sent from the local - * peer to the remote peer using the transport-info - * {@link JingleIQ} - */ - protected void sendTransportInfo(Iterable contents) - { - // if the call is canceled, do not start sending candidates in - // transport-info - if(cancelled) - return; - - JingleIQ transportInfo = new JingleIQ(); - - for (ContentPacketExtension content : contents) - transportInfo.addContent(content); - - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - - transportInfo.setAction(JingleAction.TRANSPORT_INFO); - transportInfo.setFrom(protocolProvider.getOurJID()); - transportInfo.setSID(getSID()); - transportInfo.setTo(getAddress()); - transportInfo.setType(IQ.Type.SET); - - PacketCollector collector - = protocolProvider.getConnection().createPacketCollector( - new PacketIDFilter(transportInfo.getPacketID())); - - protocolProvider.getConnection().sendPacket(transportInfo); - collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); - collector.cancel(); - } - - @Override - public void setState(CallPeerState newState, String reason, int reasonCode) - { - CallPeerState oldState = getState(); - try - { - /* - * We need to dispose of the transport manager before the - * 'call' field is set to null, because if Jitsi Videobridge is in - * use, it (the call) is needed in order to expire the - * Videobridge channels. - */ - if (CallPeerState.DISCONNECTED.equals(newState) - || CallPeerState.FAILED.equals(newState)) - getMediaHandler().getTransportManager().close(); - } - finally - { - super.setState(newState, reason, reasonCode); - } - - if (CallPeerState.isOnHold(oldState) - && CallPeerState.CONNECTED.equals(newState)) - { - try - { - getCall().modifyVideoContent(); - } - catch (OperationFailedException ofe) - { - logger.error("Failed to update call video state after " + - "'hold' status removed for "+this); - } - } - } - - /** - * Transfer (in the sense of call transfer) this CallPeer to a - * specific callee address which may optionally be participating in an - * active Call. - * - * @param to the address of the callee to transfer this CallPeer to - * @param sid the Jingle session ID of the active Call between the - * local peer and the callee in the case of attended transfer; null - * in the case of unattended transfer - * @throws OperationFailedException if something goes wrong - */ - protected void transfer(String to, String sid) - throws OperationFailedException - { - JingleIQ transferSessionInfo = new JingleIQ(); - ProtocolProviderServiceJabberImpl protocolProvider - = getProtocolProvider(); - - transferSessionInfo.setAction(JingleAction.SESSION_INFO); - transferSessionInfo.setFrom(protocolProvider.getOurJID()); - transferSessionInfo.setSID(getSID()); - transferSessionInfo.setTo(getAddress()); - transferSessionInfo.setType(IQ.Type.SET); - - TransferPacketExtension transfer = new TransferPacketExtension(); - - // Attended transfer. - if (sid != null) - { - /* - * Not really sure what the value of the "from" attribute of the - * "transfer" element should be but the examples in "XEP-0251: - * Jingle Session Transfer" has it in the case of attended transfer. - */ - transfer.setFrom(protocolProvider.getOurJID()); - transfer.setSID(sid); - - // Puts on hold the 2 calls before making the attended transfer. - OperationSetBasicTelephonyJabberImpl basicTelephony - = (OperationSetBasicTelephonyJabberImpl) - protocolProvider.getOperationSet( - OperationSetBasicTelephony.class); - CallPeerJabberImpl callPeer = basicTelephony.getActiveCallPeer(sid); - if(callPeer != null) - { - if(!CallPeerState.isOnHold(callPeer.getState())) - { - callPeer.putOnHold(true); - } - } - - if(!CallPeerState.isOnHold(this.getState())) - { - this.putOnHold(true); - } - } - transfer.setTo(to); - - transferSessionInfo.addExtension(transfer); - - Connection connection = protocolProvider.getConnection(); - PacketCollector collector = connection.createPacketCollector( - new PacketIDFilter(transferSessionInfo.getPacketID())); - protocolProvider.getConnection().sendPacket(transferSessionInfo); - - Packet result - = collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); - - if(result == null) - { - // Log the failed transfer call and notify the user. - throw new OperationFailedException( - "No response to the \"transfer\" request.", - OperationFailedException.ILLEGAL_ARGUMENT); - } - else if (((IQ) result).getType() != IQ.Type.RESULT) - { - // Log the failed transfer call and notify the user. - throw new OperationFailedException( - "Remote peer does not manage call \"transfer\"." - + "Response to the \"transfer\" request is: " - + ((IQ) result).getType(), - OperationFailedException.ILLEGAL_ARGUMENT); - } - else - { - String message = ((sid == null) ? "Unattended" : "Attended") - + " transfer to: " - + to; - // Implements the SIP behavior: once the transfer is accepted, the - // current call is closed. - hangup( - false, - message, - new ReasonPacketExtension(Reason.SUCCESS, - message, - new TransferredPacketExtension())); - } - } - - /** - * {@inheritDoc} - */ - public String getEntity() - { - return getAddress(); - } - - /** - * {@inheritDoc} - * - * In Jingle there isn't an actual "direction" parameter. We use the - * senders field to calculate the direction. - */ - @Override - public MediaDirection getDirection(MediaType mediaType) - { - SendersEnum senders = getSenders(mediaType); - - if (senders == SendersEnum.none) - { - return MediaDirection.INACTIVE; - } - else if (senders == null || senders == SendersEnum.both) - { - return MediaDirection.SENDRECV; - } - else if (senders == SendersEnum.initiator) - { - return - isInitiator() - ? MediaDirection.RECVONLY - : MediaDirection.SENDONLY; - } - else //senders == SendersEnum.responder - { - return - isInitiator() - ? MediaDirection.SENDONLY - : MediaDirection.RECVONLY; - } - } - - /** - * Gets the current value of the senders field of the content with - * name mediaType in the Jingle session with this - * CallPeer. - * - * @param mediaType the MediaType for which to get the current - * value of the senders field. - * @return the current value of the senders field of the content - * with name mediaType in the Jingle session with this - * CallPeer. - */ - public SendersEnum getSenders(MediaType mediaType) - { - switch (mediaType) - { - case AUDIO: - return audioSenders; - case DATA: - /* - * FIXME DATA has been introduced as a MediaType but explicit - * support for DATA content has not been added yet. - */ - return SendersEnum.none; - case VIDEO: - return videoSenders; - default: - throw new IllegalArgumentException("mediaType"); - } - } - - /** - * Set the current value of the senders field of the content with - * name mediaType in the Jingle session with this CallPeer - * @param mediaType the MediaType for which to get the current - * value of the senders field. - * @param senders the value to set - */ - public void setSenders(MediaType mediaType, SendersEnum senders) - { - if (mediaType == null) - return; - else if (MediaType.AUDIO.equals(mediaType)) - this.audioSenders = senders; - else if (MediaType.VIDEO.equals(mediaType)) - this.videoSenders = senders; - else - throw new IllegalArgumentException("mediaType"); - } - - /** - * Gets the MediaType of content. If content - * does not have a description child and therefore not - * MediaType can be associated with it, tries to take the - * MediaType from the session's already established contents with - * the same name as content - * @param content the ContentPacketExtention for which to get the - * MediaType - * @return the MediaType of content. - */ - public MediaType getMediaType(ContentPacketExtension content) - { - String contentName = content.getName(); - if (contentName == null) - return null; - - MediaType mediaType = JingleUtils.getMediaType(content); - if (mediaType == null) - { - CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); - for (MediaType m : MediaType.values()) - { - ContentPacketExtension sessionContent - = mediaHandler.getRemoteContent(m.toString()); - if (sessionContent == null) - sessionContent = mediaHandler.getLocalContent(m.toString()); - - if (sessionContent != null - && contentName.equals(sessionContent.getName())) - { - mediaType = m; - break; - } - } - } - - return mediaType; - } -} +package net.java.sip.communicator.impl.protocol.jabber; + +import java.lang.reflect.*; +import java.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.ContentPacketExtension.SendersEnum; +import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.neomedia.*; +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.util.*; +import org.jivesoftware.smackx.packet.*; + +/** + * Implements a Jabber CallPeer. + * + * @author Emil Ivov + * @author Lyubomir Marinov + * @author Boris Grozev + */ +public class CallPeerJabberImpl + extends AbstractCallPeerJabberGTalkImpl + +{ + /** + * The Logger used by the CallPeerJabberImpl class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(CallPeerJabberImpl.class); + + /** + * If the call is cancelled before session-initiate is sent. + */ + private boolean cancelled = false; + + /** + * Synchronization object for candidates available. + */ + private final Object candSyncRoot = new Object(); + + /** + * If the content-add does not contains candidates. + */ + private boolean contentAddWithNoCands = false; + + /** + * If we have processed the session initiate. + */ + private boolean sessionInitiateProcessed = false; + + /** + * Synchronization object. Synchronization object? Wow, who would have + * thought! ;) Would be great to have a word on what we are syncing with it + */ + private final Object sessionInitiateSyncRoot = new Object(); + + /** + * Synchronization object for SID. + */ + private final Object sidSyncRoot = new Object(); + + /** + * The current value of the 'senders' field of the audio content in the + * Jingle session with this CallPeer. + * null should be interpreted as 'both', which is the default in + * Jingle if the XML attribute is missing. + */ + private SendersEnum audioSenders = SendersEnum.none; + + /** + * The current value of the 'senders' field of the video content in the + * Jingle session with this CallPeer. + * null should be interpreted as 'both', which is the default in + * Jingle if the XML attribute is missing. + */ + private SendersEnum videoSenders = SendersEnum.none; + + /** + * Creates a new call peer with address peerAddress. + * + * @param peerAddress the Jabber address of the new call peer. + * @param owningCall the call that contains this call peer. + */ + public CallPeerJabberImpl(String peerAddress, + CallJabberImpl owningCall) + { + super(peerAddress, owningCall); + + setMediaHandler(new CallPeerMediaHandlerJabberImpl(this)); + } + + /** + * Creates a new call peer with address peerAddress. + * + * @param peerAddress the Jabber address of the new call peer. + * @param owningCall the call that contains this call peer. + * @param sessionIQ The session-initiate JingleIQ which was + * received from peerAddress and caused the creation of this + * CallPeerJabberImpl + */ + public CallPeerJabberImpl(String peerAddress, + CallJabberImpl owningCall, + JingleIQ sessionIQ) + { + this(peerAddress, owningCall); + this.sessionInitIQ = sessionIQ; + } + + /** + * Send a session-accept JingleIQ to this CallPeer + * @throws OperationFailedException if we fail to create or send the + * response. + */ + public synchronized void answer() + throws OperationFailedException + { + Iterable answer; + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + try + { + mediaHandler + .getTransportManager() + .wrapupConnectivityEstablishment(); + answer = mediaHandler.generateSessionAccept(); + for (ContentPacketExtension c : answer) + setSenders(getMediaType(c), c.getSenders()); + } + catch(Exception exc) + { + logger.info("Failed to answer an incoming call", exc); + + //send an error response + String reasonText = "Error: " + exc.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + sessionInitIQ.getTo(), + sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), + Reason.FAILED_APPLICATION, + reasonText); + + setState(CallPeerState.FAILED, reasonText); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + + JingleIQ response + = JinglePacketFactory.createSessionAccept( + sessionInitIQ.getTo(), + sessionInitIQ.getFrom(), + getSID(), + answer); + + //send the packet first and start the stream later in case the media + //relay needs to see it before letting hole punching techniques through. + getProtocolProvider().getConnection().sendPacket(response); + + try + { + mediaHandler.start(); + } + catch(UndeclaredThrowableException e) + { + Throwable exc = e.getUndeclaredThrowable(); + + logger.info("Failed to establish a connection", exc); + + //send an error response + String reasonText = "Error: " + exc.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + sessionInitIQ.getTo(), + sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), + Reason.GENERAL_ERROR, + reasonText); + + setState(CallPeerState.FAILED, reasonText); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + + //tell everyone we are connected so that the audio notifications would + //stop + setState(CallPeerState.CONNECTED); + } + + /** + * Returns the session ID of the Jingle session associated with this call. + * + * @return the session ID of the Jingle session associated with this call. + */ + @Override + public String getSID() + { + return sessionInitIQ != null ? sessionInitIQ.getSID() : null; + } + + /** + * Returns the IQ ID of the Jingle session-initiate packet associated with + * this call. + * + * @return the IQ ID of the Jingle session-initiate packet associated with + * this call. + */ + public JingleIQ getSessionIQ() + { + return sessionInitIQ; + } + + /** + * Ends the call with this CallPeer. Depending on the state + * of the peer the method would send a CANCEL, BYE, or BUSY_HERE message + * and set the new state to DISCONNECTED. + * + * @param failed indicates if the hangup is following to a call failure or + * simply a disconnect + * @param reasonText the text, if any, to be set on the + * ReasonPacketExtension as the value of its + * @param reasonOtherExtension the PacketExtension, if any, to be + * set on the ReasonPacketExtension as the value of its + * otherExtension property + */ + public void hangup(boolean failed, + String reasonText, + PacketExtension reasonOtherExtension) + { + CallPeerState prevPeerState = getState(); + + // do nothing if the call is already ended + if (CallPeerState.DISCONNECTED.equals(prevPeerState) + || CallPeerState.FAILED.equals(prevPeerState)) + { + if (logger.isDebugEnabled()) + logger.debug("Ignoring a request to hangup a call peer " + + "that is already DISCONNECTED"); + return; + } + + setState( + failed ? CallPeerState.FAILED : CallPeerState.DISCONNECTED, + reasonText); + + JingleIQ responseIQ = null; + + if (prevPeerState.equals(CallPeerState.CONNECTED) + || CallPeerState.isOnHold(prevPeerState)) + { + responseIQ = JinglePacketFactory.createBye( + getProtocolProvider().getOurJID(), peerJID, getSID()); + } + else if (CallPeerState.CONNECTING.equals(prevPeerState) + || CallPeerState.CONNECTING_WITH_EARLY_MEDIA.equals(prevPeerState) + || CallPeerState.ALERTING_REMOTE_SIDE.equals(prevPeerState)) + { + String jingleSID = getSID(); + + if(jingleSID == null) + { + synchronized(sidSyncRoot) + { + // we cancelled the call too early because the jingleSID + // is null (i.e. the session-initiate has not been created) + // and no need to send the session-terminate + cancelled = true; + return; + } + } + + responseIQ = JinglePacketFactory.createCancel( + getProtocolProvider().getOurJID(), peerJID, getSID()); + } + else if (prevPeerState.equals(CallPeerState.INCOMING_CALL)) + { + responseIQ = JinglePacketFactory.createBusy( + getProtocolProvider().getOurJID(), peerJID, getSID()); + } + else if (prevPeerState.equals(CallPeerState.BUSY) + || prevPeerState.equals(CallPeerState.FAILED)) + { + // For FAILED and BUSY we only need to update CALL_STATUS + // as everything else has been done already. + } + else + { + logger.info("Could not determine call peer state!"); + } + + if (responseIQ != null) + { + if (reasonOtherExtension != null) + { + ReasonPacketExtension reason + = (ReasonPacketExtension) + responseIQ.getExtension( + ReasonPacketExtension.ELEMENT_NAME, + ReasonPacketExtension.NAMESPACE); + + if (reason != null) + { + reason.setOtherExtension(reasonOtherExtension); + } + else if(reasonOtherExtension instanceof ReasonPacketExtension) + { + responseIQ.setReason( + (ReasonPacketExtension)reasonOtherExtension); + } + } + + getProtocolProvider().getConnection().sendPacket(responseIQ); + } + } + + /** + * Creates and sends a session-initiate {@link JingleIQ}. + * + * @param sessionInitiateExtensions a collection of additional and optional + * PacketExtensions to be added to the session-initiate + * {@link JingleIQ} which is to initiate the session with this + * CallPeerJabberImpl + * @throws OperationFailedException exception + */ + protected synchronized void initiateSession( + Iterable sessionInitiateExtensions) + throws OperationFailedException + { + initiator = false; + + //Create the media description that we'd like to send to the other side. + List offer + = getMediaHandler().createContentList(); + + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + + synchronized(sidSyncRoot) + { + sessionInitIQ + = JinglePacketFactory.createSessionInitiate( + protocolProvider.getOurJID(), + this.peerJID, + JingleIQ.generateSID(), + offer); + + if(cancelled) + { + // we cancelled the call too early so no need to send the + // session-initiate to peer + getMediaHandler().getTransportManager().close(); + return; + } + } + + if (sessionInitiateExtensions != null) + { + for (PacketExtension sessionInitiateExtension + : sessionInitiateExtensions) + { + sessionInitIQ.addExtension(sessionInitiateExtension); + } + } + + protocolProvider.getConnection().sendPacket(sessionInitIQ); + } + + /** + * Notifies this instance that a specific ColibriConferenceIQ has + * been received. This CallPeerJabberImpl uses the part of the + * information provided in the specified conferenceIQ which + * concerns it only. + * + * @param conferenceIQ the ColibriConferenceIQ which has been + * received + */ + void processColibriConferenceIQ(ColibriConferenceIQ conferenceIQ) + { + /* + * CallPeerJabberImpl does not itself/directly know the specifics + * related to the channels allocated on the Jitsi Videobridge server. + * The channels contain transport and media-related information so + * forward the notification to CallPeerMediaHandlerJabberImpl. + */ + getMediaHandler().processColibriConferenceIQ(conferenceIQ); + } + + /** + * Processes the content-accept {@link JingleIQ}. + * + * @param content The {@link JingleIQ} that contains content that remote + * peer has accepted + */ + public void processContentAccept(JingleIQ content) + { + List contents = content.getContentList(); + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + try + { + mediaHandler + .getTransportManager() + .wrapupConnectivityEstablishment(); + mediaHandler.processAnswer(contents); + for (ContentPacketExtension c : contents) + setSenders(getMediaType(c), c.getSenders()); + } + catch (Exception e) + { + logger.warn("Failed to process a content-accept", e); + + // Send an error response. + String reason = "Error: " + e.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + getProtocolProvider().getOurJID(), + peerJID, + sessionInitIQ.getSID(), + Reason.INCOMPATIBLE_PARAMETERS, + reason); + + setState(CallPeerState.FAILED, reason); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + + mediaHandler.start(); + } + + /** + * Processes the content-add {@link JingleIQ}. + * + * @param content The {@link JingleIQ} that contains content that remote + * peer wants to be added + */ + public void processContentAdd(final JingleIQ content) + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + List contents = content.getContentList(); + Iterable answerContents; + JingleIQ contentIQ; + boolean noCands = false; + MediaStream oldVideoStream = mediaHandler.getStream(MediaType.VIDEO); + + if(logger.isInfoEnabled()) + logger.info("Looking for candidates in content-add."); + try + { + if(!contentAddWithNoCands) + { + mediaHandler.processOffer(contents); + + /* + * Gingle transport will not put candidate in session-initiate + * and content-add. + */ + for(ContentPacketExtension c : contents) + { + if(JingleUtils.getFirstCandidate(c, 1) == null) + { + contentAddWithNoCands = true; + noCands = true; + } + } + } + + // if no candidates are present, launch a new Thread which will + // process and wait for the connectivity establishment (otherwise + // the existing thread will be blocked and thus cannot receive + // transport-info with candidates + if(noCands) + { + new Thread() + { + @Override + public void run() + { + try + { + synchronized(candSyncRoot) + { + candSyncRoot.wait(); + } + } + catch(InterruptedException e) + { + } + + processContentAdd(content); + contentAddWithNoCands = false; + } + }.start(); + if(logger.isInfoEnabled()) + logger.info("No candidates found in content-add, started " + + "new thread."); + return; + } + + mediaHandler + .getTransportManager() + .wrapupConnectivityEstablishment(); + if(logger.isInfoEnabled()) + logger.info("Wrapping up connectivity establishment"); + answerContents = mediaHandler.generateSessionAccept(); + contentIQ = null; + } + catch(Exception e) + { + logger.warn("Exception occurred", e); + + answerContents = null; + contentIQ + = JinglePacketFactory.createContentReject( + getProtocolProvider().getOurJID(), + this.peerJID, + getSID(), + answerContents); + } + + if(contentIQ == null) + { + /* send content-accept */ + contentIQ + = JinglePacketFactory.createContentAccept( + getProtocolProvider().getOurJID(), + this.peerJID, + getSID(), + answerContents); + for (ContentPacketExtension c : answerContents) + setSenders(getMediaType(c), c.getSenders()); + } + + getProtocolProvider().getConnection().sendPacket(contentIQ); + mediaHandler.start(); + + /* + * If a remote peer turns her video on in a conference which is hosted + * by the local peer and the local peer is not streaming her local + * video, reinvite the other remote peers to enable RTP translation. + */ + if (oldVideoStream == null) + { + MediaStream newVideoStream + = mediaHandler.getStream(MediaType.VIDEO); + + if ((newVideoStream != null) + && mediaHandler.isRTPTranslationEnabled(MediaType.VIDEO)) + { + try + { + getCall().modifyVideoContent(); + } + catch (OperationFailedException ofe) + { + logger.error("Failed to enable RTP translation", ofe); + } + } + } + } + + /** + * Processes the content-modify {@link JingleIQ}. + * + * @param content The {@link JingleIQ} that contains content that remote + * peer wants to be modified + */ + public void processContentModify(JingleIQ content) + { + ContentPacketExtension ext = content.getContentList().get(0); + MediaType mediaType = getMediaType(ext); + + try + { + boolean modify + = (ext.getFirstChildOfType(RtpDescriptionPacketExtension.class) + != null); + + getMediaHandler().reinitContent(ext.getName(), ext, modify); + + setSenders(mediaType, ext.getSenders()); + + if (MediaType.VIDEO.equals(mediaType)) + getCall().modifyVideoContent(); + } + catch(Exception e) + { + logger.info("Failed to process an incoming content-modify", e); + + // Send an error response. + String reason = "Error: " + e.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + getProtocolProvider().getOurJID(), + peerJID, + sessionInitIQ.getSID(), + Reason.INCOMPATIBLE_PARAMETERS, + reason); + + setState(CallPeerState.FAILED, reason); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + } + + /** + * Processes the content-reject {@link JingleIQ}. + * + * @param content The {@link JingleIQ} + */ + public void processContentReject(JingleIQ content) + { + if(content.getContentList().isEmpty()) + { + //send an error response; + JingleIQ errResp = JinglePacketFactory.createSessionTerminate( + sessionInitIQ.getTo(), sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS, + "Error: content rejected"); + + setState(CallPeerState.FAILED, "Error: content rejected"); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + } + + /** + * Processes the content-remove {@link JingleIQ}. + * + * @param content The {@link JingleIQ} that contains content that remote + * peer wants to be removed + */ + public void processContentRemove(JingleIQ content) + { + List contents = content.getContentList(); + boolean videoContentRemoved = false; + + if (!contents.isEmpty()) + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + for(ContentPacketExtension c : contents) + { + mediaHandler.removeContent(c.getName()); + + MediaType mediaType = getMediaType(c); + setSenders(mediaType, SendersEnum.none); + + if (MediaType.VIDEO.equals(mediaType)) + videoContentRemoved = true; + } + + /* + * TODO XEP-0166: Jingle says: If the content-remove results in zero + * content definitions for the session, the entity that receives the + * content-remove SHOULD send a session-terminate action to the + * other party (since a session with no content definitions is + * void). + */ + } + + if (videoContentRemoved) + { + // removing of the video content might affect the other sessions + // in the call + try + { + getCall().modifyVideoContent(); + } + catch (Exception e) + { + logger.warn("Failed to update Jingle sessions"); + } + } + } + + /** + * Processes a session-accept {@link JingleIQ}. + * + * @param sessionInitIQ The session-accept {@link JingleIQ} to process. + */ + public void processSessionAccept(JingleIQ sessionInitIQ) + { + this.sessionInitIQ = sessionInitIQ; + + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + List answer = sessionInitIQ.getContentList(); + + try + { + mediaHandler + .getTransportManager() + .wrapupConnectivityEstablishment(); + mediaHandler.processAnswer(answer); + for (ContentPacketExtension c : answer) + setSenders(getMediaType(c), c.getSenders()); + } + catch(Exception exc) + { + if (logger.isInfoEnabled()) + logger.info("Failed to process a session-accept", exc); + + //send an error response; + JingleIQ errResp = JinglePacketFactory.createSessionTerminate( + sessionInitIQ.getTo(), sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), Reason.INCOMPATIBLE_PARAMETERS, + exc.getClass().getName() + ": " + exc.getMessage()); + + setState(CallPeerState.FAILED, "Error: " + exc.getMessage()); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + + //tell everyone we are connected so that the audio notifications would + //stop + setState(CallPeerState.CONNECTED); + + mediaHandler.start(); + + /* + * If video was added to the call after we sent the session-initiate + * to this peer, it needs to be added to this peer's session with a + * content-add. + */ + sendModifyVideoContent(); + } + + /** + * Handles the specified session info packet according to its + * content. + * + * @param info the {@link SessionInfoPacketExtension} that we just received. + */ + public void processSessionInfo(SessionInfoPacketExtension info) + { + switch (info.getType()) + { + case ringing: + setState(CallPeerState.ALERTING_REMOTE_SIDE); + break; + case hold: + getMediaHandler().setRemotelyOnHold(true); + reevalRemoteHoldStatus(); + break; + case unhold: + case active: + getMediaHandler().setRemotelyOnHold(false); + reevalRemoteHoldStatus(); + break; + default: + logger.warn("Received SessionInfoPacketExtension of unknown type"); + } + } + + /** + * Processes the session initiation {@link JingleIQ} that we were created + * with, passing its content to the media handler and then sends either a + * "session-info/ringing" or a "session-terminate" response. + * + * @param sessionInitIQ The {@link JingleIQ} that created the session that + * we are handling here. + */ + protected synchronized void processSessionInitiate(JingleIQ sessionInitIQ) + { + // Do initiate the session. + this.sessionInitIQ = sessionInitIQ; + this.initiator = true; + + // This is the SDP offer that came from the initial session-initiate. + // Contrary to SIP, we are guaranteed to have content because XEP-0166 + // says: "A session consists of at least one content type at a time." + List offer = sessionInitIQ.getContentList(); + + try + { + getMediaHandler().processOffer(offer); + + CoinPacketExtension coin = null; + + for(PacketExtension ext : sessionInitIQ.getExtensions()) + { + if(ext.getElementName().equals( + CoinPacketExtension.ELEMENT_NAME)) + { + coin = (CoinPacketExtension)ext; + break; + } + } + + /* does the call peer acts as a conference focus ? */ + if(coin != null) + { + setConferenceFocus(Boolean.parseBoolean( + (String)coin.getAttribute("isfocus"))); + } + } + catch(Exception ex) + { + logger.info("Failed to process an incoming session initiate", ex); + + //send an error response; + String reasonText = "Error: " + ex.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + sessionInitIQ.getTo(), + sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), + Reason.INCOMPATIBLE_PARAMETERS, + reasonText); + + setState(CallPeerState.FAILED, reasonText); + getProtocolProvider().getConnection().sendPacket(errResp); + return; + } + + // If we do not get the info about the remote peer yet. Get it right + // now. + if(this.getDiscoveryInfo() == null) + { + String calleeURI = sessionInitIQ.getFrom(); + retrieveDiscoveryInfo(calleeURI); + } + + //send a ringing response + if (logger.isTraceEnabled()) + logger.trace("will send ringing response: "); + + getProtocolProvider().getConnection().sendPacket( + JinglePacketFactory.createRinging(sessionInitIQ)); + + synchronized(sessionInitiateSyncRoot) + { + sessionInitiateProcessed = true; + sessionInitiateSyncRoot.notify(); + } + + //if this is a 3264 initiator, let's give them an early peek at our + //answer so that they could start ICE (SIP-2-Jingle gateways won't + //be able to send their candidates unless they have this) + DiscoverInfo discoverInfo = getDiscoveryInfo(); + if ((discoverInfo != null) + && discoverInfo.containsFeature( + ProtocolProviderServiceJabberImpl.URN_IETF_RFC_3264)) + { + getProtocolProvider().getConnection().sendPacket( + JinglePacketFactory.createDescriptionInfo( + sessionInitIQ.getTo(), + sessionInitIQ.getFrom(), + sessionInitIQ.getSID(), + getMediaHandler().getLocalContentList())); + } + } + + /** + * Puts this peer into a {@link CallPeerState#DISCONNECTED}, indicating a + * reason to the user, if there is one. + * + * @param jingleIQ the {@link JingleIQ} that's terminating our session. + */ + public void processSessionTerminate(JingleIQ jingleIQ) + { + String reasonStr = "Call ended by remote side."; + ReasonPacketExtension reasonExt = jingleIQ.getReason(); + + if(reasonExt != null) + { + Reason reason = reasonExt.getReason(); + + if(reason != null) + reasonStr += " Reason: " + reason.toString() + "."; + + String text = reasonExt.getText(); + + if(text != null) + reasonStr += " " + text; + } + + setState(CallPeerState.DISCONNECTED, reasonStr); + } + + /** + * Processes a specific "XEP-0251: Jingle Session Transfer" + * transfer packet (extension). + * + * @param transfer the "XEP-0251: Jingle Session Transfer" transfer packet + * (extension) to process + * @throws OperationFailedException if anything goes wrong while processing + * the specified transfer packet (extension) + */ + public void processTransfer(TransferPacketExtension transfer) + throws OperationFailedException + { + String attendantAddress = transfer.getFrom(); + + if (attendantAddress == null) + { + throw new OperationFailedException( + "Session transfer must contain a \'from\' attribute value.", + OperationFailedException.ILLEGAL_ARGUMENT); + } + + String calleeAddress = transfer.getTo(); + + if (calleeAddress == null) + { + throw new OperationFailedException( + "Session transfer must contain a \'to\' attribute value.", + OperationFailedException.ILLEGAL_ARGUMENT); + } + + // Checks if the transfer remote peer is contained by the roster of this + // account. + Roster roster = getProtocolProvider().getConnection().getRoster(); + if(!roster.contains(StringUtils.parseBareAddress(calleeAddress))) + { + String failedMessage = + "Transfer impossible:\n" + + "Account roster does not contain transfer peer: " + + StringUtils.parseBareAddress(calleeAddress); + setState(CallPeerState.FAILED, failedMessage); + logger.info(failedMessage); + } + + OperationSetBasicTelephonyJabberImpl basicTelephony + = (OperationSetBasicTelephonyJabberImpl) + getProtocolProvider() + .getOperationSet(OperationSetBasicTelephony.class); + CallJabberImpl calleeCall = new CallJabberImpl(basicTelephony); + TransferPacketExtension calleeTransfer = new TransferPacketExtension(); + String sid = transfer.getSID(); + + calleeTransfer.setFrom(attendantAddress); + if (sid != null) + { + calleeTransfer.setSID(sid); + calleeTransfer.setTo(calleeAddress); + } + basicTelephony.createOutgoingCall( + calleeCall, + calleeAddress, + Arrays.asList(new PacketExtension[] { calleeTransfer })); + } + + /** + * Processes the transport-info {@link JingleIQ}. + * + * @param jingleIQ the transport-info {@link JingleIQ} to process + */ + public void processTransportInfo(JingleIQ jingleIQ) + { + /* + * The transport-info action is used to exchange transport candidates so + * it only concerns the mediaHandler. + */ + try + { + if(isInitiator()) + { + synchronized(sessionInitiateSyncRoot) + { + if(!sessionInitiateProcessed) + { + try + { + sessionInitiateSyncRoot.wait(); + } + catch(InterruptedException e) + { + } + } + } + } + + getMediaHandler().processTransportInfo( + jingleIQ.getContentList()); + } + catch (OperationFailedException ofe) + { + logger.warn("Failed to process an incoming transport-info", ofe); + + //send an error response + String reasonText = "Error: " + ofe.getMessage(); + JingleIQ errResp + = JinglePacketFactory.createSessionTerminate( + getProtocolProvider().getOurJID(), + peerJID, + sessionInitIQ.getSID(), + Reason.GENERAL_ERROR, + reasonText); + + setState(CallPeerState.FAILED, reasonText); + getProtocolProvider().getConnection().sendPacket(errResp); + + return; + } + + synchronized(candSyncRoot) + { + candSyncRoot.notify(); + } + } + + /** + * Puts the CallPeer represented by this instance on or off hold. + * + * @param onHold true to have the CallPeer put on hold; + * false, otherwise + * + * @throws OperationFailedException if we fail to construct or send the + * INVITE request putting the remote side on/off hold. + */ + public void putOnHold(boolean onHold) + throws OperationFailedException + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + mediaHandler.setLocallyOnHold(onHold); + + SessionInfoType type; + + if(onHold) + type = SessionInfoType.hold; + else + { + type = SessionInfoType.unhold; + getMediaHandler().reinitAllContents(); + } + + //we are now on hold and need to realize this before potentially + //spoiling it all with an exception while sending the packet :). + reevalLocalHoldStatus(); + + JingleIQ onHoldIQ = JinglePacketFactory.createSessionInfo( + getProtocolProvider().getOurJID(), + peerJID, + getSID(), + type); + + getProtocolProvider().getConnection().sendPacket(onHoldIQ); + } + + /** + * Send a content-add to add video setup. + */ + private void sendAddVideoContent() + { + List contents; + + try + { + contents = getMediaHandler().createContentList(MediaType.VIDEO); + } + catch(Exception exc) + { + logger.warn("Failed to gather content for video type", exc); + return; + } + + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + JingleIQ contentIQ + = JinglePacketFactory.createContentAdd( + protocolProvider.getOurJID(), + this.peerJID, + getSID(), + contents); + + protocolProvider.getConnection().sendPacket(contentIQ); + } + + /** + * Sends a content message to reflect changes in the setup such as + * the local peer/user becoming a conference focus. + */ + public void sendCoinSessionInfo() + { + JingleIQ sessionInfoIQ + = JinglePacketFactory.createSessionInfo( + getProtocolProvider().getOurJID(), + this.peerJID, + getSID()); + CoinPacketExtension coinExt + = new CoinPacketExtension(getCall().isConferenceFocus()); + + sessionInfoIQ.addExtension(coinExt); + getProtocolProvider().getConnection().sendPacket(sessionInfoIQ); + } + + /** + * Returns the MediaDirection that should be set for the content + * of type mediaType in the Jingle session for this + * CallPeer. + * If we are the focus of a conference and are doing RTP translation, + * takes into account the other CallPeers in the Call. + * + * @param mediaType the MediaType for which to return the + * MediaDirection + * @return the MediaDirection that should be used for the content + * of type mediaType in the Jingle session for this + * CallPeer. + */ + private MediaDirection getDirectionForJingle(MediaType mediaType) + { + MediaDirection direction = MediaDirection.INACTIVE; + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + // If we are streaming media, the direction should allow sending + if ( (MediaType.AUDIO == mediaType && + mediaHandler.isLocalAudioTransmissionEnabled()) || + (MediaType.VIDEO == mediaType && + isLocalVideoStreaming())) + direction = direction.or(MediaDirection.SENDONLY); + + // If we are receiving media from this CallPeer, the direction should + // allow receiving + SendersEnum senders = getSenders(mediaType); + if (senders == null || senders == SendersEnum.both || + (isInitiator() && senders == SendersEnum.initiator) || + (!isInitiator() && senders == SendersEnum.responder)) + direction = direction.or(MediaDirection.RECVONLY); + + // If we are the focus of a conference and we are receiving media from + // another CallPeer in the same Call, the direction should allow sending + CallJabberImpl call = getCall(); + if (call != null && call.isConferenceFocus()) + { + for (CallPeerJabberImpl peer : call.getCallPeerList()) + { + if (peer != this) + { + senders = peer.getSenders(mediaType); + if (senders == null || senders == SendersEnum.both || + (peer.isInitiator() + && senders == SendersEnum.initiator) || + (!peer.isInitiator() + && senders == SendersEnum.responder)) + { + direction = direction.or(MediaDirection.SENDONLY); + break; + } + } + } + } + + return direction; + } + + /** + * Send, if necessary, a jingle content message to reflect change + * in video setup. Whether the jingle session should have a video content, + * and if so, the value of the senders field is determined + * based on whether we are streaming local video and, if we are the focus + * of a conference, on the other peers in the conference. + * The message can be content-modify if video content exists (and the + * senders field changes), content-add or content-remove. + * + * @return true if a jingle content message was sent. + */ + public boolean sendModifyVideoContent() + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + MediaDirection direction = getDirectionForJingle(MediaType.VIDEO); + + ContentPacketExtension remoteContent + = mediaHandler.getLocalContent(MediaType.VIDEO.toString()); + + if (remoteContent == null) + { + if (direction == MediaDirection.INACTIVE) + { + // no video content, none needed + return false; + } + else + { + if (getState() == CallPeerState.CONNECTED) + { + if (logger.isInfoEnabled()) + logger.info("Adding video content for " + this); + sendAddVideoContent(); + return true; + } + return false; + } + } + else + { + if (direction == MediaDirection.INACTIVE) + { + sendRemoveVideoContent(); + return true; + } + } + + SendersEnum senders = getSenders(MediaType.VIDEO); + if (senders == null) + senders = SendersEnum.both; + + SendersEnum newSenders = SendersEnum.none; + if (MediaDirection.SENDRECV == direction) + newSenders = SendersEnum.both; + else if (MediaDirection.RECVONLY == direction) + newSenders = isInitiator() + ? SendersEnum.initiator : SendersEnum.responder; + else if (MediaDirection.SENDONLY == direction) + newSenders = isInitiator() + ? SendersEnum.responder : SendersEnum.initiator; + + /* + * Send Content-Modify + */ + ContentPacketExtension ext = new ContentPacketExtension(); + String remoteContentName = remoteContent.getName(); + + ext.setSenders(newSenders); + ext.setCreator(remoteContent.getCreator()); + ext.setName(remoteContentName); + + if (newSenders != senders) + { + if (logger.isInfoEnabled()) + logger.info("Sending content modify, senders: " + + senders + "->" + newSenders); + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + JingleIQ contentIQ + = JinglePacketFactory.createContentModify( + protocolProvider.getOurJID(), + this.peerJID, + getSID(), + ext); + + protocolProvider.getConnection().sendPacket(contentIQ); + } + + try + { + mediaHandler.reinitContent(remoteContentName, ext, false); + mediaHandler.start(); + } + catch(Exception e) + { + logger.warn("Exception occurred during media reinitialization", e); + } + + return (newSenders != senders); + } + + /** + * Send a content message to reflect change in video setup (start + * or stop). + */ + public void sendModifyVideoResolutionContent() + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + ContentPacketExtension remoteContent + = mediaHandler.getRemoteContent(MediaType.VIDEO.toString()); + ContentPacketExtension content; + + logger.info("send modify-content to change resolution"); + + // send content-modify with RTP description + + // create content list with resolution + try + { + content = mediaHandler.createContentForMedia(MediaType.VIDEO); + } + catch (Exception e) + { + logger.warn("Failed to gather content for video type", e); + return; + } + + // if we are only receiving video senders is null + SendersEnum senders = remoteContent.getSenders(); + + if (senders != null) + content.setSenders(senders); + + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + JingleIQ contentIQ + = JinglePacketFactory.createContentModify( + protocolProvider.getOurJID(), + this.peerJID, + getSID(), + content); + + protocolProvider.getConnection().sendPacket(contentIQ); + + try + { + mediaHandler.reinitContent(remoteContent.getName(), content, false); + mediaHandler.start(); + } + catch(Exception e) + { + logger.warn("Exception occurred when media reinitialization", e); + } + } + + /** + * Send a content-remove to remove video setup. + */ + private void sendRemoveVideoContent() + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + + ContentPacketExtension content = new ContentPacketExtension(); + ContentPacketExtension remoteContent + = mediaHandler.getRemoteContent(MediaType.VIDEO.toString()); + if (remoteContent == null) + return; + String remoteContentName = remoteContent.getName(); + + content.setName(remoteContentName); + content.setCreator(remoteContent.getCreator()); + content.setSenders(remoteContent.getSenders()); + + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + JingleIQ contentIQ + = JinglePacketFactory.createContentRemove( + protocolProvider.getOurJID(), + this.peerJID, + getSID(), + Arrays.asList(content)); + + protocolProvider.getConnection().sendPacket(contentIQ); + mediaHandler.removeContent(remoteContentName); + setSenders(MediaType.VIDEO, SendersEnum.none); + } + + /** + * Sends local candidate addresses from the local peer to the remote peer + * using the transport-info {@link JingleIQ}. + * + * @param contents the local candidate addresses to be sent from the local + * peer to the remote peer using the transport-info + * {@link JingleIQ} + */ + protected void sendTransportInfo(Iterable contents) + { + // if the call is canceled, do not start sending candidates in + // transport-info + if(cancelled) + return; + + JingleIQ transportInfo = new JingleIQ(); + + for (ContentPacketExtension content : contents) + transportInfo.addContent(content); + + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + + transportInfo.setAction(JingleAction.TRANSPORT_INFO); + transportInfo.setFrom(protocolProvider.getOurJID()); + transportInfo.setSID(getSID()); + transportInfo.setTo(getAddress()); + transportInfo.setType(IQ.Type.SET); + + PacketCollector collector + = protocolProvider.getConnection().createPacketCollector( + new PacketIDFilter(transportInfo.getPacketID())); + + protocolProvider.getConnection().sendPacket(transportInfo); + collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); + collector.cancel(); + } + + @Override + public void setState(CallPeerState newState, String reason, int reasonCode) + { + CallPeerState oldState = getState(); + try + { + /* + * We need to dispose of the transport manager before the + * 'call' field is set to null, because if Jitsi Videobridge is in + * use, it (the call) is needed in order to expire the + * Videobridge channels. + */ + if (CallPeerState.DISCONNECTED.equals(newState) + || CallPeerState.FAILED.equals(newState)) + getMediaHandler().getTransportManager().close(); + } + finally + { + super.setState(newState, reason, reasonCode); + } + + if (CallPeerState.isOnHold(oldState) + && CallPeerState.CONNECTED.equals(newState)) + { + try + { + getCall().modifyVideoContent(); + } + catch (OperationFailedException ofe) + { + logger.error("Failed to update call video state after " + + "'hold' status removed for "+this); + } + } + } + + /** + * Transfer (in the sense of call transfer) this CallPeer to a + * specific callee address which may optionally be participating in an + * active Call. + * + * @param to the address of the callee to transfer this CallPeer to + * @param sid the Jingle session ID of the active Call between the + * local peer and the callee in the case of attended transfer; null + * in the case of unattended transfer + * @throws OperationFailedException if something goes wrong + */ + protected void transfer(String to, String sid) + throws OperationFailedException + { + JingleIQ transferSessionInfo = new JingleIQ(); + ProtocolProviderServiceJabberImpl protocolProvider + = getProtocolProvider(); + + transferSessionInfo.setAction(JingleAction.SESSION_INFO); + transferSessionInfo.setFrom(protocolProvider.getOurJID()); + transferSessionInfo.setSID(getSID()); + transferSessionInfo.setTo(getAddress()); + transferSessionInfo.setType(IQ.Type.SET); + + TransferPacketExtension transfer = new TransferPacketExtension(); + + // Attended transfer. + if (sid != null) + { + /* + * Not really sure what the value of the "from" attribute of the + * "transfer" element should be but the examples in "XEP-0251: + * Jingle Session Transfer" has it in the case of attended transfer. + */ + transfer.setFrom(protocolProvider.getOurJID()); + transfer.setSID(sid); + + // Puts on hold the 2 calls before making the attended transfer. + OperationSetBasicTelephonyJabberImpl basicTelephony + = (OperationSetBasicTelephonyJabberImpl) + protocolProvider.getOperationSet( + OperationSetBasicTelephony.class); + CallPeerJabberImpl callPeer = basicTelephony.getActiveCallPeer(sid); + if(callPeer != null) + { + if(!CallPeerState.isOnHold(callPeer.getState())) + { + callPeer.putOnHold(true); + } + } + + if(!CallPeerState.isOnHold(this.getState())) + { + this.putOnHold(true); + } + } + transfer.setTo(to); + + transferSessionInfo.addExtension(transfer); + + Connection connection = protocolProvider.getConnection(); + PacketCollector collector = connection.createPacketCollector( + new PacketIDFilter(transferSessionInfo.getPacketID())); + protocolProvider.getConnection().sendPacket(transferSessionInfo); + + Packet result + = collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); + + if(result == null) + { + // Log the failed transfer call and notify the user. + throw new OperationFailedException( + "No response to the \"transfer\" request.", + OperationFailedException.ILLEGAL_ARGUMENT); + } + else if (((IQ) result).getType() != IQ.Type.RESULT) + { + // Log the failed transfer call and notify the user. + throw new OperationFailedException( + "Remote peer does not manage call \"transfer\"." + + "Response to the \"transfer\" request is: " + + ((IQ) result).getType(), + OperationFailedException.ILLEGAL_ARGUMENT); + } + else + { + String message = ((sid == null) ? "Unattended" : "Attended") + + " transfer to: " + + to; + // Implements the SIP behavior: once the transfer is accepted, the + // current call is closed. + hangup( + false, + message, + new ReasonPacketExtension(Reason.SUCCESS, + message, + new TransferredPacketExtension())); + } + } + + /** + * {@inheritDoc} + */ + public String getEntity() + { + return getAddress(); + } + + /** + * {@inheritDoc} + * + * In Jingle there isn't an actual "direction" parameter. We use the + * senders field to calculate the direction. + */ + @Override + public MediaDirection getDirection(MediaType mediaType) + { + SendersEnum senders = getSenders(mediaType); + + if (senders == SendersEnum.none) + { + return MediaDirection.INACTIVE; + } + else if (senders == null || senders == SendersEnum.both) + { + return MediaDirection.SENDRECV; + } + else if (senders == SendersEnum.initiator) + { + return + isInitiator() + ? MediaDirection.RECVONLY + : MediaDirection.SENDONLY; + } + else //senders == SendersEnum.responder + { + return + isInitiator() + ? MediaDirection.SENDONLY + : MediaDirection.RECVONLY; + } + } + + /** + * Gets the current value of the senders field of the content with + * name mediaType in the Jingle session with this + * CallPeer. + * + * @param mediaType the MediaType for which to get the current + * value of the senders field. + * @return the current value of the senders field of the content + * with name mediaType in the Jingle session with this + * CallPeer. + */ + public SendersEnum getSenders(MediaType mediaType) + { + switch (mediaType) + { + case AUDIO: + return audioSenders; + case DATA: + /* + * FIXME DATA has been introduced as a MediaType but explicit + * support for DATA content has not been added yet. + */ + return SendersEnum.none; + case VIDEO: + return videoSenders; + default: + throw new IllegalArgumentException("mediaType"); + } + } + + /** + * Set the current value of the senders field of the content with + * name mediaType in the Jingle session with this CallPeer + * @param mediaType the MediaType for which to get the current + * value of the senders field. + * @param senders the value to set + */ + public void setSenders(MediaType mediaType, SendersEnum senders) + { + if (mediaType == null) + return; + else if (MediaType.AUDIO.equals(mediaType)) + this.audioSenders = senders; + else if (MediaType.VIDEO.equals(mediaType)) + this.videoSenders = senders; + else + throw new IllegalArgumentException("mediaType"); + } + + /** + * Gets the MediaType of content. If content + * does not have a description child and therefore not + * MediaType can be associated with it, tries to take the + * MediaType from the session's already established contents with + * the same name as content + * @param content the ContentPacketExtention for which to get the + * MediaType + * @return the MediaType of content. + */ + public MediaType getMediaType(ContentPacketExtension content) + { + String contentName = content.getName(); + if (contentName == null) + return null; + + MediaType mediaType = JingleUtils.getMediaType(content); + if (mediaType == null) + { + CallPeerMediaHandlerJabberImpl mediaHandler = getMediaHandler(); + for (MediaType m : MediaType.values()) + { + ContentPacketExtension sessionContent + = mediaHandler.getRemoteContent(m.toString()); + if (sessionContent == null) + sessionContent = mediaHandler.getLocalContent(m.toString()); + + if (sessionContent != null + && contentName.equals(sessionContent.getName())) + { + mediaType = m; + break; + } + } + } + + return mediaType; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java index e81b43a..56cf63c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,585 +15,585 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber; - -import java.util.*; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.coin.*; -import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.media.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.util.xml.*; -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.*; -import org.jivesoftware.smack.packet.*; -import org.jivesoftware.smack.packet.IQ.Type; -import org.jivesoftware.smack.util.*; -import org.jivesoftware.smackx.packet.*; - -/** - * Implements OperationSetTelephonyConferencing for Jabber. - * - * @author Lyubomir Marinov - * @author Sebastien Vincent - * @author Boris Grozev - * @author Pawel Domas - */ -public class OperationSetTelephonyConferencingJabberImpl - extends AbstractOperationSetTelephonyConferencing< - ProtocolProviderServiceJabberImpl, - OperationSetBasicTelephonyJabberImpl, - CallJabberImpl, - CallPeerJabberImpl, - String> - implements RegistrationStateChangeListener, - PacketListener, - PacketFilter - -{ - /** - * The Logger used by the - * OperationSetTelephonyConferencingJabberImpl class and its - * instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(OperationSetTelephonyConferencingJabberImpl.class); - - /** - * The minimum interval in milliseconds between COINs sent to a single - * CallPeer. - */ - private static final int COIN_MIN_INTERVAL = 200; - - /** - * Property used to disable COIN notifications. - */ - public static final String DISABLE_COIN_PROP_NAME - = "net.java.sip.communicator.impl.protocol.jabber.DISABLE_COIN"; - - /** - * Synchronization object. - */ - private final Object lock = new Object(); - - /** - * Field indicates whether COIN notification are disabled or not. - */ - private boolean isCoinDisabled = false; - - /** - * Initializes a new OperationSetTelephonyConferencingJabberImpl - * instance which is to provide telephony conferencing services for the - * specified Jabber ProtocolProviderService implementation. - * - * @param parentProvider the Jabber ProtocolProviderService - * implementation which has requested the creation of the new instance and - * for which the new instance is to provide telephony conferencing services - */ - public OperationSetTelephonyConferencingJabberImpl( - ProtocolProviderServiceJabberImpl parentProvider) - { - super(parentProvider); - - this.isCoinDisabled - = JabberActivator.getConfigurationService() - .getBoolean(DISABLE_COIN_PROP_NAME, false); - } - - /** - * Notifies all CallPeers associated with a specific Call - * about changes in the telephony conference-related information. In - * contrast, {@link #notifyAll()} notifies all CallPeers associated - * with the telephony conference in which a specific Call is - * participating. - * - * @param call the Call whose CallPeers are to be notified - * about changes in the telephony conference-related information - */ - @Override - protected void notifyCallPeers(Call call) - { - if (!isCoinDisabled && call.isConferenceFocus()) - { - synchronized (lock) - { - // send conference-info to all CallPeers of the specified call. - for (Iterator i = call.getCallPeers(); - i.hasNext();) - { - notify(i.next()); - } - } - } - } - - /** - * Notifies a specific CallPeer about changes in the telephony - * conference-related information. - * - * @param callPeer the CallPeer to notify. - */ - private void notify(CallPeer callPeer) - { - if(!(callPeer instanceof CallPeerJabberImpl)) - return; - - //Don't send COINs to peers with might not be ready to accept COINs yet - CallPeerState peerState = callPeer.getState(); - if (peerState == CallPeerState.CONNECTING - || peerState == CallPeerState.UNKNOWN - || peerState == CallPeerState.INITIATING_CALL - || peerState == CallPeerState.DISCONNECTED - || peerState == CallPeerState.FAILED) - return; - - final CallPeerJabberImpl callPeerJabber = (CallPeerJabberImpl)callPeer; - - final long timeSinceLastCoin = System.currentTimeMillis() - - callPeerJabber.getLastConferenceInfoSentTimestamp(); - if (timeSinceLastCoin < COIN_MIN_INTERVAL) - { - if (callPeerJabber.isConfInfoScheduled()) - return; - - logger.info("Scheduling to send a COIN to " + callPeerJabber); - callPeerJabber.setConfInfoScheduled(true); - new Thread(new Runnable(){ - @Override - public void run() - { - try - { - Thread.sleep(1 + COIN_MIN_INTERVAL - timeSinceLastCoin); - } - catch (InterruptedException ie) {} - - OperationSetTelephonyConferencingJabberImpl.this - .notify(callPeerJabber); - } - }).start(); - - return; - } - - // check that callPeer supports COIN before sending him a - // conference-info - String to = getBasicTelephony().getFullCalleeURI(callPeer.getAddress()); - - // XXX if this generates actual disco#info requests we might want to - // cache it. - try - { - DiscoverInfo discoverInfo - = parentProvider.getDiscoveryManager().discoverInfo(to); - - if (!discoverInfo.containsFeature( - ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_COIN)) - { - logger.info(callPeer.getAddress() + " does not support COIN"); - callPeerJabber.setConfInfoScheduled(false); - return; - } - } - catch (XMPPException xmppe) - { - logger.warn("Failed to retrieve DiscoverInfo for " + to, xmppe); - } - - ConferenceInfoDocument currentConfInfo - = getCurrentConferenceInfo(callPeerJabber); - ConferenceInfoDocument lastSentConfInfo - = callPeerJabber.getLastConferenceInfoSent(); - - ConferenceInfoDocument diff; - - if (lastSentConfInfo == null) - diff = currentConfInfo; - else - diff = getConferenceInfoDiff(lastSentConfInfo, currentConfInfo); - - if (diff != null) - { - int newVersion - = lastSentConfInfo == null - ? 1 - : lastSentConfInfo.getVersion() + 1; - diff.setVersion(newVersion); - - IQ iq = getConferenceInfo(callPeerJabber, diff); - - if (iq != null) - { - parentProvider.getConnection().sendPacket(iq); - - // We save currentConfInfo, because it is of state "full", while - // diff could be a partial - currentConfInfo.setVersion(newVersion); - callPeerJabber.setLastConferenceInfoSent(currentConfInfo); - callPeerJabber.setLastConferenceInfoSentTimestamp( - System.currentTimeMillis()); - } - } - callPeerJabber.setConfInfoScheduled(false); - } - - /** - * Generates the conference-info IQ to be sent to a specific - * CallPeer in order to notify it of the current state of the - * conference managed by the local peer. - * - * @param callPeer the CallPeer to generate conference-info XML for - * @param confInfo the ConferenceInformationDocument which is to be - * included in the IQ - * @return the conference-info IQ to be sent to the specified - * callPeer in order to notify it of the current state of the - * conference managed by the local peer - */ - private IQ getConferenceInfo(CallPeerJabberImpl callPeer, - final ConferenceInfoDocument confInfo) - { - String callPeerSID = callPeer.getSID(); - - if (callPeerSID == null) - return null; - - IQ iq = new IQ(){ - @Override - public String getChildElementXML() - { - return confInfo.toXml(); - } - }; - - CallJabberImpl call = callPeer.getCall(); - - iq.setFrom(call.getProtocolProvider().getOurJID()); - iq.setTo(callPeer.getAddress()); - iq.setType(Type.SET); - - return iq; - } - - /** - * Implementation of method registrationStateChange from - * interface RegistrationStateChangeListener for setting up (or down) - * our JingleManager when an XMPPConnection is available - * - * @param evt the event received - */ - @Override - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - super.registrationStateChanged(evt); - - RegistrationState registrationState = evt.getNewState(); - - if (RegistrationState.REGISTERED.equals(registrationState)) - { - if(logger.isDebugEnabled()) - logger.debug("Subscribes to Coin packets"); - subscribeForCoinPackets(); - } - else if (RegistrationState.UNREGISTERED.equals(registrationState)) - { - if(logger.isDebugEnabled()) - logger.debug("Unsubscribes to Coin packets"); - unsubscribeForCoinPackets(); - } - } - - /** - * Creates a new outgoing Call into which conference callees are to - * be invited by this OperationSetTelephonyConferencing. - * - * @return a new outgoing Call into which conference callees are to - * be invited by this OperationSetTelephonyConferencing - * @throws OperationFailedException if anything goes wrong - */ - @Override - protected CallJabberImpl createOutgoingCall() - throws OperationFailedException - { - return new CallJabberImpl(getBasicTelephony()); - } - - /** - * {@inheritDoc} - * - * Implements the protocol-dependent part of the logic of inviting a callee - * to a Call. The protocol-independent part of that logic is - * implemented by - * {@link AbstractOperationSetTelephonyConferencing#inviteCalleeToCall(String,Call)}. - */ - @Override - protected CallPeer doInviteCalleeToCall( - String calleeAddress, - CallJabberImpl call) - throws OperationFailedException - { - return - getBasicTelephony().createOutgoingCall( - call, - calleeAddress, - Arrays.asList( - new PacketExtension[] - { - new CoinPacketExtension(true) - })); - } - - /** - * Parses a String value which represents a callee address - * specified by the user into an object which is to actually represent the - * callee during the invitation to a conference Call. - * - * @param calleeAddressString a String value which represents a - * callee address to be parsed into an object which is to actually represent - * the callee during the invitation to a conference Call - * @return an object which is to actually represent the specified - * calleeAddressString during the invitation to a conference - * Call - * @throws OperationFailedException if parsing the specified - * calleeAddressString fails - */ - @Override - protected String parseAddressString(String calleeAddressString) - throws OperationFailedException - { - return getBasicTelephony().getFullCalleeURI(calleeAddressString); - } - - /** - * Subscribes us to notifications about incoming Coin packets. - */ - private void subscribeForCoinPackets() - { - parentProvider.getConnection().addPacketListener(this, this); - } - - /** - * Unsubscribes us from notifications about incoming Coin packets. - */ - private void unsubscribeForCoinPackets() - { - XMPPConnection connection = parentProvider.getConnection(); - - if (connection != null) - connection.removePacketListener(this); - } - - /** - * Tests whether or not the specified packet should be handled by this - * operation set. This method is called by smack prior to packet delivery - * and it would only accept CoinIQs. - * - * @param packet the packet to test. - * @return true if and only if packet passes the filter. - */ - public boolean accept(Packet packet) - { - return (packet instanceof CoinIQ); - } - - /** - * Handles incoming jingle packets and passes them to the corresponding - * method based on their action. - * - * @param packet the packet to process. - */ - public void processPacket(Packet packet) - { - CoinIQ coinIQ = (CoinIQ) packet; - String errorMessage = null; - - //first ack all "set" requests. - IQ.Type type = coinIQ.getType(); - if (type == IQ.Type.SET) - { - IQ ack = IQ.createResultIQ(coinIQ); - - parentProvider.getConnection().sendPacket(ack); - } - else if(type == IQ.Type.ERROR) - { - XMPPError error = coinIQ.getError(); - if(error != null) - { - String msg = error.getMessage(); - errorMessage = ((msg != null)? (msg + " ") : "") - + "Error code: " + error.getCode(); - } - - logger.error("Received error in COIN packet. "+errorMessage); - } - - String sid = coinIQ.getSID(); - - if (sid != null) - { - CallPeerJabberImpl callPeer - = getBasicTelephony().getActiveCallsRepository().findCallPeer( - sid); - - - if (callPeer != null) - { - if(type == IQ.Type.ERROR) - { - callPeer.fireConferenceMemberErrorEvent(errorMessage); - return; - } - - if (logger.isDebugEnabled()) - logger.debug("Processing COIN from " + coinIQ.getFrom() - + " (version=" + coinIQ.getVersion() + ")"); - - handleCoin(callPeer, coinIQ); - } - } - } - - /** - * Handles a specific CoinIQ sent from a specific - * CallPeer. - * - * @param callPeer the CallPeer from which the specified - * CoinIQ was sent - * @param coinIQ the CoinIQ which was sent from the specified - * callPeer - */ - private void handleCoin(CallPeerJabberImpl callPeer, CoinIQ coinIQ) - { - try - { - setConferenceInfoXML(callPeer, coinIQ.getChildElementXML()); - } - catch (XMLException e) - { - logger.error("Could not handle received COIN from " + callPeer - + ": " + coinIQ); - } - } - - /** - * {@inheritDoc} - * - * For COINs (XEP-0298), we use the attributes of the - * conference-info element to piggyback a Jingle SID. This is - * temporary and should be removed once we choose a better way to pass the - * SID. - */ - @Override - protected ConferenceInfoDocument getCurrentConferenceInfo( - MediaAwareCallPeer callPeer) - { - ConferenceInfoDocument confInfo - = super.getCurrentConferenceInfo(callPeer); - - if (callPeer instanceof CallPeerJabberImpl - && confInfo != null) - { - confInfo.setSid(((CallPeerJabberImpl)callPeer).getSID()); - } - return confInfo; - } - - /** - * {@inheritDoc} - */ - @Override - protected String getLocalEntity(CallPeer callPeer) - { - JingleIQ sessionIQ = ((CallPeerJabberImpl)callPeer).getSessionIQ(); - String from = sessionIQ.getFrom(); - String chatRoomName = StringUtils.parseBareAddress(from); - OperationSetMultiUserChatJabberImpl opSetMUC - = (OperationSetMultiUserChatJabberImpl) - parentProvider.getOperationSet(OperationSetMultiUserChat.class); - ChatRoom room = null; - if(opSetMUC != null) - room = opSetMUC.getChatRoom(chatRoomName); - - if(room != null) - return "xmpp:" + chatRoomName + "/" + room.getUserNickname(); - - return "xmpp:" + parentProvider.getOurJID(); - } - - /** - * {@inheritDoc} - */ - @Override - protected String getLocalDisplayName() - { - return null; - } - - /** - * {@inheritDoc} - * - * The URI of the returned ConferenceDescription is the occupant - * JID with which we have joined the room. - * - * If a Videobridge is available for our ProtocolProviderService - * we use it. TODO: this should be relaxed when we refactor the Videobridge - * implementation, so that any Videobridge (on any protocol provider) can - * be used. - */ - @Override - public ConferenceDescription setupConference(final ChatRoom chatRoom) - { - OperationSetVideoBridge videoBridge - = parentProvider.getOperationSet(OperationSetVideoBridge.class); - boolean isVideobridge = (videoBridge != null) && videoBridge.isActive(); - - CallJabberImpl call = new CallJabberImpl(getBasicTelephony()); - call.setAutoAnswer(true); - - String uri = "xmpp:" + chatRoom.getIdentifier() + - "/" + chatRoom.getUserNickname(); - - ConferenceDescription cd - = new ConferenceDescription(uri, call.getCallID()); - - call.addCallChangeListener(new CallChangeListener() - { - @Override - public void callStateChanged(CallChangeEvent ev) - { - if(CallState.CALL_ENDED.equals(ev.getNewValue())) - chatRoom.publishConference(null, null); - } - - @Override - public void callPeerRemoved(CallPeerEvent ev) - { - } - - @Override - public void callPeerAdded(CallPeerEvent ev) - { - } - }); - if (isVideobridge) - { - call.setConference(new MediaAwareCallConference(true)); - - //For Jitsi Videobridge we set the transports to RAW-UDP, otherwise - //we leave them empty (meaning both RAW-UDP and ICE could be used) - cd.addTransport( - ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0); - } - - if (logger.isInfoEnabled()) - { - logger.info("Setup a conference with uri=" + uri + " and callid=" + - call.getCallID() + ". Videobridge in use: " + isVideobridge); - } - - return cd; - } -} +package net.java.sip.communicator.impl.protocol.jabber; + +import java.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.coin.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.media.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.util.xml.*; +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; +import org.jivesoftware.smack.packet.IQ.Type; +import org.jivesoftware.smack.util.*; +import org.jivesoftware.smackx.packet.*; + +/** + * Implements OperationSetTelephonyConferencing for Jabber. + * + * @author Lyubomir Marinov + * @author Sebastien Vincent + * @author Boris Grozev + * @author Pawel Domas + */ +public class OperationSetTelephonyConferencingJabberImpl + extends AbstractOperationSetTelephonyConferencing< + ProtocolProviderServiceJabberImpl, + OperationSetBasicTelephonyJabberImpl, + CallJabberImpl, + CallPeerJabberImpl, + String> + implements RegistrationStateChangeListener, + PacketListener, + PacketFilter + +{ + /** + * The Logger used by the + * OperationSetTelephonyConferencingJabberImpl class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(OperationSetTelephonyConferencingJabberImpl.class); + + /** + * The minimum interval in milliseconds between COINs sent to a single + * CallPeer. + */ + private static final int COIN_MIN_INTERVAL = 200; + + /** + * Property used to disable COIN notifications. + */ + public static final String DISABLE_COIN_PROP_NAME + = "net.java.sip.communicator.impl.protocol.jabber.DISABLE_COIN"; + + /** + * Synchronization object. + */ + private final Object lock = new Object(); + + /** + * Field indicates whether COIN notification are disabled or not. + */ + private boolean isCoinDisabled = false; + + /** + * Initializes a new OperationSetTelephonyConferencingJabberImpl + * instance which is to provide telephony conferencing services for the + * specified Jabber ProtocolProviderService implementation. + * + * @param parentProvider the Jabber ProtocolProviderService + * implementation which has requested the creation of the new instance and + * for which the new instance is to provide telephony conferencing services + */ + public OperationSetTelephonyConferencingJabberImpl( + ProtocolProviderServiceJabberImpl parentProvider) + { + super(parentProvider); + + this.isCoinDisabled + = JabberActivator.getConfigurationService() + .getBoolean(DISABLE_COIN_PROP_NAME, false); + } + + /** + * Notifies all CallPeers associated with a specific Call + * about changes in the telephony conference-related information. In + * contrast, {@link #notifyAll()} notifies all CallPeers associated + * with the telephony conference in which a specific Call is + * participating. + * + * @param call the Call whose CallPeers are to be notified + * about changes in the telephony conference-related information + */ + @Override + protected void notifyCallPeers(Call call) + { + if (!isCoinDisabled && call.isConferenceFocus()) + { + synchronized (lock) + { + // send conference-info to all CallPeers of the specified call. + for (Iterator i = call.getCallPeers(); + i.hasNext();) + { + notify(i.next()); + } + } + } + } + + /** + * Notifies a specific CallPeer about changes in the telephony + * conference-related information. + * + * @param callPeer the CallPeer to notify. + */ + private void notify(CallPeer callPeer) + { + if(!(callPeer instanceof CallPeerJabberImpl)) + return; + + //Don't send COINs to peers with might not be ready to accept COINs yet + CallPeerState peerState = callPeer.getState(); + if (peerState == CallPeerState.CONNECTING + || peerState == CallPeerState.UNKNOWN + || peerState == CallPeerState.INITIATING_CALL + || peerState == CallPeerState.DISCONNECTED + || peerState == CallPeerState.FAILED) + return; + + final CallPeerJabberImpl callPeerJabber = (CallPeerJabberImpl)callPeer; + + final long timeSinceLastCoin = System.currentTimeMillis() + - callPeerJabber.getLastConferenceInfoSentTimestamp(); + if (timeSinceLastCoin < COIN_MIN_INTERVAL) + { + if (callPeerJabber.isConfInfoScheduled()) + return; + + logger.info("Scheduling to send a COIN to " + callPeerJabber); + callPeerJabber.setConfInfoScheduled(true); + new Thread(new Runnable(){ + @Override + public void run() + { + try + { + Thread.sleep(1 + COIN_MIN_INTERVAL - timeSinceLastCoin); + } + catch (InterruptedException ie) {} + + OperationSetTelephonyConferencingJabberImpl.this + .notify(callPeerJabber); + } + }).start(); + + return; + } + + // check that callPeer supports COIN before sending him a + // conference-info + String to = getBasicTelephony().getFullCalleeURI(callPeer.getAddress()); + + // XXX if this generates actual disco#info requests we might want to + // cache it. + try + { + DiscoverInfo discoverInfo + = parentProvider.getDiscoveryManager().discoverInfo(to); + + if (!discoverInfo.containsFeature( + ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_COIN)) + { + logger.info(callPeer.getAddress() + " does not support COIN"); + callPeerJabber.setConfInfoScheduled(false); + return; + } + } + catch (XMPPException xmppe) + { + logger.warn("Failed to retrieve DiscoverInfo for " + to, xmppe); + } + + ConferenceInfoDocument currentConfInfo + = getCurrentConferenceInfo(callPeerJabber); + ConferenceInfoDocument lastSentConfInfo + = callPeerJabber.getLastConferenceInfoSent(); + + ConferenceInfoDocument diff; + + if (lastSentConfInfo == null) + diff = currentConfInfo; + else + diff = getConferenceInfoDiff(lastSentConfInfo, currentConfInfo); + + if (diff != null) + { + int newVersion + = lastSentConfInfo == null + ? 1 + : lastSentConfInfo.getVersion() + 1; + diff.setVersion(newVersion); + + IQ iq = getConferenceInfo(callPeerJabber, diff); + + if (iq != null) + { + parentProvider.getConnection().sendPacket(iq); + + // We save currentConfInfo, because it is of state "full", while + // diff could be a partial + currentConfInfo.setVersion(newVersion); + callPeerJabber.setLastConferenceInfoSent(currentConfInfo); + callPeerJabber.setLastConferenceInfoSentTimestamp( + System.currentTimeMillis()); + } + } + callPeerJabber.setConfInfoScheduled(false); + } + + /** + * Generates the conference-info IQ to be sent to a specific + * CallPeer in order to notify it of the current state of the + * conference managed by the local peer. + * + * @param callPeer the CallPeer to generate conference-info XML for + * @param confInfo the ConferenceInformationDocument which is to be + * included in the IQ + * @return the conference-info IQ to be sent to the specified + * callPeer in order to notify it of the current state of the + * conference managed by the local peer + */ + private IQ getConferenceInfo(CallPeerJabberImpl callPeer, + final ConferenceInfoDocument confInfo) + { + String callPeerSID = callPeer.getSID(); + + if (callPeerSID == null) + return null; + + IQ iq = new IQ(){ + @Override + public String getChildElementXML() + { + return confInfo.toXml(); + } + }; + + CallJabberImpl call = callPeer.getCall(); + + iq.setFrom(call.getProtocolProvider().getOurJID()); + iq.setTo(callPeer.getAddress()); + iq.setType(Type.SET); + + return iq; + } + + /** + * Implementation of method registrationStateChange from + * interface RegistrationStateChangeListener for setting up (or down) + * our JingleManager when an XMPPConnection is available + * + * @param evt the event received + */ + @Override + public void registrationStateChanged(RegistrationStateChangeEvent evt) + { + super.registrationStateChanged(evt); + + RegistrationState registrationState = evt.getNewState(); + + if (RegistrationState.REGISTERED.equals(registrationState)) + { + if(logger.isDebugEnabled()) + logger.debug("Subscribes to Coin packets"); + subscribeForCoinPackets(); + } + else if (RegistrationState.UNREGISTERED.equals(registrationState)) + { + if(logger.isDebugEnabled()) + logger.debug("Unsubscribes to Coin packets"); + unsubscribeForCoinPackets(); + } + } + + /** + * Creates a new outgoing Call into which conference callees are to + * be invited by this OperationSetTelephonyConferencing. + * + * @return a new outgoing Call into which conference callees are to + * be invited by this OperationSetTelephonyConferencing + * @throws OperationFailedException if anything goes wrong + */ + @Override + protected CallJabberImpl createOutgoingCall() + throws OperationFailedException + { + return new CallJabberImpl(getBasicTelephony()); + } + + /** + * {@inheritDoc} + * + * Implements the protocol-dependent part of the logic of inviting a callee + * to a Call. The protocol-independent part of that logic is + * implemented by + * {@link AbstractOperationSetTelephonyConferencing#inviteCalleeToCall(String,Call)}. + */ + @Override + protected CallPeer doInviteCalleeToCall( + String calleeAddress, + CallJabberImpl call) + throws OperationFailedException + { + return + getBasicTelephony().createOutgoingCall( + call, + calleeAddress, + Arrays.asList( + new PacketExtension[] + { + new CoinPacketExtension(true) + })); + } + + /** + * Parses a String value which represents a callee address + * specified by the user into an object which is to actually represent the + * callee during the invitation to a conference Call. + * + * @param calleeAddressString a String value which represents a + * callee address to be parsed into an object which is to actually represent + * the callee during the invitation to a conference Call + * @return an object which is to actually represent the specified + * calleeAddressString during the invitation to a conference + * Call + * @throws OperationFailedException if parsing the specified + * calleeAddressString fails + */ + @Override + protected String parseAddressString(String calleeAddressString) + throws OperationFailedException + { + return getBasicTelephony().getFullCalleeURI(calleeAddressString); + } + + /** + * Subscribes us to notifications about incoming Coin packets. + */ + private void subscribeForCoinPackets() + { + parentProvider.getConnection().addPacketListener(this, this); + } + + /** + * Unsubscribes us from notifications about incoming Coin packets. + */ + private void unsubscribeForCoinPackets() + { + XMPPConnection connection = parentProvider.getConnection(); + + if (connection != null) + connection.removePacketListener(this); + } + + /** + * Tests whether or not the specified packet should be handled by this + * operation set. This method is called by smack prior to packet delivery + * and it would only accept CoinIQs. + * + * @param packet the packet to test. + * @return true if and only if packet passes the filter. + */ + public boolean accept(Packet packet) + { + return (packet instanceof CoinIQ); + } + + /** + * Handles incoming jingle packets and passes them to the corresponding + * method based on their action. + * + * @param packet the packet to process. + */ + public void processPacket(Packet packet) + { + CoinIQ coinIQ = (CoinIQ) packet; + String errorMessage = null; + + //first ack all "set" requests. + IQ.Type type = coinIQ.getType(); + if (type == IQ.Type.SET) + { + IQ ack = IQ.createResultIQ(coinIQ); + + parentProvider.getConnection().sendPacket(ack); + } + else if(type == IQ.Type.ERROR) + { + XMPPError error = coinIQ.getError(); + if(error != null) + { + String msg = error.getMessage(); + errorMessage = ((msg != null)? (msg + " ") : "") + + "Error code: " + error.getCode(); + } + + logger.error("Received error in COIN packet. "+errorMessage); + } + + String sid = coinIQ.getSID(); + + if (sid != null) + { + CallPeerJabberImpl callPeer + = getBasicTelephony().getActiveCallsRepository().findCallPeer( + sid); + + + if (callPeer != null) + { + if(type == IQ.Type.ERROR) + { + callPeer.fireConferenceMemberErrorEvent(errorMessage); + return; + } + + if (logger.isDebugEnabled()) + logger.debug("Processing COIN from " + coinIQ.getFrom() + + " (version=" + coinIQ.getVersion() + ")"); + + handleCoin(callPeer, coinIQ); + } + } + } + + /** + * Handles a specific CoinIQ sent from a specific + * CallPeer. + * + * @param callPeer the CallPeer from which the specified + * CoinIQ was sent + * @param coinIQ the CoinIQ which was sent from the specified + * callPeer + */ + private void handleCoin(CallPeerJabberImpl callPeer, CoinIQ coinIQ) + { + try + { + setConferenceInfoXML(callPeer, coinIQ.getChildElementXML()); + } + catch (XMLException e) + { + logger.error("Could not handle received COIN from " + callPeer + + ": " + coinIQ); + } + } + + /** + * {@inheritDoc} + * + * For COINs (XEP-0298), we use the attributes of the + * conference-info element to piggyback a Jingle SID. This is + * temporary and should be removed once we choose a better way to pass the + * SID. + */ + @Override + protected ConferenceInfoDocument getCurrentConferenceInfo( + MediaAwareCallPeer callPeer) + { + ConferenceInfoDocument confInfo + = super.getCurrentConferenceInfo(callPeer); + + if (callPeer instanceof CallPeerJabberImpl + && confInfo != null) + { + confInfo.setSid(((CallPeerJabberImpl)callPeer).getSID()); + } + return confInfo; + } + + /** + * {@inheritDoc} + */ + @Override + protected String getLocalEntity(CallPeer callPeer) + { + JingleIQ sessionIQ = ((CallPeerJabberImpl)callPeer).getSessionIQ(); + String from = sessionIQ.getFrom(); + String chatRoomName = StringUtils.parseBareAddress(from); + OperationSetMultiUserChatJabberImpl opSetMUC + = (OperationSetMultiUserChatJabberImpl) + parentProvider.getOperationSet(OperationSetMultiUserChat.class); + ChatRoom room = null; + if(opSetMUC != null) + room = opSetMUC.getChatRoom(chatRoomName); + + if(room != null) + return "xmpp:" + chatRoomName + "/" + room.getUserNickname(); + + return "xmpp:" + parentProvider.getOurJID(); + } + + /** + * {@inheritDoc} + */ + @Override + protected String getLocalDisplayName() + { + return null; + } + + /** + * {@inheritDoc} + * + * The URI of the returned ConferenceDescription is the occupant + * JID with which we have joined the room. + * + * If a Videobridge is available for our ProtocolProviderService + * we use it. TODO: this should be relaxed when we refactor the Videobridge + * implementation, so that any Videobridge (on any protocol provider) can + * be used. + */ + @Override + public ConferenceDescription setupConference(final ChatRoom chatRoom) + { + OperationSetVideoBridge videoBridge + = parentProvider.getOperationSet(OperationSetVideoBridge.class); + boolean isVideobridge = (videoBridge != null) && videoBridge.isActive(); + + CallJabberImpl call = new CallJabberImpl(getBasicTelephony()); + call.setAutoAnswer(true); + + String uri = "xmpp:" + chatRoom.getIdentifier() + + "/" + chatRoom.getUserNickname(); + + ConferenceDescription cd + = new ConferenceDescription(uri, call.getCallID()); + + call.addCallChangeListener(new CallChangeListener() + { + @Override + public void callStateChanged(CallChangeEvent ev) + { + if(CallState.CALL_ENDED.equals(ev.getNewValue())) + chatRoom.publishConference(null, null); + } + + @Override + public void callPeerRemoved(CallPeerEvent ev) + { + } + + @Override + public void callPeerAdded(CallPeerEvent ev) + { + } + }); + if (isVideobridge) + { + call.setConference(new MediaAwareCallConference(true)); + + //For Jitsi Videobridge we set the transports to RAW-UDP, otherwise + //we leave them empty (meaning both RAW-UDP and ICE could be used) + cd.addTransport( + ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0); + } + + if (logger.isInfoEnabled()) + { + logger.info("Setup a conference with uri=" + uri + " and callid=" + + call.getCallID() + ". Videobridge in use: " + isVideobridge); + } + + return cd; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java index b7e13ea..e388865 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,282 +15,282 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber; - -import java.util.*; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.media.*; -import net.java.sip.communicator.util.*; - -import org.jivesoftware.smack.*; -import org.jivesoftware.smack.filter.*; -import org.jivesoftware.smack.packet.*; - -/** - * Implements OperationSetVideoBridge for Jabber. - * - * @author Yana Stamcheva - * @author Lyubomir Marinov - */ -public class OperationSetVideoBridgeImpl - implements OperationSetVideoBridge, - PacketFilter, - PacketListener, - RegistrationStateChangeListener -{ - /** - * The Logger used by the OperationSetVideoBridgeImpl - * class and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(OperationSetVideoBridgeImpl.class); - - /** - * The ProtocolProviderService implementation which initialized - * this instance, owns it and is often referred to as its parent. - */ - private final ProtocolProviderServiceJabberImpl protocolProvider; - - /** - * Creates an instance of OperationSetVideoBridgeImpl by - * specifying the parent ProtocolProviderService announcing this - * operation set. - * - * @param protocolProvider the parent Jabber protocol provider - */ - public OperationSetVideoBridgeImpl( - ProtocolProviderServiceJabberImpl protocolProvider) - { - this.protocolProvider = protocolProvider; - this.protocolProvider.addRegistrationStateChangeListener(this); - } - - /** - * Implements {@link PacketFilter}. Determines whether this instance is - * interested in a specific {@link Packet}. - * OperationSetVideoBridgeImpl returns true if the - * specified packet is a {@link ColibriConferenceIQ}; otherwise, - * false. - * - * @param packet the Packet to be determined whether this instance - * is interested in it - * @return true if the specified packet is a - * ColibriConferenceIQ; otherwise, false - */ - public boolean accept(Packet packet) - { - return (packet instanceof ColibriConferenceIQ); - } - - /** - * Creates a conference call with the specified callees as call peers via a - * video bridge provided by the parent Jabber provider. - * - * @param callees the list of addresses that we should call - * @return the newly created conference call containing all CallPeers - * @throws OperationFailedException if establishing the conference call - * fails - * @throws OperationNotSupportedException if the provider does not have any - * conferencing features. - */ - public Call createConfCall(String[] callees) - throws OperationFailedException, - OperationNotSupportedException - { - return - protocolProvider - .getOperationSet(OperationSetTelephonyConferencing.class) - .createConfCall( - callees, - new MediaAwareCallConference(true)); - } - - /** - * Invites the callee represented by the specified uri to an already - * existing call using a video bridge provided by the parent Jabber provider. - * The difference between this method and createConfCall is that - * inviteCalleeToCall allows a user to add new peers to an already - * established conference. - * - * @param uri the callee to invite to an existing conf call. - * @param call the call that we should invite the callee to. - * @return the CallPeer object corresponding to the callee represented by - * the specified uri. - * @throws OperationFailedException if inviting the specified callee to the - * specified call fails - * @throws OperationNotSupportedException if allowing additional callees to - * a pre-established call is not supported. - */ - public CallPeer inviteCalleeToCall(String uri, Call call) - throws OperationFailedException, - OperationNotSupportedException - { - return - protocolProvider - .getOperationSet(OperationSetTelephonyConferencing.class) - .inviteCalleeToCall(uri, call); - } - - /** - * Indicates if there's an active video bridge available at this moment. The - * Jabber provider may announce support for video bridge, but it should not - * be used for calling until it becomes actually active. - * - * @return true to indicate that there's currently an active - * available video bridge, false - otherwise - */ - public boolean isActive() - { - String jitsiVideobridge = protocolProvider.getJitsiVideobridge(); - - return ((jitsiVideobridge != null) && (jitsiVideobridge.length() > 0)); - } - - /** - * Notifies this instance that a specific ColibriConferenceIQ has - * been received. - * - * @param conferenceIQ the ColibriConferenceIQ which has been - * received - */ - private void processColibriConferenceIQ(ColibriConferenceIQ conferenceIQ) - { - /* - * The application is not a Jitsi Videobridge server, it is a client. - * Consequently, the specified ColibriConferenceIQ is sent to it in - * relation to the part of the application's functionality which makes - * requests to a Jitsi Videobridge server i.e. CallJabberImpl. - * - * Additionally, the method processColibriConferenceIQ is presently tasked - * with processing ColibriConferenceIQ requests only. They are SET IQs - * sent by the Jitsi Videobridge server to notify the application about - * updates in the states of (colibri) conferences organized by the - * application. - */ - if (IQ.Type.SET.equals(conferenceIQ.getType()) - && conferenceIQ.getID() != null) - { - OperationSetBasicTelephony basicTelephony - = protocolProvider.getOperationSet( - OperationSetBasicTelephony.class); - - if (basicTelephony != null) - { - Iterator i = basicTelephony.getActiveCalls(); - - while (i.hasNext()) - { - Call call = i.next(); - - if (call instanceof CallJabberImpl) - { - CallJabberImpl callJabberImpl = (CallJabberImpl) call; - MediaAwareCallConference conference - = callJabberImpl.getConference(); - - if ((conference != null) - && conference.isJitsiVideobridge()) - { - /* - * TODO We may want to disallow rogue CallJabberImpl - * instances which may throw an exception to prevent - * the conferenceIQ from reaching the CallJabberImpl - * instance which it was meant for. - */ - if (callJabberImpl.processColibriConferenceIQ( - conferenceIQ)) - break; - } - } - } - } - } - } - - /** - * Implements {@link PacketListener}. Notifies this instance that a specific - * {@link Packet} (which this instance has already expressed interest into - * by returning true from {@link #accept(Packet)}) has been - * received. - * - * @param packet the Packet which has been received and which this - * instance is given a chance to process - */ - public void processPacket(Packet packet) - { - /* - * As we do elsewhere, acknowledge the receipt of the Packet first and - * then go about our business with it. - */ - IQ iq = (IQ) packet; - - if (iq.getType() == IQ.Type.SET) - protocolProvider.getConnection().sendPacket(IQ.createResultIQ(iq)); - - /* - * Now that the acknowledging is out of the way, do go about our - * business with the Packet. - */ - ColibriConferenceIQ conferenceIQ = (ColibriConferenceIQ) iq; - boolean interrupted = false; - - try - { - processColibriConferenceIQ(conferenceIQ); - } - catch (Throwable t) - { - logger.error( - "An error occurred during the processing of a " - + packet.getClass().getName() + " packet", - t); - - if (t instanceof InterruptedException) - { - /* - * We cleared the interrupted state of the current Thread by - * catching the InterruptedException. However, we do not really - * care whether the current Thread has been interrupted - we - * caught the InterruptedException because we want to swallow - * any Throwable. Consequently, we should better restore the - * interrupted state. - */ - interrupted = true; - } - else if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - } - if (interrupted) - Thread.currentThread().interrupt(); - } - - /** - * {@inheritDoc} - * - * Implements {@link RegistrationStateChangeListener}. Notifies this - * instance that there has been a change in the RegistrationState - * of {@link #protocolProvider}. Subscribes this instance to - * {@link ColibriConferenceIQ}s as soon as protocolProvider is - * registered and unsubscribes it as soon as protocolProvider is - * unregistered. - */ - public void registrationStateChanged(RegistrationStateChangeEvent ev) - { - RegistrationState registrationState = ev.getNewState(); - - if (RegistrationState.REGISTERED.equals(registrationState)) - { - protocolProvider.getConnection().addPacketListener(this, this); - } - else if (RegistrationState.UNREGISTERED.equals(registrationState)) - { - XMPPConnection connection = protocolProvider.getConnection(); - - if (connection != null) - connection.removePacketListener(this); - } - } -} +package net.java.sip.communicator.impl.protocol.jabber; + +import java.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.media.*; +import net.java.sip.communicator.util.*; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; + +/** + * Implements OperationSetVideoBridge for Jabber. + * + * @author Yana Stamcheva + * @author Lyubomir Marinov + */ +public class OperationSetVideoBridgeImpl + implements OperationSetVideoBridge, + PacketFilter, + PacketListener, + RegistrationStateChangeListener +{ + /** + * The Logger used by the OperationSetVideoBridgeImpl + * class and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(OperationSetVideoBridgeImpl.class); + + /** + * The ProtocolProviderService implementation which initialized + * this instance, owns it and is often referred to as its parent. + */ + private final ProtocolProviderServiceJabberImpl protocolProvider; + + /** + * Creates an instance of OperationSetVideoBridgeImpl by + * specifying the parent ProtocolProviderService announcing this + * operation set. + * + * @param protocolProvider the parent Jabber protocol provider + */ + public OperationSetVideoBridgeImpl( + ProtocolProviderServiceJabberImpl protocolProvider) + { + this.protocolProvider = protocolProvider; + this.protocolProvider.addRegistrationStateChangeListener(this); + } + + /** + * Implements {@link PacketFilter}. Determines whether this instance is + * interested in a specific {@link Packet}. + * OperationSetVideoBridgeImpl returns true if the + * specified packet is a {@link ColibriConferenceIQ}; otherwise, + * false. + * + * @param packet the Packet to be determined whether this instance + * is interested in it + * @return true if the specified packet is a + * ColibriConferenceIQ; otherwise, false + */ + public boolean accept(Packet packet) + { + return (packet instanceof ColibriConferenceIQ); + } + + /** + * Creates a conference call with the specified callees as call peers via a + * video bridge provided by the parent Jabber provider. + * + * @param callees the list of addresses that we should call + * @return the newly created conference call containing all CallPeers + * @throws OperationFailedException if establishing the conference call + * fails + * @throws OperationNotSupportedException if the provider does not have any + * conferencing features. + */ + public Call createConfCall(String[] callees) + throws OperationFailedException, + OperationNotSupportedException + { + return + protocolProvider + .getOperationSet(OperationSetTelephonyConferencing.class) + .createConfCall( + callees, + new MediaAwareCallConference(true)); + } + + /** + * Invites the callee represented by the specified uri to an already + * existing call using a video bridge provided by the parent Jabber provider. + * The difference between this method and createConfCall is that + * inviteCalleeToCall allows a user to add new peers to an already + * established conference. + * + * @param uri the callee to invite to an existing conf call. + * @param call the call that we should invite the callee to. + * @return the CallPeer object corresponding to the callee represented by + * the specified uri. + * @throws OperationFailedException if inviting the specified callee to the + * specified call fails + * @throws OperationNotSupportedException if allowing additional callees to + * a pre-established call is not supported. + */ + public CallPeer inviteCalleeToCall(String uri, Call call) + throws OperationFailedException, + OperationNotSupportedException + { + return + protocolProvider + .getOperationSet(OperationSetTelephonyConferencing.class) + .inviteCalleeToCall(uri, call); + } + + /** + * Indicates if there's an active video bridge available at this moment. The + * Jabber provider may announce support for video bridge, but it should not + * be used for calling until it becomes actually active. + * + * @return true to indicate that there's currently an active + * available video bridge, false - otherwise + */ + public boolean isActive() + { + String jitsiVideobridge = protocolProvider.getJitsiVideobridge(); + + return ((jitsiVideobridge != null) && (jitsiVideobridge.length() > 0)); + } + + /** + * Notifies this instance that a specific ColibriConferenceIQ has + * been received. + * + * @param conferenceIQ the ColibriConferenceIQ which has been + * received + */ + private void processColibriConferenceIQ(ColibriConferenceIQ conferenceIQ) + { + /* + * The application is not a Jitsi Videobridge server, it is a client. + * Consequently, the specified ColibriConferenceIQ is sent to it in + * relation to the part of the application's functionality which makes + * requests to a Jitsi Videobridge server i.e. CallJabberImpl. + * + * Additionally, the method processColibriConferenceIQ is presently tasked + * with processing ColibriConferenceIQ requests only. They are SET IQs + * sent by the Jitsi Videobridge server to notify the application about + * updates in the states of (colibri) conferences organized by the + * application. + */ + if (IQ.Type.SET.equals(conferenceIQ.getType()) + && conferenceIQ.getID() != null) + { + OperationSetBasicTelephony basicTelephony + = protocolProvider.getOperationSet( + OperationSetBasicTelephony.class); + + if (basicTelephony != null) + { + Iterator i = basicTelephony.getActiveCalls(); + + while (i.hasNext()) + { + Call call = i.next(); + + if (call instanceof CallJabberImpl) + { + CallJabberImpl callJabberImpl = (CallJabberImpl) call; + MediaAwareCallConference conference + = callJabberImpl.getConference(); + + if ((conference != null) + && conference.isJitsiVideobridge()) + { + /* + * TODO We may want to disallow rogue CallJabberImpl + * instances which may throw an exception to prevent + * the conferenceIQ from reaching the CallJabberImpl + * instance which it was meant for. + */ + if (callJabberImpl.processColibriConferenceIQ( + conferenceIQ)) + break; + } + } + } + } + } + } + + /** + * Implements {@link PacketListener}. Notifies this instance that a specific + * {@link Packet} (which this instance has already expressed interest into + * by returning true from {@link #accept(Packet)}) has been + * received. + * + * @param packet the Packet which has been received and which this + * instance is given a chance to process + */ + public void processPacket(Packet packet) + { + /* + * As we do elsewhere, acknowledge the receipt of the Packet first and + * then go about our business with it. + */ + IQ iq = (IQ) packet; + + if (iq.getType() == IQ.Type.SET) + protocolProvider.getConnection().sendPacket(IQ.createResultIQ(iq)); + + /* + * Now that the acknowledging is out of the way, do go about our + * business with the Packet. + */ + ColibriConferenceIQ conferenceIQ = (ColibriConferenceIQ) iq; + boolean interrupted = false; + + try + { + processColibriConferenceIQ(conferenceIQ); + } + catch (Throwable t) + { + logger.error( + "An error occurred during the processing of a " + + packet.getClass().getName() + " packet", + t); + + if (t instanceof InterruptedException) + { + /* + * We cleared the interrupted state of the current Thread by + * catching the InterruptedException. However, we do not really + * care whether the current Thread has been interrupted - we + * caught the InterruptedException because we want to swallow + * any Throwable. Consequently, we should better restore the + * interrupted state. + */ + interrupted = true; + } + else if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + } + if (interrupted) + Thread.currentThread().interrupt(); + } + + /** + * {@inheritDoc} + * + * Implements {@link RegistrationStateChangeListener}. Notifies this + * instance that there has been a change in the RegistrationState + * of {@link #protocolProvider}. Subscribes this instance to + * {@link ColibriConferenceIQ}s as soon as protocolProvider is + * registered and unsubscribes it as soon as protocolProvider is + * unregistered. + */ + public void registrationStateChanged(RegistrationStateChangeEvent ev) + { + RegistrationState registrationState = ev.getNewState(); + + if (RegistrationState.REGISTERED.equals(registrationState)) + { + protocolProvider.getConnection().addPacketListener(this, this); + } + else if (RegistrationState.UNREGISTERED.equals(registrationState)) + { + XMPPConnection connection = protocolProvider.getConnection(); + + if (connection != null) + connection.removePacketListener(this); + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java index 0aa4fb6..4bd49a9 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/RawUdpTransportManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,529 +15,529 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber; - -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; -import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; -import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; -import net.java.sip.communicator.service.protocol.*; - -import org.jitsi.service.neomedia.*; -import org.jivesoftware.smack.packet.*; - -/** - * A {@link TransportManagerJabberImpl} implementation that would only gather a - * single candidate pair (i.e. RTP and RTCP). - * - * @author Emil Ivov - * @author Lyubomir Marinov - * @author Hristo Terezov - */ -public class RawUdpTransportManager - extends TransportManagerJabberImpl -{ - /** - * The list of ContentPacketExtensions which represents the local - * counterpart of the negotiation between the local and the remote peers. - */ - private List local; - - /** - * The collection of ContentPacketExtensions which represents the - * remote counterpart of the negotiation between the local and the remote - * peers. - */ - private final List> remotes - = new LinkedList>(); - - /** - * Creates a new instance of this transport manager, binding it to the - * specified peer. - * - * @param callPeer the {@link CallPeer} whose traffic we will be taking - * care of. - */ - public RawUdpTransportManager(CallPeerJabberImpl callPeer) - { - super(callPeer); - } - - /** - * {@inheritDoc} - */ - protected PacketExtension createTransport(String media) - throws OperationFailedException - { - MediaType mediaType = MediaType.parseString(media); - - return createTransport(mediaType, getStreamConnector(mediaType)); - } - - /** - * Creates a raw UDP transport element according to a specific - * StreamConnector. - * - * @param mediaType the MediaType of the MediaStream which - * uses the specified connector or channel - * @param connector the StreamConnector to be described within the - * transport element - * @return a {@link RawUdpTransportPacketExtension} containing the RTP and - * RTCP candidates of the specified connector - */ - private RawUdpTransportPacketExtension createTransport( - MediaType mediaType, - StreamConnector connector) - { - RawUdpTransportPacketExtension ourTransport - = new RawUdpTransportPacketExtension(); - int generation = getCurrentGeneration(); - - // create and add candidates that correspond to the stream connector - // RTP - CandidatePacketExtension rtpCand = new CandidatePacketExtension(); - - rtpCand.setComponent(CandidatePacketExtension.RTP_COMPONENT_ID); - rtpCand.setGeneration(generation); - rtpCand.setID(getNextID()); - rtpCand.setType(CandidateType.host); - - DatagramSocket dataSocket = connector.getDataSocket(); - - rtpCand.setIP(dataSocket.getLocalAddress().getHostAddress()); - rtpCand.setPort(dataSocket.getLocalPort()); - - ourTransport.addCandidate(rtpCand); - - // RTCP - CandidatePacketExtension rtcpCand = new CandidatePacketExtension(); - - rtcpCand.setComponent(CandidatePacketExtension.RTCP_COMPONENT_ID); - rtcpCand.setGeneration(generation); - rtcpCand.setID(getNextID()); - rtcpCand.setType(CandidateType.host); - - DatagramSocket controlSocket = connector.getControlSocket(); - - rtcpCand.setIP(controlSocket.getLocalAddress().getHostAddress()); - rtcpCand.setPort(controlSocket.getLocalPort()); - - ourTransport.addCandidate(rtcpCand); - - return ourTransport; - } - - /** - * {@inheritDoc} - */ - protected PacketExtension createTransportPacketExtension() - { - return new RawUdpTransportPacketExtension(); - } - - /** - * Implements {@link TransportManagerJabberImpl#getStreamTarget(MediaType)}. - * Gets the MediaStreamTarget to be used as the target of - * the MediaStream with a specific MediaType. - * - * @param mediaType the MediaType of the MediaStream which - * is to have its target set to the returned - * MediaStreamTarget - * @return the MediaStreamTarget to be used as the target - * of the MediaStream with the specified MediaType - * @see TransportManagerJabberImpl#getStreamTarget(MediaType) - */ - @Override - public MediaStreamTarget getStreamTarget(MediaType mediaType) - { - ColibriConferenceIQ.Channel channel - = getColibriChannel(mediaType, true /* local */); - MediaStreamTarget streamTarget = null; - - if (channel == null) - { - String media = mediaType.toString(); - - for (Iterable remote : remotes) - { - for (ContentPacketExtension content : remote) - { - RtpDescriptionPacketExtension rtpDescription - = content.getFirstChildOfType( - RtpDescriptionPacketExtension.class); - - if (media.equals(rtpDescription.getMedia())) - { - streamTarget - = JingleUtils.extractDefaultTarget(content); - break; - } - } - } - } - else - { - IceUdpTransportPacketExtension transport = channel.getTransport(); - - if (transport != null) - streamTarget = JingleUtils.extractDefaultTarget(transport); - if (streamTarget == null) - { - /* - * For the purposes of compatibility with legacy Jitsi - * Videobridge, support the channel attributes host, rtpPort and - * rtcpPort. - */ - @SuppressWarnings("deprecation") - String host = channel.getHost(); - - if (host != null) - { - @SuppressWarnings("deprecation") - int rtpPort = channel.getRTPPort(); - @SuppressWarnings("deprecation") - int rtcpPort = channel.getRTCPPort(); - - streamTarget - = new MediaStreamTarget( - new InetSocketAddress(host, rtpPort), - new InetSocketAddress(host, rtcpPort)); - } - } - } - return streamTarget; - } - - /** - * Implements {@link TransportManagerJabberImpl#getXmlNamespace()}. Gets the - * XML namespace of the Jingle transport implemented by this - * TransportManagerJabberImpl. - * - * @return the XML namespace of the Jingle transport implemented by this - * TransportManagerJabberImpl - * @see TransportManagerJabberImpl#getXmlNamespace() - */ - @Override - public String getXmlNamespace() - { - return ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0; - } - - /** - * Removes a content with a specific name from the transport-related part of - * the session represented by this TransportManagerJabberImpl which - * may have been reported through previous calls to the - * startCandidateHarvest and - * startConnectivityEstablishment methods. - * - * @param name the name of the content to be removed from the - * transport-related part of the session represented by this - * TransportManagerJabberImpl - * @see TransportManagerJabberImpl#removeContent(String) - */ - @Override - public void removeContent(String name) - { - if (local != null) - removeContent(local, name); - - removeRemoteContent(name); - } - - /** - * Removes a content with a specific name from the remote counterpart of the - * negotiation between the local and the remote peers. - * - * @param name the name of the content to be removed from the remote - * counterpart of the negotiation between the local and the remote peers - */ - private void removeRemoteContent(String name) - { - for (Iterator> remoteIter - = remotes.iterator(); - remoteIter.hasNext();) - { - Iterable remote = remoteIter.next(); - - /* - * Once the remote content is removed, make sure that we are not - * retaining sets which do not have any contents. - */ - if ((removeContent(remote, name) != null) - && !remote.iterator().hasNext()) - { - remoteIter.remove(); - } - } - } - - /** - * {@inheritDoc} - */ - protected PacketExtension startCandidateHarvest( - ContentPacketExtension theirContent, - ContentPacketExtension ourContent, - TransportInfoSender transportInfoSender, - String media) - throws OperationFailedException - { - return createTransportForStartCandidateHarvest(media); - } - - /** - * Starts transport candidate harvest. This method should complete rapidly - * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests - * are necessary, they should be executed in a separate thread. Candidate - * harvest would then need to be concluded in the - * {@link #wrapupCandidateHarvest()} method which would be called once we - * absolutely need the candidates. - * - * @param theirOffer a media description offer that we've received from the - * remote party and that we should use in case we need to know what - * transports our peer is using. - * @param ourAnswer the content descriptions that we should be adding our - * transport lists to (although not necessarily in this very instance). - * @param transportInfoSender the TransportInfoSender to be used by - * this TransportManagerJabberImpl to send transport-info - * JingleIQs from the local peer to the remote peer if this - * TransportManagerJabberImpl wishes to utilize - * transport-info. Local candidate addresses sent by this - * TransportManagerJabberImpl in transport-info are - * expected to not be included in the result of - * {@link #wrapupCandidateHarvest()}. - * - * @throws OperationFailedException if we fail to allocate a port number. - * @see TransportManagerJabberImpl#startCandidateHarvest(List, List, - * TransportInfoSender) - */ - @Override - public void startCandidateHarvest( - List theirOffer, - List ourAnswer, - TransportInfoSender transportInfoSender) - throws OperationFailedException - { - this.local = ourAnswer; - - super.startCandidateHarvest(theirOffer, ourAnswer, transportInfoSender); - } - - /** - * Overrides the super implementation in order to remember the remote - * counterpart of the negotiation between the local and the remote peer for - * subsequent calls to {@link #getStreamTarget(MediaType)}. - * - * @param remote the collection of ContentPacketExtensions which - * represents the remote counterpart of the negotiation between the local - * and the remote peer - * @return true because RawUdpTransportManager does not - * perform connectivity checks - * @see TransportManagerJabberImpl#startConnectivityEstablishment(Iterable) - */ - @Override - public boolean startConnectivityEstablishment( - Iterable remote) - { - if ((remote != null) && !remotes.contains(remote)) - { - /* - * The state of the session in Jingle is maintained by each peer and - * is modified by content-add and content-remove. The remotes field - * of this RawUdpTransportManager represents the state of the - * session with respect to the remote peer. When the remote peer - * tells us about a specific set of contents, make sure that it is - * the only record we will have with respect to the specified set of - * contents. - */ - for (ContentPacketExtension content : remote) - removeRemoteContent(content.getName()); - - remotes.add(remote); - } - - return super.startConnectivityEstablishment(remote); - } - - /** - * Simply returns the list of local candidates that we gathered during the - * harvest. This is a raw UDP transport manager so there's no real wrapping - * up to do. - * - * @return the list of local candidates that we gathered during the harvest - * @see TransportManagerJabberImpl#wrapupCandidateHarvest() - */ - @Override - public List wrapupCandidateHarvest() - { - return local; - } - - /** - * Returns the extended type of the candidate selected if this transport - * manager is using ICE. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return The extended type of the candidate selected if this transport - * manager is using ICE. Otherwise, returns null. - */ - @Override - public String getICECandidateExtendedType(String streamName) - { - return null; - } - - /** - * Returns the current state of ICE processing. - * - * @return the current state of ICE processing. - */ - @Override - public String getICEState() - { - return null; - } - - /** - * Returns the ICE local host address. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local host address if this transport - * manager is using ICE. Otherwise, returns null. - */ - @Override - public InetSocketAddress getICELocalHostAddress(String streamName) - { - return null; - } - - /** - * Returns the ICE remote host address. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote host address if this transport - * manager is using ICE. Otherwise, returns null. - */ - @Override - public InetSocketAddress getICERemoteHostAddress(String streamName) - { - return null; - } - - /** - * Returns the ICE local reflexive address (server or peer reflexive). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local reflexive address. May be null if this transport - * manager is not using ICE or if there is no reflexive address for the - * local candidate used. - */ - @Override - public InetSocketAddress getICELocalReflexiveAddress(String streamName) - { - return null; - } - - /** - * Returns the ICE remote reflexive address (server or peer reflexive). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote reflexive address. May be null if this transport - * manager is not using ICE or if there is no reflexive address for the - * remote candidate used. - */ - @Override - public InetSocketAddress getICERemoteReflexiveAddress(String streamName) - { - return null; - } - - /** - * Returns the ICE local relayed address (server or peer relayed). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local relayed address. May be null if this transport - * manager is not using ICE or if there is no relayed address for the - * local candidate used. - */ - @Override - public InetSocketAddress getICELocalRelayedAddress(String streamName) - { - return null; - } - - /** - * Returns the ICE remote relayed address (server or peer relayed). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote relayed address. May be null if this transport - * manager is not using ICE or if there is no relayed address for the - * remote candidate used. - */ - @Override - public InetSocketAddress getICERemoteRelayedAddress(String streamName) - { - return null; - } - - /** - * Returns the total harvesting time (in ms) for all harvesters. - * - * @return The total harvesting time (in ms) for all the harvesters. 0 if - * the ICE agent is null, or if the agent has nevers harvested. - */ - @Override - public long getTotalHarvestingTime() - { - return 0; - } - - /** - * Returns the harvesting time (in ms) for the harvester given in parameter. - * - * @param harvesterName The class name if the harvester. - * - * @return The harvesting time (in ms) for the harvester given in parameter. - * 0 if this harvester does not exists, if the ICE agent is null, or if the - * agent has never harvested with this harvester. - */ - @Override - public long getHarvestingTime(String harvesterName) - { - return 0; - } - - /** - * Returns the number of harvesting for this agent. - * - * @return The number of harvesting for this agent. - */ - @Override - public int getNbHarvesting() - { - return 0; - } - - /** - * Returns the number of harvesting time for the harvester given in - * parameter. - * - * @param harvesterName The class name if the harvester. - * - * @return The number of harvesting time for the harvester given in - * parameter. - */ - @Override - public int getNbHarvesting(String harvesterName) - { - return 0; - } -} +package net.java.sip.communicator.impl.protocol.jabber; + +import java.net.*; +import java.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; +import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; +import net.java.sip.communicator.service.protocol.*; + +import org.jitsi.service.neomedia.*; +import org.jivesoftware.smack.packet.*; + +/** + * A {@link TransportManagerJabberImpl} implementation that would only gather a + * single candidate pair (i.e. RTP and RTCP). + * + * @author Emil Ivov + * @author Lyubomir Marinov + * @author Hristo Terezov + */ +public class RawUdpTransportManager + extends TransportManagerJabberImpl +{ + /** + * The list of ContentPacketExtensions which represents the local + * counterpart of the negotiation between the local and the remote peers. + */ + private List local; + + /** + * The collection of ContentPacketExtensions which represents the + * remote counterpart of the negotiation between the local and the remote + * peers. + */ + private final List> remotes + = new LinkedList>(); + + /** + * Creates a new instance of this transport manager, binding it to the + * specified peer. + * + * @param callPeer the {@link CallPeer} whose traffic we will be taking + * care of. + */ + public RawUdpTransportManager(CallPeerJabberImpl callPeer) + { + super(callPeer); + } + + /** + * {@inheritDoc} + */ + protected PacketExtension createTransport(String media) + throws OperationFailedException + { + MediaType mediaType = MediaType.parseString(media); + + return createTransport(mediaType, getStreamConnector(mediaType)); + } + + /** + * Creates a raw UDP transport element according to a specific + * StreamConnector. + * + * @param mediaType the MediaType of the MediaStream which + * uses the specified connector or channel + * @param connector the StreamConnector to be described within the + * transport element + * @return a {@link RawUdpTransportPacketExtension} containing the RTP and + * RTCP candidates of the specified connector + */ + private RawUdpTransportPacketExtension createTransport( + MediaType mediaType, + StreamConnector connector) + { + RawUdpTransportPacketExtension ourTransport + = new RawUdpTransportPacketExtension(); + int generation = getCurrentGeneration(); + + // create and add candidates that correspond to the stream connector + // RTP + CandidatePacketExtension rtpCand = new CandidatePacketExtension(); + + rtpCand.setComponent(CandidatePacketExtension.RTP_COMPONENT_ID); + rtpCand.setGeneration(generation); + rtpCand.setID(getNextID()); + rtpCand.setType(CandidateType.host); + + DatagramSocket dataSocket = connector.getDataSocket(); + + rtpCand.setIP(dataSocket.getLocalAddress().getHostAddress()); + rtpCand.setPort(dataSocket.getLocalPort()); + + ourTransport.addCandidate(rtpCand); + + // RTCP + CandidatePacketExtension rtcpCand = new CandidatePacketExtension(); + + rtcpCand.setComponent(CandidatePacketExtension.RTCP_COMPONENT_ID); + rtcpCand.setGeneration(generation); + rtcpCand.setID(getNextID()); + rtcpCand.setType(CandidateType.host); + + DatagramSocket controlSocket = connector.getControlSocket(); + + rtcpCand.setIP(controlSocket.getLocalAddress().getHostAddress()); + rtcpCand.setPort(controlSocket.getLocalPort()); + + ourTransport.addCandidate(rtcpCand); + + return ourTransport; + } + + /** + * {@inheritDoc} + */ + protected PacketExtension createTransportPacketExtension() + { + return new RawUdpTransportPacketExtension(); + } + + /** + * Implements {@link TransportManagerJabberImpl#getStreamTarget(MediaType)}. + * Gets the MediaStreamTarget to be used as the target of + * the MediaStream with a specific MediaType. + * + * @param mediaType the MediaType of the MediaStream which + * is to have its target set to the returned + * MediaStreamTarget + * @return the MediaStreamTarget to be used as the target + * of the MediaStream with the specified MediaType + * @see TransportManagerJabberImpl#getStreamTarget(MediaType) + */ + @Override + public MediaStreamTarget getStreamTarget(MediaType mediaType) + { + ColibriConferenceIQ.Channel channel + = getColibriChannel(mediaType, true /* local */); + MediaStreamTarget streamTarget = null; + + if (channel == null) + { + String media = mediaType.toString(); + + for (Iterable remote : remotes) + { + for (ContentPacketExtension content : remote) + { + RtpDescriptionPacketExtension rtpDescription + = content.getFirstChildOfType( + RtpDescriptionPacketExtension.class); + + if (media.equals(rtpDescription.getMedia())) + { + streamTarget + = JingleUtils.extractDefaultTarget(content); + break; + } + } + } + } + else + { + IceUdpTransportPacketExtension transport = channel.getTransport(); + + if (transport != null) + streamTarget = JingleUtils.extractDefaultTarget(transport); + if (streamTarget == null) + { + /* + * For the purposes of compatibility with legacy Jitsi + * Videobridge, support the channel attributes host, rtpPort and + * rtcpPort. + */ + @SuppressWarnings("deprecation") + String host = channel.getHost(); + + if (host != null) + { + @SuppressWarnings("deprecation") + int rtpPort = channel.getRTPPort(); + @SuppressWarnings("deprecation") + int rtcpPort = channel.getRTCPPort(); + + streamTarget + = new MediaStreamTarget( + new InetSocketAddress(host, rtpPort), + new InetSocketAddress(host, rtcpPort)); + } + } + } + return streamTarget; + } + + /** + * Implements {@link TransportManagerJabberImpl#getXmlNamespace()}. Gets the + * XML namespace of the Jingle transport implemented by this + * TransportManagerJabberImpl. + * + * @return the XML namespace of the Jingle transport implemented by this + * TransportManagerJabberImpl + * @see TransportManagerJabberImpl#getXmlNamespace() + */ + @Override + public String getXmlNamespace() + { + return ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0; + } + + /** + * Removes a content with a specific name from the transport-related part of + * the session represented by this TransportManagerJabberImpl which + * may have been reported through previous calls to the + * startCandidateHarvest and + * startConnectivityEstablishment methods. + * + * @param name the name of the content to be removed from the + * transport-related part of the session represented by this + * TransportManagerJabberImpl + * @see TransportManagerJabberImpl#removeContent(String) + */ + @Override + public void removeContent(String name) + { + if (local != null) + removeContent(local, name); + + removeRemoteContent(name); + } + + /** + * Removes a content with a specific name from the remote counterpart of the + * negotiation between the local and the remote peers. + * + * @param name the name of the content to be removed from the remote + * counterpart of the negotiation between the local and the remote peers + */ + private void removeRemoteContent(String name) + { + for (Iterator> remoteIter + = remotes.iterator(); + remoteIter.hasNext();) + { + Iterable remote = remoteIter.next(); + + /* + * Once the remote content is removed, make sure that we are not + * retaining sets which do not have any contents. + */ + if ((removeContent(remote, name) != null) + && !remote.iterator().hasNext()) + { + remoteIter.remove(); + } + } + } + + /** + * {@inheritDoc} + */ + protected PacketExtension startCandidateHarvest( + ContentPacketExtension theirContent, + ContentPacketExtension ourContent, + TransportInfoSender transportInfoSender, + String media) + throws OperationFailedException + { + return createTransportForStartCandidateHarvest(media); + } + + /** + * Starts transport candidate harvest. This method should complete rapidly + * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests + * are necessary, they should be executed in a separate thread. Candidate + * harvest would then need to be concluded in the + * {@link #wrapupCandidateHarvest()} method which would be called once we + * absolutely need the candidates. + * + * @param theirOffer a media description offer that we've received from the + * remote party and that we should use in case we need to know what + * transports our peer is using. + * @param ourAnswer the content descriptions that we should be adding our + * transport lists to (although not necessarily in this very instance). + * @param transportInfoSender the TransportInfoSender to be used by + * this TransportManagerJabberImpl to send transport-info + * JingleIQs from the local peer to the remote peer if this + * TransportManagerJabberImpl wishes to utilize + * transport-info. Local candidate addresses sent by this + * TransportManagerJabberImpl in transport-info are + * expected to not be included in the result of + * {@link #wrapupCandidateHarvest()}. + * + * @throws OperationFailedException if we fail to allocate a port number. + * @see TransportManagerJabberImpl#startCandidateHarvest(List, List, + * TransportInfoSender) + */ + @Override + public void startCandidateHarvest( + List theirOffer, + List ourAnswer, + TransportInfoSender transportInfoSender) + throws OperationFailedException + { + this.local = ourAnswer; + + super.startCandidateHarvest(theirOffer, ourAnswer, transportInfoSender); + } + + /** + * Overrides the super implementation in order to remember the remote + * counterpart of the negotiation between the local and the remote peer for + * subsequent calls to {@link #getStreamTarget(MediaType)}. + * + * @param remote the collection of ContentPacketExtensions which + * represents the remote counterpart of the negotiation between the local + * and the remote peer + * @return true because RawUdpTransportManager does not + * perform connectivity checks + * @see TransportManagerJabberImpl#startConnectivityEstablishment(Iterable) + */ + @Override + public boolean startConnectivityEstablishment( + Iterable remote) + { + if ((remote != null) && !remotes.contains(remote)) + { + /* + * The state of the session in Jingle is maintained by each peer and + * is modified by content-add and content-remove. The remotes field + * of this RawUdpTransportManager represents the state of the + * session with respect to the remote peer. When the remote peer + * tells us about a specific set of contents, make sure that it is + * the only record we will have with respect to the specified set of + * contents. + */ + for (ContentPacketExtension content : remote) + removeRemoteContent(content.getName()); + + remotes.add(remote); + } + + return super.startConnectivityEstablishment(remote); + } + + /** + * Simply returns the list of local candidates that we gathered during the + * harvest. This is a raw UDP transport manager so there's no real wrapping + * up to do. + * + * @return the list of local candidates that we gathered during the harvest + * @see TransportManagerJabberImpl#wrapupCandidateHarvest() + */ + @Override + public List wrapupCandidateHarvest() + { + return local; + } + + /** + * Returns the extended type of the candidate selected if this transport + * manager is using ICE. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return The extended type of the candidate selected if this transport + * manager is using ICE. Otherwise, returns null. + */ + @Override + public String getICECandidateExtendedType(String streamName) + { + return null; + } + + /** + * Returns the current state of ICE processing. + * + * @return the current state of ICE processing. + */ + @Override + public String getICEState() + { + return null; + } + + /** + * Returns the ICE local host address. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local host address if this transport + * manager is using ICE. Otherwise, returns null. + */ + @Override + public InetSocketAddress getICELocalHostAddress(String streamName) + { + return null; + } + + /** + * Returns the ICE remote host address. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote host address if this transport + * manager is using ICE. Otherwise, returns null. + */ + @Override + public InetSocketAddress getICERemoteHostAddress(String streamName) + { + return null; + } + + /** + * Returns the ICE local reflexive address (server or peer reflexive). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local reflexive address. May be null if this transport + * manager is not using ICE or if there is no reflexive address for the + * local candidate used. + */ + @Override + public InetSocketAddress getICELocalReflexiveAddress(String streamName) + { + return null; + } + + /** + * Returns the ICE remote reflexive address (server or peer reflexive). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote reflexive address. May be null if this transport + * manager is not using ICE or if there is no reflexive address for the + * remote candidate used. + */ + @Override + public InetSocketAddress getICERemoteReflexiveAddress(String streamName) + { + return null; + } + + /** + * Returns the ICE local relayed address (server or peer relayed). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local relayed address. May be null if this transport + * manager is not using ICE or if there is no relayed address for the + * local candidate used. + */ + @Override + public InetSocketAddress getICELocalRelayedAddress(String streamName) + { + return null; + } + + /** + * Returns the ICE remote relayed address (server or peer relayed). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote relayed address. May be null if this transport + * manager is not using ICE or if there is no relayed address for the + * remote candidate used. + */ + @Override + public InetSocketAddress getICERemoteRelayedAddress(String streamName) + { + return null; + } + + /** + * Returns the total harvesting time (in ms) for all harvesters. + * + * @return The total harvesting time (in ms) for all the harvesters. 0 if + * the ICE agent is null, or if the agent has nevers harvested. + */ + @Override + public long getTotalHarvestingTime() + { + return 0; + } + + /** + * Returns the harvesting time (in ms) for the harvester given in parameter. + * + * @param harvesterName The class name if the harvester. + * + * @return The harvesting time (in ms) for the harvester given in parameter. + * 0 if this harvester does not exists, if the ICE agent is null, or if the + * agent has never harvested with this harvester. + */ + @Override + public long getHarvestingTime(String harvesterName) + { + return 0; + } + + /** + * Returns the number of harvesting for this agent. + * + * @return The number of harvesting for this agent. + */ + @Override + public int getNbHarvesting() + { + return 0; + } + + /** + * Returns the number of harvesting time for the harvester given in + * parameter. + * + * @param harvesterName The class name if the harvester. + * + * @return The number of harvesting time for the harvester given in + * parameter. + */ + @Override + public int getNbHarvesting(String harvesterName) + { + return 0; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerJabberImpl.java index f7f47c6..41e8c05 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/TransportManagerJabberImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,963 +15,963 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber; - -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; -import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; -import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.media.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.neomedia.*; -import org.jivesoftware.smack.packet.*; - -/** - * TransportManagers gather local candidates for incoming and outgoing - * calls. Their work starts by calling a start method which, using the remote - * peer's session description, would start the harvest. Calling a second wrapup - * method would deliver the candidate harvest, possibly after blocking if it has - * not yet completed. - * - * @author Emil Ivov - * @author Lyubomir Marinov - */ -public abstract class TransportManagerJabberImpl - extends TransportManager -{ - /** - * The Logger used by the TransportManagerJabberImpl class - * and its instances to print debug messages. - */ - private static final Logger logger - = Logger.getLogger(TransportManagerJabberImpl.class); - - /** - * The ID that we will be assigning to our next candidate. We use - * ints for interoperability reasons (Emil: I believe that GTalk - * uses ints. If that turns out not to be the case we can stop - * using ints here if that's an issue). - */ - private static int nextID = 1; - - /** - * The information pertaining to the Jisti Videobridge conference which the - * local peer represented by this instance is a focus of. It gives a view of - * the whole Jitsi Videobridge conference managed by the associated - * CallJabberImpl which provides information specific to this - * TransportManager only. - */ - private ColibriConferenceIQ colibri; - - /** - * The generation of the candidates we are currently generating - */ - private int currentGeneration = 0; - - /** - * The indicator which determines whether this TransportManager - * instance is responsible to establish the connectivity with the associated - * Jitsi Videobridge (in case it is being employed at all). - */ - boolean isEstablishingConnectivityWithJitsiVideobridge = false; - - /** - * The indicator which determines whether this TransportManager - * instance is yet to start establishing the connectivity with the - * associated Jitsi Videobridge (in case it is being employed at all). - */ - boolean startConnectivityEstablishmentWithJitsiVideobridge = false; - - /** - * Creates a new instance of this transport manager, binding it to the - * specified peer. - * - * @param callPeer the {@link CallPeer} whose traffic we will be taking - * care of. - */ - protected TransportManagerJabberImpl(CallPeerJabberImpl callPeer) - { - super(callPeer); - } - - /** - * Returns the InetAddress that is most likely to be to be used - * as a next hop when contacting the specified destination. This is - * an utility method that is used whenever we have to choose one of our - * local addresses to put in the Via, Contact or (in the case of no - * registrar accounts) From headers. - * - * @param peer the CallPeer that we would contact. - * - * @return the InetAddress that is most likely to be to be used - * as a next hop when contacting the specified destination. - * - * @throws IllegalArgumentException if destination is not a valid - * host/IP/FQDN - */ - @Override - protected InetAddress getIntendedDestination(CallPeerJabberImpl peer) - { - return peer.getProtocolProvider().getNextHop(); - } - - /** - * Returns the ID that we will be assigning to the next candidate we create. - * - * @return the next ID to use with a candidate. - */ - protected String getNextID() - { - int nextID; - - synchronized (TransportManagerJabberImpl.class) - { - nextID = TransportManagerJabberImpl.nextID++; - } - return Integer.toString(nextID); - } - - /** - * Gets the MediaStreamTarget to be used as the target of - * the MediaStream with a specific MediaType. - * - * @param mediaType the MediaType of the MediaStream which - * is to have its target set to the returned - * MediaStreamTarget - * @return the MediaStreamTarget to be used as the target - * of the MediaStream with the specified MediaType - */ - public abstract MediaStreamTarget getStreamTarget(MediaType mediaType); - - /** - * Gets the XML namespace of the Jingle transport implemented by this - * TransportManagerJabberImpl. - * - * @return the XML namespace of the Jingle transport implemented by this - * TransportManagerJabberImpl - */ - public abstract String getXmlNamespace(); - - /** - * Returns the generation that our current candidates belong to. - * - * @return the generation that we should assign to candidates that we are - * currently advertising. - */ - protected int getCurrentGeneration() - { - return currentGeneration; - } - - /** - * Increments the generation that we are assigning candidates. - */ - protected void incrementGeneration() - { - currentGeneration++; - } - - /** - * Sends transport-related information received from the remote peer to the - * associated Jiitsi Videobridge in order to update the (remote) - * ColibriConferenceIQ.Channel associated with this - * TransportManager instance. - * - * @param map a Map of media-IceUdpTransportPacketExtension pairs - * which represents the transport-related information which has been - * received from the remote peer and which is to be sent to the associated - * Jitsi Videobridge - */ - protected void sendTransportInfoToJitsiVideobridge( - Map map) - { - CallPeerJabberImpl peer = getCallPeer(); - boolean initiator = !peer.isInitiator(); - ColibriConferenceIQ conferenceRequest = null; - - for (Map.Entry e - : map.entrySet()) - { - String media = e.getKey(); - MediaType mediaType = MediaType.parseString(media); - ColibriConferenceIQ.Channel channel - = getColibriChannel(mediaType, false /* remote */); - - if (channel != null) - { - IceUdpTransportPacketExtension transport; - - try - { - transport = cloneTransportAndCandidates(e.getValue()); - } - catch (OperationFailedException ofe) - { - transport = null; - } - if (transport == null) - continue; - - ColibriConferenceIQ.Channel channelRequest - = new ColibriConferenceIQ.Channel(); - - channelRequest.setID(channel.getID()); - channelRequest.setInitiator(initiator); - channelRequest.setTransport(transport); - - if (conferenceRequest == null) - { - if (colibri == null) - break; - else - { - String id = colibri.getID(); - - if ((id == null) || (id.length() == 0)) - break; - else - { - conferenceRequest = new ColibriConferenceIQ(); - conferenceRequest.setID(id); - conferenceRequest.setTo(colibri.getFrom()); - conferenceRequest.setType(IQ.Type.SET); - } - } - } - conferenceRequest.getOrCreateContent(media).addChannel( - channelRequest); - } - } - if (conferenceRequest != null) - { - peer.getProtocolProvider().getConnection().sendPacket( - conferenceRequest); - } - } - - /** - * Starts transport candidate harvest for a specific - * ContentPacketExtension that we are going to offer or answer - * with. - * - * @param theirContent the ContentPacketExtension offered by the - * remote peer to which we are going to answer with ourContent or - * null if ourContent will be an offer to the remote peer - * @param ourContent the ContentPacketExtension for which transport - * candidate harvest is to be started - * @param transportInfoSender a TransportInfoSender if the - * harvested transport candidates are to be sent in a - * transport-info rather than in ourContent; otherwise, - * null - * @param media the media of the RtpDescriptionPacketExtension - * child of ourContent - * @return a PacketExtension to be added as a child to - * ourContent; otherwise, null - * @throws OperationFailedException if anything goes wrong while starting - * transport candidate harvest for the specified ourContent - */ - protected abstract PacketExtension startCandidateHarvest( - ContentPacketExtension theirContent, - ContentPacketExtension ourContent, - TransportInfoSender transportInfoSender, - String media) - throws OperationFailedException; - - /** - * Starts transport candidate harvest. This method should complete rapidly - * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests - * are necessary, they should be executed in a separate thread. Candidate - * harvest would then need to be concluded in the - * {@link #wrapupCandidateHarvest()} method which would be called once we - * absolutely need the candidates. - * - * @param theirOffer a media description offer that we've received from the - * remote party and that we should use in case we need to know what - * transports our peer is using. - * @param ourAnswer the content descriptions that we should be adding our - * transport lists to (although not necessarily in this very instance). - * @param transportInfoSender the TransportInfoSender to be used by - * this TransportManagerJabberImpl to send transport-info - * JingleIQs from the local peer to the remote peer if this - * TransportManagerJabberImpl wishes to utilize - * transport-info. Local candidate addresses sent by this - * TransportManagerJabberImpl in transport-info are - * expected to not be included in the result of - * {@link #wrapupCandidateHarvest()}. - * - * @throws OperationFailedException if we fail to allocate a port number. - */ - public void startCandidateHarvest( - List theirOffer, - List ourAnswer, - TransportInfoSender transportInfoSender) - throws OperationFailedException - { - CallPeerJabberImpl peer = getCallPeer(); - CallJabberImpl call = peer.getCall(); - boolean isJitsiVideobridge = call.getConference().isJitsiVideobridge(); - List cpes - = (theirOffer == null) ? ourAnswer : theirOffer; - - /* - * If Jitsi Videobridge is to be used, determine which channels are to - * be allocated and attempt to allocate them now. - */ - if (isJitsiVideobridge) - { - Map contentMap - = new LinkedHashMap - (); - - for (ContentPacketExtension cpe : cpes) - { - MediaType mediaType = JingleUtils.getMediaType(cpe); - - /* - * The existence of a content for the mediaType and regardless - * of the existence of channels in it signals that a channel - * allocation request has already been sent for that mediaType. - */ - if ((colibri == null) - || (colibri.getContent(mediaType.toString()) == null)) - { - ContentPacketExtension local, remote; - - if (cpes == ourAnswer) - { - local = cpe; - remote - = (theirOffer == null) - ? null - : findContentByName(theirOffer, cpe.getName()); - } - else - { - local = findContentByName(ourAnswer, cpe.getName()); - remote = cpe; - } - contentMap.put(local, remote); - } - } - if (!contentMap.isEmpty()) - { - /* - * We are about to request the channel allocations for the media - * types found in contentMap. Regardless of the response, we do - * not want to repeat these requests. - */ - if (colibri == null) - colibri = new ColibriConferenceIQ(); - for (Map.Entry e - : contentMap.entrySet()) - { - ContentPacketExtension cpe = e.getValue(); - - if (cpe == null) - cpe = e.getKey(); - - colibri.getOrCreateContent( - JingleUtils.getMediaType(cpe).toString()); - } - - ColibriConferenceIQ conferenceResult - = call.createColibriChannels(peer, contentMap); - - if (conferenceResult != null) - { - String videobridgeID = colibri.getID(); - String conferenceResultID = conferenceResult.getID(); - - if (videobridgeID == null) - colibri.setID(conferenceResultID); - else if (!videobridgeID.equals(conferenceResultID)) - throw new IllegalStateException("conference.id"); - - String videobridgeFrom = conferenceResult.getFrom(); - - if ((videobridgeFrom != null) - && (videobridgeFrom.length() != 0)) - { - colibri.setFrom(videobridgeFrom); - } - - for (ColibriConferenceIQ.Content contentResult - : conferenceResult.getContents()) - { - ColibriConferenceIQ.Content content - = colibri.getOrCreateContent( - contentResult.getName()); - - for (ColibriConferenceIQ.Channel channelResult - : contentResult.getChannels()) - { - if (content.getChannel(channelResult.getID()) - == null) - { - content.addChannel(channelResult); - } - } - } - } - else - { - /* - * The call fails if the createColibriChannels method fails - * which may happen if the conference packet times out or it - * can't be built. - */ - ProtocolProviderServiceJabberImpl - .throwOperationFailedException( - "Failed to allocate colibri channel.", - OperationFailedException.GENERAL_ERROR, - null, - logger); - } - } - } - - for (ContentPacketExtension cpe : cpes) - { - String contentName = cpe.getName(); - ContentPacketExtension ourContent - = findContentByName(ourAnswer, contentName); - - //it might be that we decided not to reply to this content - if (ourContent != null) - { - ContentPacketExtension theirContent - = (theirOffer == null) - ? null - : findContentByName(theirOffer, contentName); - RtpDescriptionPacketExtension rtpDesc - = ourContent.getFirstChildOfType( - RtpDescriptionPacketExtension.class); - String media = rtpDesc.getMedia(); - PacketExtension pe - = startCandidateHarvest( - theirContent, - ourContent, - transportInfoSender, - media); - - if (pe != null) - ourContent.addChildExtension(pe); - } - } - } - - /** - * Starts transport candidate harvest. This method should complete rapidly - * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests - * are necessary, they should be executed in a separate thread. Candidate - * harvest would then need to be concluded in the - * {@link #wrapupCandidateHarvest()} method which would be called once we - * absolutely need the candidates. - * - * @param ourOffer the content descriptions that we should be adding our - * transport lists to (although not necessarily in this very instance). - * @param transportInfoSender the TransportInfoSender to be used by - * this TransportManagerJabberImpl to send transport-info - * JingleIQs from the local peer to the remote peer if this - * TransportManagerJabberImpl wishes to utilize - * transport-info. Local candidate addresses sent by this - * TransportManagerJabberImpl in transport-info are - * expected to not be included in the result of - * {@link #wrapupCandidateHarvest()}. - * @throws OperationFailedException if we fail to allocate a port number. - */ - public void startCandidateHarvest( - List ourOffer, - TransportInfoSender transportInfoSender) - throws OperationFailedException - { - startCandidateHarvest( - /* theirOffer */ null, - ourOffer, - transportInfoSender); - } - - /** - * Notifies the transport manager that it should conclude candidate - * harvesting as soon as possible and return the lists of candidates - * gathered so far. - * - * @return the content list that we received earlier (possibly cloned into - * a new instance) and that we have updated with transport lists. - */ - public abstract List wrapupCandidateHarvest(); - - /** - * Looks through the cpExtList and returns the {@link - * ContentPacketExtension} with the specified name. - * - * @param cpExtList the list that we will be searching for a specific - * content. - * @param name the name of the content element we are looking for. - * @return the {@link ContentPacketExtension} with the specified name or - * null if no such content element exists. - */ - public static ContentPacketExtension findContentByName( - Iterable cpExtList, - String name) - { - for(ContentPacketExtension cpExt : cpExtList) - { - if(cpExt.getName().equals(name)) - return cpExt; - } - return null; - } - - /** - * Starts the connectivity establishment of this - * TransportManagerJabberImpl i.e. checks the connectivity between - * the local and the remote peers given the remote counterpart of the - * negotiation between them. - * - * @param remote the collection of ContentPacketExtensions which - * represents the remote counterpart of the negotiation between the local - * and the remote peer - * @return true if connectivity establishment has been started in - * response to the call; otherwise, false. - * TransportManagerJabberImpl implementations which do not perform - * connectivity checks (e.g. raw UDP) should return true. The - * default implementation does not perform connectivity checks and always - * returns true. - */ - public boolean startConnectivityEstablishment( - Iterable remote) - { - return true; - } - - /** - * Starts the connectivity establishment of this - * TransportManagerJabberImpl i.e. checks the connectivity between - * the local and the remote peers given the remote counterpart of the - * negotiation between them. - * - * @param remote a Map of - * media-IceUdpTransportPacketExtension pairs which represents the - * remote counterpart of the negotiation between the local and the remote - * peers - * @return true if connectivity establishment has been started in - * response to the call; otherwise, false. - * TransportManagerJabberImpl implementations which do not perform - * connectivity checks (e.g. raw UDP) should return true. The - * default implementation does not perform connectivity checks and always - * returns true. - */ - protected boolean startConnectivityEstablishment( - Map remote) - { - return true; - } - - /** - * Notifies this TransportManagerJabberImpl that it should conclude - * any started connectivity establishment. - * - * @throws OperationFailedException if anything goes wrong with connectivity - * establishment (i.e. ICE failed, ...) - */ - public void wrapupConnectivityEstablishment() - throws OperationFailedException - { - } - - /** - * Removes a content with a specific name from the transport-related part of - * the session represented by this TransportManagerJabberImpl which - * may have been reported through previous calls to the - * startCandidateHarvest and - * startConnectivityEstablishment methods. - *

    - * Note: Because TransportManager deals with - * MediaTypes, not content names and - * TransportManagerJabberImpl does not implement translating from - * content name to MediaType, implementers are expected to call - * {@link TransportManager#closeStreamConnector(MediaType)}. - *

    - * - * @param name the name of the content to be removed from the - * transport-related part of the session represented by this - * TransportManagerJabberImpl - */ - public abstract void removeContent(String name); - - /** - * Removes a content with a specific name from a specific collection of - * contents and closes any associated StreamConnector. - * - * @param contents the collection of contents to remove the content with the - * specified name from - * @param name the name of the content to remove - * @return the removed ContentPacketExtension if any; otherwise, - * null - */ - protected ContentPacketExtension removeContent( - Iterable contents, - String name) - { - for (Iterator contentIter = contents.iterator(); - contentIter.hasNext();) - { - ContentPacketExtension content = contentIter.next(); - - if (name.equals(content.getName())) - { - contentIter.remove(); - - // closeStreamConnector - MediaType mediaType = JingleUtils.getMediaType(content); - if (mediaType != null) - { - closeStreamConnector(mediaType); - } - - return content; - } - } - return null; - } - - /** - * Clones a specific IceUdpTransportPacketExtension and its - * candidates. - * - * @param src the IceUdpTransportPacketExtension to be cloned - * @return a new IceUdpTransportPacketExtension instance which has - * the same run-time type, attributes, namespace, text and candidates as the - * specified src - * @throws OperationFailedException if an error occurs during the cloing of - * the specified src and its candidates - */ - static IceUdpTransportPacketExtension cloneTransportAndCandidates( - IceUdpTransportPacketExtension src) - throws OperationFailedException - { - try - { - return IceUdpTransportPacketExtension - .cloneTransportAndCandidates(src); - } - catch (Exception e) - { - ProtocolProviderServiceJabberImpl - .throwOperationFailedException( - "Failed to close transport and candidates.", - OperationFailedException.GENERAL_ERROR, - e, - logger); - - } - return null; - } - - /** - * Releases the resources acquired by this TransportManager and - * prepares it for garbage collection. - */ - public void close() - { - for (MediaType mediaType : MediaType.values()) - closeStreamConnector(mediaType); - } - - /** - * Closes a specific StreamConnector associated with a specific - * MediaType. If this TransportManager has a reference to - * the specified streamConnector, it remains. - * Also expires the ColibriConferenceIQ.Channel associated with - * the closed StreamConnector. - * - * @param mediaType the MediaType associated with the specified - * streamConnector - * @param streamConnector the StreamConnector to be closed - */ - @Override - protected void closeStreamConnector( - MediaType mediaType, - StreamConnector streamConnector) - { - try - { - boolean superCloseStreamConnector = true; - - if (streamConnector instanceof ColibriStreamConnector) - { - CallPeerJabberImpl peer = getCallPeer(); - - if (peer != null) - { - CallJabberImpl call = peer.getCall(); - - if (call != null) - { - superCloseStreamConnector = false; - call.closeColibriStreamConnector( - peer, - mediaType, - (ColibriStreamConnector) streamConnector); - } - } - } - if (superCloseStreamConnector) - super.closeStreamConnector(mediaType, streamConnector); - } - finally - { - /* - * Expire the ColibriConferenceIQ.Channel associated with the closed - * StreamConnector. - */ - if (colibri != null) - { - ColibriConferenceIQ.Content content - = colibri.getContent(mediaType.toString()); - - if (content != null) - { - List channels - = content.getChannels(); - - if (channels.size() == 2) - { - ColibriConferenceIQ requestConferenceIQ - = new ColibriConferenceIQ(); - - requestConferenceIQ.setID(colibri.getID()); - - ColibriConferenceIQ.Content requestContent - = requestConferenceIQ.getOrCreateContent( - content.getName()); - - requestContent.addChannel(channels.get(1 /* remote */)); - - /* - * Regardless of whether the request to expire the - * Channel associated with mediaType succeeds, consider - * the Channel in question expired. Since - * RawUdpTransportManager allocates a single channel per - * MediaType, consider the whole Content expired. - */ - colibri.removeContent(content); - - CallPeerJabberImpl peer = getCallPeer(); - - if (peer != null) - { - CallJabberImpl call = peer.getCall(); - - if (call != null) - { - call.expireColibriChannels( - peer, - requestConferenceIQ); - } - } - } - } - } - } - } - - /** - * {@inheritDoc} - * - * Adds support for telephony conferences utilizing the Jitsi Videobridge - * server-side technology. - * - * @see #doCreateStreamConnector(MediaType) - */ - @Override - protected StreamConnector createStreamConnector(final MediaType mediaType) - throws OperationFailedException - { - ColibriConferenceIQ.Channel channel - = getColibriChannel(mediaType, true /* local */); - - if (channel != null) - { - CallPeerJabberImpl peer = getCallPeer(); - CallJabberImpl call = peer.getCall(); - StreamConnector streamConnector - = call.createColibriStreamConnector( - peer, - mediaType, - channel, - new StreamConnectorFactory() - { - public StreamConnector createStreamConnector() - { - try - { - return doCreateStreamConnector(mediaType); - } - catch (OperationFailedException ofe) - { - return null; - } - } - }); - - if (streamConnector != null) - return streamConnector; - } - - return doCreateStreamConnector(mediaType); - } - - protected abstract PacketExtension createTransport(String media) - throws OperationFailedException; - - protected PacketExtension createTransportForStartCandidateHarvest( - String media) - throws OperationFailedException - { - PacketExtension pe = null; - - if (getCallPeer().isJitsiVideobridge()) - { - MediaType mediaType = MediaType.parseString(media); - ColibriConferenceIQ.Channel channel - = getColibriChannel(mediaType, false /* remote */); - - if (channel != null) - pe = cloneTransportAndCandidates(channel.getTransport()); - } - else - pe = createTransport(media); - return pe; - } - - /** - * Initializes a new PacketExtension instance appropriate to the - * type of Jingle transport represented by this TransportManager. - * The new instance is not initialized with any attributes or child - * extensions. - * - * @return a new PacketExtension instance appropriate to the type - * of Jingle transport represented by this TransportManager - */ - protected abstract PacketExtension createTransportPacketExtension(); - - /** - * Creates a media StreamConnector for a stream of a specific - * MediaType. The minimum and maximum of the media port boundaries - * are taken into account. - * - * @param mediaType the MediaType of the stream for which a - * StreamConnector is to be created - * @return a StreamConnector for the stream of the specified - * mediaType - * @throws OperationFailedException if the binding of the sockets fails - */ - protected StreamConnector doCreateStreamConnector(MediaType mediaType) - throws OperationFailedException - { - return super.createStreamConnector(mediaType); - } - - /** - * Finds a TransportManagerJabberImpl participating in a telephony - * conference utilizing the Jitsi Videobridge server-side technology that - * this instance is participating in which is establishing the connectivity - * with the Jitsi Videobridge server (as opposed to a CallPeer). - * - * @return a TransportManagerJabberImpl which is participating in - * a telephony conference utilizing the Jitsi Videobridge server-side - * technology that this instance is participating in which is establishing - * the connectivity with the Jitsi Videobridge server (as opposed to a - * CallPeer). - */ - TransportManagerJabberImpl - findTransportManagerEstablishingConnectivityWithJitsiVideobridge() - { - Call call = getCallPeer().getCall(); - TransportManagerJabberImpl transportManager = null; - - if (call != null) - { - CallConference conference = call.getConference(); - - if ((conference != null) && conference.isJitsiVideobridge()) - { - for (Call aCall : conference.getCalls()) - { - Iterator callPeerIter - = aCall.getCallPeers(); - - while (callPeerIter.hasNext()) - { - CallPeer aCallPeer = callPeerIter.next(); - - if (aCallPeer instanceof CallPeerJabberImpl) - { - TransportManagerJabberImpl aTransportManager - = ((CallPeerJabberImpl) aCallPeer) - .getMediaHandler() - .getTransportManager(); - - if (aTransportManager - .isEstablishingConnectivityWithJitsiVideobridge) - { - transportManager = aTransportManager; - break; - } - } - } - } - } - } - return transportManager; - } - - /** - * Gets the {@link ColibriConferenceIQ.Channel} which belongs to a content - * associated with a specific MediaType and is to be either locally - * or remotely used. - *

    - * Note: Modifications to the ColibriConferenceIQ.Channel - * instance returned by the method propagate to (the state of) this - * instance. - *

    - * - * @param mediaType the MediaType associated with the content which - * contains the ColibriConferenceIQ.Channel to get - * @param local true if the ColibriConferenceIQ.Channel - * which is to be used locally is to be returned or false for the - * one which is to be used remotely - * @return the ColibriConferenceIQ.Channel which belongs to a - * content associated with the specified mediaType and which is to - * be used in accord with the specified local indicator if such a - * channel exists; otherwise, null - */ - ColibriConferenceIQ.Channel getColibriChannel( - MediaType mediaType, - boolean local) - { - ColibriConferenceIQ.Channel channel = null; - - if (colibri != null) - { - ColibriConferenceIQ.Content content - = colibri.getContent(mediaType.toString()); - - if (content != null) - { - List channels - = content.getChannels(); - - if (channels.size() == 2) - channel = channels.get(local ? 0 : 1); - } - } - return channel; - } -} +package net.java.sip.communicator.impl.protocol.jabber; + +import java.net.*; +import java.util.*; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.colibri.*; +import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*; +import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.media.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.neomedia.*; +import org.jivesoftware.smack.packet.*; + +/** + * TransportManagers gather local candidates for incoming and outgoing + * calls. Their work starts by calling a start method which, using the remote + * peer's session description, would start the harvest. Calling a second wrapup + * method would deliver the candidate harvest, possibly after blocking if it has + * not yet completed. + * + * @author Emil Ivov + * @author Lyubomir Marinov + */ +public abstract class TransportManagerJabberImpl + extends TransportManager +{ + /** + * The Logger used by the TransportManagerJabberImpl class + * and its instances to print debug messages. + */ + private static final Logger logger + = Logger.getLogger(TransportManagerJabberImpl.class); + + /** + * The ID that we will be assigning to our next candidate. We use + * ints for interoperability reasons (Emil: I believe that GTalk + * uses ints. If that turns out not to be the case we can stop + * using ints here if that's an issue). + */ + private static int nextID = 1; + + /** + * The information pertaining to the Jisti Videobridge conference which the + * local peer represented by this instance is a focus of. It gives a view of + * the whole Jitsi Videobridge conference managed by the associated + * CallJabberImpl which provides information specific to this + * TransportManager only. + */ + private ColibriConferenceIQ colibri; + + /** + * The generation of the candidates we are currently generating + */ + private int currentGeneration = 0; + + /** + * The indicator which determines whether this TransportManager + * instance is responsible to establish the connectivity with the associated + * Jitsi Videobridge (in case it is being employed at all). + */ + boolean isEstablishingConnectivityWithJitsiVideobridge = false; + + /** + * The indicator which determines whether this TransportManager + * instance is yet to start establishing the connectivity with the + * associated Jitsi Videobridge (in case it is being employed at all). + */ + boolean startConnectivityEstablishmentWithJitsiVideobridge = false; + + /** + * Creates a new instance of this transport manager, binding it to the + * specified peer. + * + * @param callPeer the {@link CallPeer} whose traffic we will be taking + * care of. + */ + protected TransportManagerJabberImpl(CallPeerJabberImpl callPeer) + { + super(callPeer); + } + + /** + * Returns the InetAddress that is most likely to be to be used + * as a next hop when contacting the specified destination. This is + * an utility method that is used whenever we have to choose one of our + * local addresses to put in the Via, Contact or (in the case of no + * registrar accounts) From headers. + * + * @param peer the CallPeer that we would contact. + * + * @return the InetAddress that is most likely to be to be used + * as a next hop when contacting the specified destination. + * + * @throws IllegalArgumentException if destination is not a valid + * host/IP/FQDN + */ + @Override + protected InetAddress getIntendedDestination(CallPeerJabberImpl peer) + { + return peer.getProtocolProvider().getNextHop(); + } + + /** + * Returns the ID that we will be assigning to the next candidate we create. + * + * @return the next ID to use with a candidate. + */ + protected String getNextID() + { + int nextID; + + synchronized (TransportManagerJabberImpl.class) + { + nextID = TransportManagerJabberImpl.nextID++; + } + return Integer.toString(nextID); + } + + /** + * Gets the MediaStreamTarget to be used as the target of + * the MediaStream with a specific MediaType. + * + * @param mediaType the MediaType of the MediaStream which + * is to have its target set to the returned + * MediaStreamTarget + * @return the MediaStreamTarget to be used as the target + * of the MediaStream with the specified MediaType + */ + public abstract MediaStreamTarget getStreamTarget(MediaType mediaType); + + /** + * Gets the XML namespace of the Jingle transport implemented by this + * TransportManagerJabberImpl. + * + * @return the XML namespace of the Jingle transport implemented by this + * TransportManagerJabberImpl + */ + public abstract String getXmlNamespace(); + + /** + * Returns the generation that our current candidates belong to. + * + * @return the generation that we should assign to candidates that we are + * currently advertising. + */ + protected int getCurrentGeneration() + { + return currentGeneration; + } + + /** + * Increments the generation that we are assigning candidates. + */ + protected void incrementGeneration() + { + currentGeneration++; + } + + /** + * Sends transport-related information received from the remote peer to the + * associated Jiitsi Videobridge in order to update the (remote) + * ColibriConferenceIQ.Channel associated with this + * TransportManager instance. + * + * @param map a Map of media-IceUdpTransportPacketExtension pairs + * which represents the transport-related information which has been + * received from the remote peer and which is to be sent to the associated + * Jitsi Videobridge + */ + protected void sendTransportInfoToJitsiVideobridge( + Map map) + { + CallPeerJabberImpl peer = getCallPeer(); + boolean initiator = !peer.isInitiator(); + ColibriConferenceIQ conferenceRequest = null; + + for (Map.Entry e + : map.entrySet()) + { + String media = e.getKey(); + MediaType mediaType = MediaType.parseString(media); + ColibriConferenceIQ.Channel channel + = getColibriChannel(mediaType, false /* remote */); + + if (channel != null) + { + IceUdpTransportPacketExtension transport; + + try + { + transport = cloneTransportAndCandidates(e.getValue()); + } + catch (OperationFailedException ofe) + { + transport = null; + } + if (transport == null) + continue; + + ColibriConferenceIQ.Channel channelRequest + = new ColibriConferenceIQ.Channel(); + + channelRequest.setID(channel.getID()); + channelRequest.setInitiator(initiator); + channelRequest.setTransport(transport); + + if (conferenceRequest == null) + { + if (colibri == null) + break; + else + { + String id = colibri.getID(); + + if ((id == null) || (id.length() == 0)) + break; + else + { + conferenceRequest = new ColibriConferenceIQ(); + conferenceRequest.setID(id); + conferenceRequest.setTo(colibri.getFrom()); + conferenceRequest.setType(IQ.Type.SET); + } + } + } + conferenceRequest.getOrCreateContent(media).addChannel( + channelRequest); + } + } + if (conferenceRequest != null) + { + peer.getProtocolProvider().getConnection().sendPacket( + conferenceRequest); + } + } + + /** + * Starts transport candidate harvest for a specific + * ContentPacketExtension that we are going to offer or answer + * with. + * + * @param theirContent the ContentPacketExtension offered by the + * remote peer to which we are going to answer with ourContent or + * null if ourContent will be an offer to the remote peer + * @param ourContent the ContentPacketExtension for which transport + * candidate harvest is to be started + * @param transportInfoSender a TransportInfoSender if the + * harvested transport candidates are to be sent in a + * transport-info rather than in ourContent; otherwise, + * null + * @param media the media of the RtpDescriptionPacketExtension + * child of ourContent + * @return a PacketExtension to be added as a child to + * ourContent; otherwise, null + * @throws OperationFailedException if anything goes wrong while starting + * transport candidate harvest for the specified ourContent + */ + protected abstract PacketExtension startCandidateHarvest( + ContentPacketExtension theirContent, + ContentPacketExtension ourContent, + TransportInfoSender transportInfoSender, + String media) + throws OperationFailedException; + + /** + * Starts transport candidate harvest. This method should complete rapidly + * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests + * are necessary, they should be executed in a separate thread. Candidate + * harvest would then need to be concluded in the + * {@link #wrapupCandidateHarvest()} method which would be called once we + * absolutely need the candidates. + * + * @param theirOffer a media description offer that we've received from the + * remote party and that we should use in case we need to know what + * transports our peer is using. + * @param ourAnswer the content descriptions that we should be adding our + * transport lists to (although not necessarily in this very instance). + * @param transportInfoSender the TransportInfoSender to be used by + * this TransportManagerJabberImpl to send transport-info + * JingleIQs from the local peer to the remote peer if this + * TransportManagerJabberImpl wishes to utilize + * transport-info. Local candidate addresses sent by this + * TransportManagerJabberImpl in transport-info are + * expected to not be included in the result of + * {@link #wrapupCandidateHarvest()}. + * + * @throws OperationFailedException if we fail to allocate a port number. + */ + public void startCandidateHarvest( + List theirOffer, + List ourAnswer, + TransportInfoSender transportInfoSender) + throws OperationFailedException + { + CallPeerJabberImpl peer = getCallPeer(); + CallJabberImpl call = peer.getCall(); + boolean isJitsiVideobridge = call.getConference().isJitsiVideobridge(); + List cpes + = (theirOffer == null) ? ourAnswer : theirOffer; + + /* + * If Jitsi Videobridge is to be used, determine which channels are to + * be allocated and attempt to allocate them now. + */ + if (isJitsiVideobridge) + { + Map contentMap + = new LinkedHashMap + (); + + for (ContentPacketExtension cpe : cpes) + { + MediaType mediaType = JingleUtils.getMediaType(cpe); + + /* + * The existence of a content for the mediaType and regardless + * of the existence of channels in it signals that a channel + * allocation request has already been sent for that mediaType. + */ + if ((colibri == null) + || (colibri.getContent(mediaType.toString()) == null)) + { + ContentPacketExtension local, remote; + + if (cpes == ourAnswer) + { + local = cpe; + remote + = (theirOffer == null) + ? null + : findContentByName(theirOffer, cpe.getName()); + } + else + { + local = findContentByName(ourAnswer, cpe.getName()); + remote = cpe; + } + contentMap.put(local, remote); + } + } + if (!contentMap.isEmpty()) + { + /* + * We are about to request the channel allocations for the media + * types found in contentMap. Regardless of the response, we do + * not want to repeat these requests. + */ + if (colibri == null) + colibri = new ColibriConferenceIQ(); + for (Map.Entry e + : contentMap.entrySet()) + { + ContentPacketExtension cpe = e.getValue(); + + if (cpe == null) + cpe = e.getKey(); + + colibri.getOrCreateContent( + JingleUtils.getMediaType(cpe).toString()); + } + + ColibriConferenceIQ conferenceResult + = call.createColibriChannels(peer, contentMap); + + if (conferenceResult != null) + { + String videobridgeID = colibri.getID(); + String conferenceResultID = conferenceResult.getID(); + + if (videobridgeID == null) + colibri.setID(conferenceResultID); + else if (!videobridgeID.equals(conferenceResultID)) + throw new IllegalStateException("conference.id"); + + String videobridgeFrom = conferenceResult.getFrom(); + + if ((videobridgeFrom != null) + && (videobridgeFrom.length() != 0)) + { + colibri.setFrom(videobridgeFrom); + } + + for (ColibriConferenceIQ.Content contentResult + : conferenceResult.getContents()) + { + ColibriConferenceIQ.Content content + = colibri.getOrCreateContent( + contentResult.getName()); + + for (ColibriConferenceIQ.Channel channelResult + : contentResult.getChannels()) + { + if (content.getChannel(channelResult.getID()) + == null) + { + content.addChannel(channelResult); + } + } + } + } + else + { + /* + * The call fails if the createColibriChannels method fails + * which may happen if the conference packet times out or it + * can't be built. + */ + ProtocolProviderServiceJabberImpl + .throwOperationFailedException( + "Failed to allocate colibri channel.", + OperationFailedException.GENERAL_ERROR, + null, + logger); + } + } + } + + for (ContentPacketExtension cpe : cpes) + { + String contentName = cpe.getName(); + ContentPacketExtension ourContent + = findContentByName(ourAnswer, contentName); + + //it might be that we decided not to reply to this content + if (ourContent != null) + { + ContentPacketExtension theirContent + = (theirOffer == null) + ? null + : findContentByName(theirOffer, contentName); + RtpDescriptionPacketExtension rtpDesc + = ourContent.getFirstChildOfType( + RtpDescriptionPacketExtension.class); + String media = rtpDesc.getMedia(); + PacketExtension pe + = startCandidateHarvest( + theirContent, + ourContent, + transportInfoSender, + media); + + if (pe != null) + ourContent.addChildExtension(pe); + } + } + } + + /** + * Starts transport candidate harvest. This method should complete rapidly + * and, in case of lengthy procedures like STUN/TURN/UPnP candidate harvests + * are necessary, they should be executed in a separate thread. Candidate + * harvest would then need to be concluded in the + * {@link #wrapupCandidateHarvest()} method which would be called once we + * absolutely need the candidates. + * + * @param ourOffer the content descriptions that we should be adding our + * transport lists to (although not necessarily in this very instance). + * @param transportInfoSender the TransportInfoSender to be used by + * this TransportManagerJabberImpl to send transport-info + * JingleIQs from the local peer to the remote peer if this + * TransportManagerJabberImpl wishes to utilize + * transport-info. Local candidate addresses sent by this + * TransportManagerJabberImpl in transport-info are + * expected to not be included in the result of + * {@link #wrapupCandidateHarvest()}. + * @throws OperationFailedException if we fail to allocate a port number. + */ + public void startCandidateHarvest( + List ourOffer, + TransportInfoSender transportInfoSender) + throws OperationFailedException + { + startCandidateHarvest( + /* theirOffer */ null, + ourOffer, + transportInfoSender); + } + + /** + * Notifies the transport manager that it should conclude candidate + * harvesting as soon as possible and return the lists of candidates + * gathered so far. + * + * @return the content list that we received earlier (possibly cloned into + * a new instance) and that we have updated with transport lists. + */ + public abstract List wrapupCandidateHarvest(); + + /** + * Looks through the cpExtList and returns the {@link + * ContentPacketExtension} with the specified name. + * + * @param cpExtList the list that we will be searching for a specific + * content. + * @param name the name of the content element we are looking for. + * @return the {@link ContentPacketExtension} with the specified name or + * null if no such content element exists. + */ + public static ContentPacketExtension findContentByName( + Iterable cpExtList, + String name) + { + for(ContentPacketExtension cpExt : cpExtList) + { + if(cpExt.getName().equals(name)) + return cpExt; + } + return null; + } + + /** + * Starts the connectivity establishment of this + * TransportManagerJabberImpl i.e. checks the connectivity between + * the local and the remote peers given the remote counterpart of the + * negotiation between them. + * + * @param remote the collection of ContentPacketExtensions which + * represents the remote counterpart of the negotiation between the local + * and the remote peer + * @return true if connectivity establishment has been started in + * response to the call; otherwise, false. + * TransportManagerJabberImpl implementations which do not perform + * connectivity checks (e.g. raw UDP) should return true. The + * default implementation does not perform connectivity checks and always + * returns true. + */ + public boolean startConnectivityEstablishment( + Iterable remote) + { + return true; + } + + /** + * Starts the connectivity establishment of this + * TransportManagerJabberImpl i.e. checks the connectivity between + * the local and the remote peers given the remote counterpart of the + * negotiation between them. + * + * @param remote a Map of + * media-IceUdpTransportPacketExtension pairs which represents the + * remote counterpart of the negotiation between the local and the remote + * peers + * @return true if connectivity establishment has been started in + * response to the call; otherwise, false. + * TransportManagerJabberImpl implementations which do not perform + * connectivity checks (e.g. raw UDP) should return true. The + * default implementation does not perform connectivity checks and always + * returns true. + */ + protected boolean startConnectivityEstablishment( + Map remote) + { + return true; + } + + /** + * Notifies this TransportManagerJabberImpl that it should conclude + * any started connectivity establishment. + * + * @throws OperationFailedException if anything goes wrong with connectivity + * establishment (i.e. ICE failed, ...) + */ + public void wrapupConnectivityEstablishment() + throws OperationFailedException + { + } + + /** + * Removes a content with a specific name from the transport-related part of + * the session represented by this TransportManagerJabberImpl which + * may have been reported through previous calls to the + * startCandidateHarvest and + * startConnectivityEstablishment methods. + *

    + * Note: Because TransportManager deals with + * MediaTypes, not content names and + * TransportManagerJabberImpl does not implement translating from + * content name to MediaType, implementers are expected to call + * {@link TransportManager#closeStreamConnector(MediaType)}. + *

    + * + * @param name the name of the content to be removed from the + * transport-related part of the session represented by this + * TransportManagerJabberImpl + */ + public abstract void removeContent(String name); + + /** + * Removes a content with a specific name from a specific collection of + * contents and closes any associated StreamConnector. + * + * @param contents the collection of contents to remove the content with the + * specified name from + * @param name the name of the content to remove + * @return the removed ContentPacketExtension if any; otherwise, + * null + */ + protected ContentPacketExtension removeContent( + Iterable contents, + String name) + { + for (Iterator contentIter = contents.iterator(); + contentIter.hasNext();) + { + ContentPacketExtension content = contentIter.next(); + + if (name.equals(content.getName())) + { + contentIter.remove(); + + // closeStreamConnector + MediaType mediaType = JingleUtils.getMediaType(content); + if (mediaType != null) + { + closeStreamConnector(mediaType); + } + + return content; + } + } + return null; + } + + /** + * Clones a specific IceUdpTransportPacketExtension and its + * candidates. + * + * @param src the IceUdpTransportPacketExtension to be cloned + * @return a new IceUdpTransportPacketExtension instance which has + * the same run-time type, attributes, namespace, text and candidates as the + * specified src + * @throws OperationFailedException if an error occurs during the cloing of + * the specified src and its candidates + */ + static IceUdpTransportPacketExtension cloneTransportAndCandidates( + IceUdpTransportPacketExtension src) + throws OperationFailedException + { + try + { + return IceUdpTransportPacketExtension + .cloneTransportAndCandidates(src); + } + catch (Exception e) + { + ProtocolProviderServiceJabberImpl + .throwOperationFailedException( + "Failed to close transport and candidates.", + OperationFailedException.GENERAL_ERROR, + e, + logger); + + } + return null; + } + + /** + * Releases the resources acquired by this TransportManager and + * prepares it for garbage collection. + */ + public void close() + { + for (MediaType mediaType : MediaType.values()) + closeStreamConnector(mediaType); + } + + /** + * Closes a specific StreamConnector associated with a specific + * MediaType. If this TransportManager has a reference to + * the specified streamConnector, it remains. + * Also expires the ColibriConferenceIQ.Channel associated with + * the closed StreamConnector. + * + * @param mediaType the MediaType associated with the specified + * streamConnector + * @param streamConnector the StreamConnector to be closed + */ + @Override + protected void closeStreamConnector( + MediaType mediaType, + StreamConnector streamConnector) + { + try + { + boolean superCloseStreamConnector = true; + + if (streamConnector instanceof ColibriStreamConnector) + { + CallPeerJabberImpl peer = getCallPeer(); + + if (peer != null) + { + CallJabberImpl call = peer.getCall(); + + if (call != null) + { + superCloseStreamConnector = false; + call.closeColibriStreamConnector( + peer, + mediaType, + (ColibriStreamConnector) streamConnector); + } + } + } + if (superCloseStreamConnector) + super.closeStreamConnector(mediaType, streamConnector); + } + finally + { + /* + * Expire the ColibriConferenceIQ.Channel associated with the closed + * StreamConnector. + */ + if (colibri != null) + { + ColibriConferenceIQ.Content content + = colibri.getContent(mediaType.toString()); + + if (content != null) + { + List channels + = content.getChannels(); + + if (channels.size() == 2) + { + ColibriConferenceIQ requestConferenceIQ + = new ColibriConferenceIQ(); + + requestConferenceIQ.setID(colibri.getID()); + + ColibriConferenceIQ.Content requestContent + = requestConferenceIQ.getOrCreateContent( + content.getName()); + + requestContent.addChannel(channels.get(1 /* remote */)); + + /* + * Regardless of whether the request to expire the + * Channel associated with mediaType succeeds, consider + * the Channel in question expired. Since + * RawUdpTransportManager allocates a single channel per + * MediaType, consider the whole Content expired. + */ + colibri.removeContent(content); + + CallPeerJabberImpl peer = getCallPeer(); + + if (peer != null) + { + CallJabberImpl call = peer.getCall(); + + if (call != null) + { + call.expireColibriChannels( + peer, + requestConferenceIQ); + } + } + } + } + } + } + } + + /** + * {@inheritDoc} + * + * Adds support for telephony conferences utilizing the Jitsi Videobridge + * server-side technology. + * + * @see #doCreateStreamConnector(MediaType) + */ + @Override + protected StreamConnector createStreamConnector(final MediaType mediaType) + throws OperationFailedException + { + ColibriConferenceIQ.Channel channel + = getColibriChannel(mediaType, true /* local */); + + if (channel != null) + { + CallPeerJabberImpl peer = getCallPeer(); + CallJabberImpl call = peer.getCall(); + StreamConnector streamConnector + = call.createColibriStreamConnector( + peer, + mediaType, + channel, + new StreamConnectorFactory() + { + public StreamConnector createStreamConnector() + { + try + { + return doCreateStreamConnector(mediaType); + } + catch (OperationFailedException ofe) + { + return null; + } + } + }); + + if (streamConnector != null) + return streamConnector; + } + + return doCreateStreamConnector(mediaType); + } + + protected abstract PacketExtension createTransport(String media) + throws OperationFailedException; + + protected PacketExtension createTransportForStartCandidateHarvest( + String media) + throws OperationFailedException + { + PacketExtension pe = null; + + if (getCallPeer().isJitsiVideobridge()) + { + MediaType mediaType = MediaType.parseString(media); + ColibriConferenceIQ.Channel channel + = getColibriChannel(mediaType, false /* remote */); + + if (channel != null) + pe = cloneTransportAndCandidates(channel.getTransport()); + } + else + pe = createTransport(media); + return pe; + } + + /** + * Initializes a new PacketExtension instance appropriate to the + * type of Jingle transport represented by this TransportManager. + * The new instance is not initialized with any attributes or child + * extensions. + * + * @return a new PacketExtension instance appropriate to the type + * of Jingle transport represented by this TransportManager + */ + protected abstract PacketExtension createTransportPacketExtension(); + + /** + * Creates a media StreamConnector for a stream of a specific + * MediaType. The minimum and maximum of the media port boundaries + * are taken into account. + * + * @param mediaType the MediaType of the stream for which a + * StreamConnector is to be created + * @return a StreamConnector for the stream of the specified + * mediaType + * @throws OperationFailedException if the binding of the sockets fails + */ + protected StreamConnector doCreateStreamConnector(MediaType mediaType) + throws OperationFailedException + { + return super.createStreamConnector(mediaType); + } + + /** + * Finds a TransportManagerJabberImpl participating in a telephony + * conference utilizing the Jitsi Videobridge server-side technology that + * this instance is participating in which is establishing the connectivity + * with the Jitsi Videobridge server (as opposed to a CallPeer). + * + * @return a TransportManagerJabberImpl which is participating in + * a telephony conference utilizing the Jitsi Videobridge server-side + * technology that this instance is participating in which is establishing + * the connectivity with the Jitsi Videobridge server (as opposed to a + * CallPeer). + */ + TransportManagerJabberImpl + findTransportManagerEstablishingConnectivityWithJitsiVideobridge() + { + Call call = getCallPeer().getCall(); + TransportManagerJabberImpl transportManager = null; + + if (call != null) + { + CallConference conference = call.getConference(); + + if ((conference != null) && conference.isJitsiVideobridge()) + { + for (Call aCall : conference.getCalls()) + { + Iterator callPeerIter + = aCall.getCallPeers(); + + while (callPeerIter.hasNext()) + { + CallPeer aCallPeer = callPeerIter.next(); + + if (aCallPeer instanceof CallPeerJabberImpl) + { + TransportManagerJabberImpl aTransportManager + = ((CallPeerJabberImpl) aCallPeer) + .getMediaHandler() + .getTransportManager(); + + if (aTransportManager + .isEstablishingConnectivityWithJitsiVideobridge) + { + transportManager = aTransportManager; + break; + } + } + } + } + } + } + return transportManager; + } + + /** + * Gets the {@link ColibriConferenceIQ.Channel} which belongs to a content + * associated with a specific MediaType and is to be either locally + * or remotely used. + *

    + * Note: Modifications to the ColibriConferenceIQ.Channel + * instance returned by the method propagate to (the state of) this + * instance. + *

    + * + * @param mediaType the MediaType associated with the content which + * contains the ColibriConferenceIQ.Channel to get + * @param local true if the ColibriConferenceIQ.Channel + * which is to be used locally is to be returned or false for the + * one which is to be used remotely + * @return the ColibriConferenceIQ.Channel which belongs to a + * content associated with the specified mediaType and which is to + * be used in accord with the specified local indicator if such a + * channel exists; otherwise, null + */ + ColibriConferenceIQ.Channel getColibriChannel( + MediaType mediaType, + boolean local) + { + ColibriConferenceIQ.Channel channel = null; + + if (colibri != null) + { + ColibriConferenceIQ.Content content + = colibri.getContent(mediaType.toString()); + + if (content != null) + { + List channels + = content.getChannels(); + + if (channels.size() == 2) + channel = channels.get(local ? 0 : 1); + } + } + return channel; + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java index d5a6ce1..ef80392 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,74 +15,74 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; - -import org.jitsi.service.neomedia.*; - -/** - * Implements a StreamConnector which allows sharing a specific - * StreamConnector instance among multiple TransportManagers - * for the purposes of the Jitsi Videobridge. - * - * @author Lyubomir Marinov - */ -public class ColibriStreamConnector - extends StreamConnectorDelegate -{ - /** - * Initializes a new ColibriStreamConnector instance which is to - * share a specific StreamConnector instance among multiple - * TransportManagers for the purposes of the Jitsi Videobridge. - * - * @param streamConnector the StreamConnector instance to be shared - * by the new instance among multiple TransportManagers for the - * purposes of the Jitsi Videobridge - */ - public ColibriStreamConnector(StreamConnector streamConnector) - { - super(streamConnector); - } - - /** - * {@inheritDoc} - * - * Overrides {@link StreamConnectorDelegate#close()} in order to prevent the - * closing of the StreamConnector wrapped by this instance because - * the latter is shared and it is not clear whether no - * TransportManager is using it. - */ - @Override - public void close() - { - /* - * Do not close the shared StreamConnector because it is not clear - * whether no TransportManager is using it. - */ - } - - /** - * {@inheritDoc} - * - * Invokes {@link #close()} on this instance when it is clear that no - * TransportManager is using it in order to release the resources - * allocated by this instance throughout its life time (that need explicit - * disposal). - */ - @Override - protected void finalize() - throws Throwable - { - try - { - /* - * Close the shared StreamConnector because it is clear that no - * TrasportManager is using it. - */ - super.close(); - } - finally - { - super.finalize(); - } - } -} +package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri; + +import org.jitsi.service.neomedia.*; + +/** + * Implements a StreamConnector which allows sharing a specific + * StreamConnector instance among multiple TransportManagers + * for the purposes of the Jitsi Videobridge. + * + * @author Lyubomir Marinov + */ +public class ColibriStreamConnector + extends StreamConnectorDelegate +{ + /** + * Initializes a new ColibriStreamConnector instance which is to + * share a specific StreamConnector instance among multiple + * TransportManagers for the purposes of the Jitsi Videobridge. + * + * @param streamConnector the StreamConnector instance to be shared + * by the new instance among multiple TransportManagers for the + * purposes of the Jitsi Videobridge + */ + public ColibriStreamConnector(StreamConnector streamConnector) + { + super(streamConnector); + } + + /** + * {@inheritDoc} + * + * Overrides {@link StreamConnectorDelegate#close()} in order to prevent the + * closing of the StreamConnector wrapped by this instance because + * the latter is shared and it is not clear whether no + * TransportManager is using it. + */ + @Override + public void close() + { + /* + * Do not close the shared StreamConnector because it is not clear + * whether no TransportManager is using it. + */ + } + + /** + * {@inheritDoc} + * + * Invokes {@link #close()} on this instance when it is clear that no + * TransportManager is using it in order to release the resources + * allocated by this instance throughout its life time (that need explicit + * disposal). + */ + @Override + protected void finalize() + throws Throwable + { + try + { + /* + * Close the shared StreamConnector because it is clear that no + * TrasportManager is using it. + */ + super.close(); + } + finally + { + super.finalize(); + } + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java index 0c5b190..46b1e77 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,441 +15,441 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle; - -import net.java.sip.communicator.impl.protocol.jabber.extensions.*; -import org.ice4j.ice.*; - -/** - * @author Emil Ivov - */ -public class CandidatePacketExtension extends AbstractPacketExtension - implements Comparable -{ - /** - * The name of the "candidate" element. - */ - public static final String ELEMENT_NAME = "candidate"; - - /** - * The name of the "component" element. - */ - public static final String COMPONENT_ATTR_NAME = "component"; - - /** - * The "component" ID for RTP components. - */ - public static final int RTP_COMPONENT_ID = 1; - - /** - * The "component" ID for RTCP components. - */ - public static final int RTCP_COMPONENT_ID = 2; - - /** - * The name of the "foundation" element. - */ - public static final String FOUNDATION_ATTR_NAME = "foundation"; - - /** - * The name of the "generation" element. - */ - public static final String GENERATION_ATTR_NAME = "generation"; - - /** - * The name of the "id" element. - */ - public static final String ID_ATTR_NAME = "id"; - - /** - * The name of the "ip" element. - */ - public static final String IP_ATTR_NAME = "ip"; - - /** - * The name of the "network" element. - */ - public static final String NETWORK_ATTR_NAME = "network"; - - /** - * The name of the "port" element. - */ - public static final String PORT_ATTR_NAME = "port"; - - /** - * The name of the "priority" element. - */ - public static final String PRIORITY_ATTR_NAME = "priority"; - - /** - * The name of the "protocol" element. - */ - public static final String PROTOCOL_ATTR_NAME = "protocol"; - - /** - * The name of the "rel-addr" element. - */ - public static final String REL_ADDR_ATTR_NAME = "rel-addr"; - - /** - * The name of the "rel-port" element. - */ - public static final String REL_PORT_ATTR_NAME = "rel-port"; - - /** - * The name of the "type" element. - */ - public static final String TYPE_ATTR_NAME = "type"; - - /** - * The name of the "tcptype" element. - */ - public static final String TCPTYPE_ATTR_NAME = "tcptype"; - - /** - * Creates a new {@link CandidatePacketExtension} - */ - public CandidatePacketExtension() - { - super(null, ELEMENT_NAME); - } - - /** - * Creates a new {@link CandidatePacketExtension} with the specified - * elementName so that this class would be usable as a - * RemoteCandidatePacketExtension parent. - * - * @param elementName the element name that this instance should be using. - */ - protected CandidatePacketExtension(String elementName) - { - super(null, elementName); - } - - /** - * Sets a component ID as defined in ICE-CORE. - * - * @param component a component ID as defined in ICE-CORE. - */ - public void setComponent(int component) - { - super.setAttribute(COMPONENT_ATTR_NAME, component); - } - - /** - * Returns a component ID as defined in ICE-CORE. - * - * @return a component ID as defined in ICE-CORE. - */ - public int getComponent() - { - return super.getAttributeAsInt(COMPONENT_ATTR_NAME); - } - - /** - * Sets the candidate foundation as defined in ICE-CORE. - * - * @param foundation the candidate foundation as defined in ICE-CORE. - */ - public void setFoundation(String foundation) - { - super.setAttribute(FOUNDATION_ATTR_NAME, foundation); - } - - /** - * Returns the candidate foundation as defined in ICE-CORE. - * - * @return the candidate foundation as defined in ICE-CORE. - */ - public String getFoundation() - { - return super.getAttributeAsString(FOUNDATION_ATTR_NAME); - } - - /** - * Sets this candidate's generation index. A generation is an index, - * starting at 0, that enables the parties to keep track of updates to the - * candidate throughout the life of the session. For details, see the ICE - * Restarts section of XEP-0176. - * - * @param generation this candidate's generation index. - */ - public void setGeneration(int generation) - { - super.setAttribute(GENERATION_ATTR_NAME, generation); - } - - /** - * Returns this candidate's generation. A generation is an index, starting at - * 0, that enables the parties to keep track of updates to the candidate - * throughout the life of the session. For details, see the ICE Restarts - * section of XEP-0176. - * - * @return this candidate's generation index. - */ - public int getGeneration() - { - return super.getAttributeAsInt(GENERATION_ATTR_NAME); - } - - /** - * Sets this candidates's unique identifier String. - * - * @param id this candidates's unique identifier String - */ - public void setID(String id) - { - super.setAttribute(ID_ATTR_NAME, id); - } - - /** - * Returns this candidates's unique identifier String. - * - * @return this candidates's unique identifier String - */ - public String getID() - { - return super.getAttributeAsString(ID_ATTR_NAME); - } - - /** - * Sets this candidate's Internet Protocol (IP) address; this can be either - * an IPv4 address or an IPv6 address. - * - * @param ip this candidate's IPv4 or IPv6 address. - */ - public void setIP(String ip) - { - super.setAttribute(IP_ATTR_NAME, ip); - } - - /** - * Returns this candidate's Internet Protocol (IP) address; this can be - * either an IPv4 address or an IPv6 address. - * - * @return this candidate's IPv4 or IPv6 address. - */ - public String getIP() - { - return super.getAttributeAsString(IP_ATTR_NAME); - } - - /** - * The network index indicating the interface that the candidate belongs to. - * The network ID is used for diagnostic purposes only in cases where the - * calling hardware has more than one Network Interface Card. - * - * @param network the network index indicating the interface that the - * candidate belongs to. - */ - public void setNetwork(int network) - { - super.setAttribute(NETWORK_ATTR_NAME, network); - } - - /** - * Returns the network index indicating the interface that the candidate - * belongs to. The network ID is used for diagnostic purposes only in cases - * where the calling hardware has more than one Network Interface Card. - * - * @return the network index indicating the interface that the candidate - * belongs to. - */ - public int getNetwork() - { - return super.getAttributeAsInt(NETWORK_ATTR_NAME); - } - - /** - * Sets this candidate's port number. - * - * @param port this candidate's port number. - */ - public void setPort(int port) - { - super.setAttribute(PORT_ATTR_NAME, port); - } - - /** - * Returns this candidate's port number. - * - * @return this candidate's port number. - */ - public int getPort() - { - return super.getAttributeAsInt(PORT_ATTR_NAME); - } - - /** - * This candidate's priority as defined in ICE's RFC 5245 - * - * @param priority this candidate's priority - */ - public void setPriority(long priority) - { - super.setAttribute(PRIORITY_ATTR_NAME, priority); - } - - /** - * This candidate's priority as defined in ICE's RFC 5245 - * - * @return this candidate's priority - */ - public int getPriority() - { - return super.getAttributeAsInt(PRIORITY_ATTR_NAME); - } - - /** - * Sets this candidate's transport protocol. - * - * @param protocol this candidate's transport protocol. - */ - public void setProtocol(String protocol) - { - super.setAttribute(PROTOCOL_ATTR_NAME, protocol); - } - - /** - * Sets this candidate's transport protocol. - * - * @return this candidate's transport protocol. - */ - public String getProtocol() - { - return super.getAttributeAsString(PROTOCOL_ATTR_NAME); - } - - /** - * Sets this candidate's related address as described by ICE's RFC 5245. - * - * @param relAddr this candidate's related address as described by ICE's - * RFC 5245. - */ - public void setRelAddr(String relAddr) - { - super.setAttribute(REL_ADDR_ATTR_NAME, relAddr); - } - - /** - * Returns this candidate's related address as described by ICE's RFC 5245. - * - * @return this candidate's related address as described by ICE's RFC 5245. - */ - public String getRelAddr() - { - return super.getAttributeAsString(REL_ADDR_ATTR_NAME); - } - - /** - * Sets this candidate's related port as described by ICE's RFC 5245. - * - * @param relPort this candidate's related port as described by ICE's - * RFC 5245. - */ - public void setRelPort(int relPort) - { - super.setAttribute(REL_PORT_ATTR_NAME, relPort); - } - - /** - * Returns this candidate's related port as described by ICE's RFC 5245. - * - * @return this candidate's related port as described by ICE's RFC 5245. - */ - public int getRelPort() - { - return super.getAttributeAsInt(REL_PORT_ATTR_NAME); - } - - /** - * Sets a Candidate Type as defined in ICE-CORE. The allowable values are - * "host" for host candidates, "prflx" for peer reflexive candidates, - * "relay" for relayed candidates, and "srflx" for server reflexive - * candidates. All allowable values are enumerated in the {@link - * CandidateType} enum. - * - * @param type this candidates' type as per ICE's RFC 5245. - */ - public void setType(CandidateType type) - { - super.setAttribute(TYPE_ATTR_NAME, type); - } - - /** - * Returns a Candidate Type as defined in ICE-CORE. The allowable values are - * "host" for host candidates, "prflx" for peer reflexive candidates, - * "relay" for relayed candidates, and "srflx" for server reflexive - * candidates. All allowable values are enumerated in the {@link - * CandidateType} enum. - * - * @return this candidates' type as per ICE's RFC 5245. - */ - public CandidateType getType() - { - return CandidateType.valueOf(getAttributeAsString(TYPE_ATTR_NAME)); - } - - /** - * Compares this instance with another CandidatePacketExtension by - * preference of type: host < local < prflx < srflx < stun < relay. - * - * @return 0 if the type are equal. -1 if this instance type is preferred. - * Otherwise 1. - */ - public int compareTo(CandidatePacketExtension candidatePacketExtension) - { - // If the types are different. - if(this.getType() != candidatePacketExtension.getType()) - { - CandidateType[] types = { - CandidateType.host, - CandidateType.local, - CandidateType.prflx, - CandidateType.srflx, - CandidateType.stun, - CandidateType.relay - }; - for(int i = 0; i < types.length; ++i) - { - // this object is preferred. - if(types[i] == this.getType()) - { - return -1; - } - // the candidatePacketExtension is preferred. - else if(types[i] == candidatePacketExtension.getType()) - { - return 1; - } - } - } - // If the types are equal. - return 0; - } - - /** - * Gets the TCP type for this CandidatePacketExtension. - */ - public CandidateTcpType getTcpType() - { - String tcpTypeString = getAttributeAsString(TCPTYPE_ATTR_NAME); - try - { - return CandidateTcpType.parse(tcpTypeString); - } - catch (IllegalArgumentException iae) - { - return null; - } - } - - /** - * Sets the TCP type for this CandidatePacketExtension. - * @param tcpType - */ - public void setTcpType(CandidateTcpType tcpType) - { - setAttribute(TCPTYPE_ATTR_NAME, tcpType.toString()); - } -} +package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.*; +import org.ice4j.ice.*; + +/** + * @author Emil Ivov + */ +public class CandidatePacketExtension extends AbstractPacketExtension + implements Comparable +{ + /** + * The name of the "candidate" element. + */ + public static final String ELEMENT_NAME = "candidate"; + + /** + * The name of the "component" element. + */ + public static final String COMPONENT_ATTR_NAME = "component"; + + /** + * The "component" ID for RTP components. + */ + public static final int RTP_COMPONENT_ID = 1; + + /** + * The "component" ID for RTCP components. + */ + public static final int RTCP_COMPONENT_ID = 2; + + /** + * The name of the "foundation" element. + */ + public static final String FOUNDATION_ATTR_NAME = "foundation"; + + /** + * The name of the "generation" element. + */ + public static final String GENERATION_ATTR_NAME = "generation"; + + /** + * The name of the "id" element. + */ + public static final String ID_ATTR_NAME = "id"; + + /** + * The name of the "ip" element. + */ + public static final String IP_ATTR_NAME = "ip"; + + /** + * The name of the "network" element. + */ + public static final String NETWORK_ATTR_NAME = "network"; + + /** + * The name of the "port" element. + */ + public static final String PORT_ATTR_NAME = "port"; + + /** + * The name of the "priority" element. + */ + public static final String PRIORITY_ATTR_NAME = "priority"; + + /** + * The name of the "protocol" element. + */ + public static final String PROTOCOL_ATTR_NAME = "protocol"; + + /** + * The name of the "rel-addr" element. + */ + public static final String REL_ADDR_ATTR_NAME = "rel-addr"; + + /** + * The name of the "rel-port" element. + */ + public static final String REL_PORT_ATTR_NAME = "rel-port"; + + /** + * The name of the "type" element. + */ + public static final String TYPE_ATTR_NAME = "type"; + + /** + * The name of the "tcptype" element. + */ + public static final String TCPTYPE_ATTR_NAME = "tcptype"; + + /** + * Creates a new {@link CandidatePacketExtension} + */ + public CandidatePacketExtension() + { + super(null, ELEMENT_NAME); + } + + /** + * Creates a new {@link CandidatePacketExtension} with the specified + * elementName so that this class would be usable as a + * RemoteCandidatePacketExtension parent. + * + * @param elementName the element name that this instance should be using. + */ + protected CandidatePacketExtension(String elementName) + { + super(null, elementName); + } + + /** + * Sets a component ID as defined in ICE-CORE. + * + * @param component a component ID as defined in ICE-CORE. + */ + public void setComponent(int component) + { + super.setAttribute(COMPONENT_ATTR_NAME, component); + } + + /** + * Returns a component ID as defined in ICE-CORE. + * + * @return a component ID as defined in ICE-CORE. + */ + public int getComponent() + { + return super.getAttributeAsInt(COMPONENT_ATTR_NAME); + } + + /** + * Sets the candidate foundation as defined in ICE-CORE. + * + * @param foundation the candidate foundation as defined in ICE-CORE. + */ + public void setFoundation(String foundation) + { + super.setAttribute(FOUNDATION_ATTR_NAME, foundation); + } + + /** + * Returns the candidate foundation as defined in ICE-CORE. + * + * @return the candidate foundation as defined in ICE-CORE. + */ + public String getFoundation() + { + return super.getAttributeAsString(FOUNDATION_ATTR_NAME); + } + + /** + * Sets this candidate's generation index. A generation is an index, + * starting at 0, that enables the parties to keep track of updates to the + * candidate throughout the life of the session. For details, see the ICE + * Restarts section of XEP-0176. + * + * @param generation this candidate's generation index. + */ + public void setGeneration(int generation) + { + super.setAttribute(GENERATION_ATTR_NAME, generation); + } + + /** + * Returns this candidate's generation. A generation is an index, starting at + * 0, that enables the parties to keep track of updates to the candidate + * throughout the life of the session. For details, see the ICE Restarts + * section of XEP-0176. + * + * @return this candidate's generation index. + */ + public int getGeneration() + { + return super.getAttributeAsInt(GENERATION_ATTR_NAME); + } + + /** + * Sets this candidates's unique identifier String. + * + * @param id this candidates's unique identifier String + */ + public void setID(String id) + { + super.setAttribute(ID_ATTR_NAME, id); + } + + /** + * Returns this candidates's unique identifier String. + * + * @return this candidates's unique identifier String + */ + public String getID() + { + return super.getAttributeAsString(ID_ATTR_NAME); + } + + /** + * Sets this candidate's Internet Protocol (IP) address; this can be either + * an IPv4 address or an IPv6 address. + * + * @param ip this candidate's IPv4 or IPv6 address. + */ + public void setIP(String ip) + { + super.setAttribute(IP_ATTR_NAME, ip); + } + + /** + * Returns this candidate's Internet Protocol (IP) address; this can be + * either an IPv4 address or an IPv6 address. + * + * @return this candidate's IPv4 or IPv6 address. + */ + public String getIP() + { + return super.getAttributeAsString(IP_ATTR_NAME); + } + + /** + * The network index indicating the interface that the candidate belongs to. + * The network ID is used for diagnostic purposes only in cases where the + * calling hardware has more than one Network Interface Card. + * + * @param network the network index indicating the interface that the + * candidate belongs to. + */ + public void setNetwork(int network) + { + super.setAttribute(NETWORK_ATTR_NAME, network); + } + + /** + * Returns the network index indicating the interface that the candidate + * belongs to. The network ID is used for diagnostic purposes only in cases + * where the calling hardware has more than one Network Interface Card. + * + * @return the network index indicating the interface that the candidate + * belongs to. + */ + public int getNetwork() + { + return super.getAttributeAsInt(NETWORK_ATTR_NAME); + } + + /** + * Sets this candidate's port number. + * + * @param port this candidate's port number. + */ + public void setPort(int port) + { + super.setAttribute(PORT_ATTR_NAME, port); + } + + /** + * Returns this candidate's port number. + * + * @return this candidate's port number. + */ + public int getPort() + { + return super.getAttributeAsInt(PORT_ATTR_NAME); + } + + /** + * This candidate's priority as defined in ICE's RFC 5245 + * + * @param priority this candidate's priority + */ + public void setPriority(long priority) + { + super.setAttribute(PRIORITY_ATTR_NAME, priority); + } + + /** + * This candidate's priority as defined in ICE's RFC 5245 + * + * @return this candidate's priority + */ + public int getPriority() + { + return super.getAttributeAsInt(PRIORITY_ATTR_NAME); + } + + /** + * Sets this candidate's transport protocol. + * + * @param protocol this candidate's transport protocol. + */ + public void setProtocol(String protocol) + { + super.setAttribute(PROTOCOL_ATTR_NAME, protocol); + } + + /** + * Sets this candidate's transport protocol. + * + * @return this candidate's transport protocol. + */ + public String getProtocol() + { + return super.getAttributeAsString(PROTOCOL_ATTR_NAME); + } + + /** + * Sets this candidate's related address as described by ICE's RFC 5245. + * + * @param relAddr this candidate's related address as described by ICE's + * RFC 5245. + */ + public void setRelAddr(String relAddr) + { + super.setAttribute(REL_ADDR_ATTR_NAME, relAddr); + } + + /** + * Returns this candidate's related address as described by ICE's RFC 5245. + * + * @return this candidate's related address as described by ICE's RFC 5245. + */ + public String getRelAddr() + { + return super.getAttributeAsString(REL_ADDR_ATTR_NAME); + } + + /** + * Sets this candidate's related port as described by ICE's RFC 5245. + * + * @param relPort this candidate's related port as described by ICE's + * RFC 5245. + */ + public void setRelPort(int relPort) + { + super.setAttribute(REL_PORT_ATTR_NAME, relPort); + } + + /** + * Returns this candidate's related port as described by ICE's RFC 5245. + * + * @return this candidate's related port as described by ICE's RFC 5245. + */ + public int getRelPort() + { + return super.getAttributeAsInt(REL_PORT_ATTR_NAME); + } + + /** + * Sets a Candidate Type as defined in ICE-CORE. The allowable values are + * "host" for host candidates, "prflx" for peer reflexive candidates, + * "relay" for relayed candidates, and "srflx" for server reflexive + * candidates. All allowable values are enumerated in the {@link + * CandidateType} enum. + * + * @param type this candidates' type as per ICE's RFC 5245. + */ + public void setType(CandidateType type) + { + super.setAttribute(TYPE_ATTR_NAME, type); + } + + /** + * Returns a Candidate Type as defined in ICE-CORE. The allowable values are + * "host" for host candidates, "prflx" for peer reflexive candidates, + * "relay" for relayed candidates, and "srflx" for server reflexive + * candidates. All allowable values are enumerated in the {@link + * CandidateType} enum. + * + * @return this candidates' type as per ICE's RFC 5245. + */ + public CandidateType getType() + { + return CandidateType.valueOf(getAttributeAsString(TYPE_ATTR_NAME)); + } + + /** + * Compares this instance with another CandidatePacketExtension by + * preference of type: host < local < prflx < srflx < stun < relay. + * + * @return 0 if the type are equal. -1 if this instance type is preferred. + * Otherwise 1. + */ + public int compareTo(CandidatePacketExtension candidatePacketExtension) + { + // If the types are different. + if(this.getType() != candidatePacketExtension.getType()) + { + CandidateType[] types = { + CandidateType.host, + CandidateType.local, + CandidateType.prflx, + CandidateType.srflx, + CandidateType.stun, + CandidateType.relay + }; + for(int i = 0; i < types.length; ++i) + { + // this object is preferred. + if(types[i] == this.getType()) + { + return -1; + } + // the candidatePacketExtension is preferred. + else if(types[i] == candidatePacketExtension.getType()) + { + return 1; + } + } + } + // If the types are equal. + return 0; + } + + /** + * Gets the TCP type for this CandidatePacketExtension. + */ + public CandidateTcpType getTcpType() + { + String tcpTypeString = getAttributeAsString(TCPTYPE_ATTR_NAME); + try + { + return CandidateTcpType.parse(tcpTypeString); + } + catch (IllegalArgumentException iae) + { + return null; + } + } + + /** + * Sets the TCP type for this CandidatePacketExtension. + * @param tcpType + */ + public void setTcpType(CandidateTcpType tcpType) + { + setAttribute(TCPTYPE_ATTR_NAME, tcpType.toString()); + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/sip/net/ManualProxyConnection.java b/src/net/java/sip/communicator/impl/protocol/sip/net/ManualProxyConnection.java index 5439d99..ca7faa9 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/net/ManualProxyConnection.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/net/ManualProxyConnection.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,115 +15,115 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.sip.net; - -import static javax.sip.ListeningPoint.PORT_5060; -import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PREFERRED_TRANSPORT; -import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_ADDRESS; -import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_PORT; - -import java.net.*; -import java.text.*; - -import net.java.sip.communicator.impl.protocol.sip.*; -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.util.*; - -/** - * Implementation of the manually configured SIP proxy connection. IP Address - * lookups are performed using the account's proxy address. - * - * @author Ingo Bauersachs - */ -public class ManualProxyConnection - extends ProxyConnection -{ - private final static Logger logger - = Logger.getLogger(ManualProxyConnection.class); - - private String address; - private int port; - - private InetSocketAddress[] lookups; - private int lookupIndex; - - /** - * Creates a new instance of this class. Uses the server from the account. - * - * @param account the account of this SIP protocol instance - */ - public ManualProxyConnection(SipAccountIDImpl account) - { - super(account); - reset(); - } - - /* - * (non-Javadoc) - * - * @see net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection# - * getNextAddress() - */ - @Override - public boolean getNextAddressFromDns() - throws DnssecException - { - if(lookups == null) - { - try - { - lookupIndex = 0; - lookups = NetworkUtils.getAandAAAARecords(address, port); - - //no result found, reset state and indicate "out of addresses" - if(lookups.length == 0) - { - lookups = null; - return false; - } - } - catch (ParseException e) - { - logger.error("Invalid address <" + address + ">", e); - return false; - } - } - - //check if the available addresses are exhausted - if(lookupIndex >= lookups.length) - { - if(logger.isDebugEnabled()) - logger.debug("No more addresses for " + account); - lookups = null; - return false; - } - - //assign the next address and return lookup success - if(logger.isDebugEnabled()) - logger.debug("Returning <" + socketAddress - + "> as next address for " + account); - socketAddress = lookups[lookupIndex]; - lookupIndex++; - return true; - } - - /* - * (non-Javadoc) - * - * @see - * net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#reset() - */ - @Override - public void reset() - { - super.reset(); - address = account.getAccountPropertyString(PROXY_ADDRESS); - port = account.getAccountPropertyInt(PROXY_PORT, PORT_5060); - transport = account.getAccountPropertyString(PREFERRED_TRANSPORT); - - //check property sanity - if(!ProtocolProviderServiceSipImpl.isValidTransport(transport)) - throw new IllegalArgumentException( - transport + " is not a valid SIP transport"); - } -} +package net.java.sip.communicator.impl.protocol.sip.net; + +import static javax.sip.ListeningPoint.PORT_5060; +import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PREFERRED_TRANSPORT; +import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_ADDRESS; +import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_PORT; + +import java.net.*; +import java.text.*; + +import net.java.sip.communicator.impl.protocol.sip.*; +import net.java.sip.communicator.service.dns.*; +import net.java.sip.communicator.util.*; + +/** + * Implementation of the manually configured SIP proxy connection. IP Address + * lookups are performed using the account's proxy address. + * + * @author Ingo Bauersachs + */ +public class ManualProxyConnection + extends ProxyConnection +{ + private final static Logger logger + = Logger.getLogger(ManualProxyConnection.class); + + private String address; + private int port; + + private InetSocketAddress[] lookups; + private int lookupIndex; + + /** + * Creates a new instance of this class. Uses the server from the account. + * + * @param account the account of this SIP protocol instance + */ + public ManualProxyConnection(SipAccountIDImpl account) + { + super(account); + reset(); + } + + /* + * (non-Javadoc) + * + * @see net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection# + * getNextAddress() + */ + @Override + public boolean getNextAddressFromDns() + throws DnssecException + { + if(lookups == null) + { + try + { + lookupIndex = 0; + lookups = NetworkUtils.getAandAAAARecords(address, port); + + //no result found, reset state and indicate "out of addresses" + if(lookups.length == 0) + { + lookups = null; + return false; + } + } + catch (ParseException e) + { + logger.error("Invalid address <" + address + ">", e); + return false; + } + } + + //check if the available addresses are exhausted + if(lookupIndex >= lookups.length) + { + if(logger.isDebugEnabled()) + logger.debug("No more addresses for " + account); + lookups = null; + return false; + } + + //assign the next address and return lookup success + if(logger.isDebugEnabled()) + logger.debug("Returning <" + socketAddress + + "> as next address for " + account); + socketAddress = lookups[lookupIndex]; + lookupIndex++; + return true; + } + + /* + * (non-Javadoc) + * + * @see + * net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#reset() + */ + @Override + public void reset() + { + super.reset(); + address = account.getAccountPropertyString(PROXY_ADDRESS); + port = account.getAccountPropertyInt(PROXY_PORT, PORT_5060); + transport = account.getAccountPropertyString(PREFERRED_TRANSPORT); + + //check property sanity + if(!ProtocolProviderServiceSipImpl.isValidTransport(transport)) + throw new IllegalArgumentException( + transport + " is not a valid SIP transport"); + } +} diff --git a/src/net/java/sip/communicator/impl/sysactivity/DBusNetworkManager.java b/src/net/java/sip/communicator/impl/sysactivity/DBusNetworkManager.java index 4c148df..c75e941 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/DBusNetworkManager.java +++ b/src/net/java/sip/communicator/impl/sysactivity/DBusNetworkManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,133 +15,133 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.sysactivity; - -import org.freedesktop.dbus.*; -import org.freedesktop.dbus.exceptions.*; - -/** - * NetworkManager D-Bus Interface - * - * @author Damian Minkov - * @author Ingo Bauersachs - */ -@DBusInterfaceName("org.freedesktop.NetworkManager") -public interface DBusNetworkManager - extends DBusInterface -{ - /* - * Types of NetworkManager states for versions < 0.9 - */ - public static final int NM_STATE_UNKNOWN = 0; - public static final int NM_STATE_ASLEEP = 1; - public static final int NM_STATE_CONNECTING = 2; - public static final int NM_STATE_CONNECTED = 3; - public static final int NM_STATE_DISCONNECTED = 4; - - /* - * Types of NetworkManager states for versions >= 0.9 - */ - public static final int NM9_STATE_UNKNOWN = 0; - public static final int NM9_STATE_ASLEEP = 10; - public static final int NM9_STATE_DISCONNECTED = 20; - public static final int NM9_STATE_DISCONNECTING = 30; - public static final int NM9_STATE_CONNECTING = 40; - public static final int NM9_STATE_CONNECTED_LOCAL = 50; - public static final int NM9_STATE_CONNECTED_SITE = 60; - public static final int NM9_STATE_CONNECTED_GLOBAL = 70; - - /** - * State change signal. - */ - public class StateChange extends DBusSignal - { - /** - * The name of the signal. - */ - public final String name; - - /** - * The current status it holds. - */ - public final UInt32 status; - - /** - * Creates status change. - * @param path the path - * @param status the status - * @throws DBusException - */ - public StateChange(String path, UInt32 status) - throws DBusException - { - super(path, status); - name = path; - this.status = status; - } - - /** - * The current status. - * @return the current status - */ - public int getStatus() - { - return status.intValue(); - } - - /** - * Returns status description - * @return the status description - */ - public String getStatusName() - { - switch(status.intValue()) - { - case NM_STATE_ASLEEP : return "Asleep"; - case NM_STATE_CONNECTING : return "Connecting"; - case NM_STATE_CONNECTED : return "Connected"; - case NM_STATE_DISCONNECTED : return "Disconnected"; - default : return "Unknown"; - } - } - } - - /** - * State changed signal. - */ - public static class StateChanged extends StateChange - { - /** - * Creates status changed. - * @param path the path - * @param status the status - * @throws DBusException - */ - public StateChanged(String path, UInt32 status) - throws DBusException - { - super(path, status); - } - - /** - * Returns status description - * @return the status name - */ - @Override - public String getStatusName() - { - switch(status.intValue()) - { - case NM9_STATE_UNKNOWN: return "Unknown"; - case NM9_STATE_ASLEEP: return "Asleep"; - case NM9_STATE_DISCONNECTED: return "Disconnected"; - case NM9_STATE_DISCONNECTING: return "Disconnecting"; - case NM9_STATE_CONNECTING: return "Connecting"; - case NM9_STATE_CONNECTED_LOCAL: return "LocalConnectivity"; - case NM9_STATE_CONNECTED_SITE: return "SiteConnectivity"; - case NM9_STATE_CONNECTED_GLOBAL: return "GlobalConnectivity"; - default : return "Unknown"; - } - } - } -} +package net.java.sip.communicator.impl.sysactivity; + +import org.freedesktop.dbus.*; +import org.freedesktop.dbus.exceptions.*; + +/** + * NetworkManager D-Bus Interface + * + * @author Damian Minkov + * @author Ingo Bauersachs + */ +@DBusInterfaceName("org.freedesktop.NetworkManager") +public interface DBusNetworkManager + extends DBusInterface +{ + /* + * Types of NetworkManager states for versions < 0.9 + */ + public static final int NM_STATE_UNKNOWN = 0; + public static final int NM_STATE_ASLEEP = 1; + public static final int NM_STATE_CONNECTING = 2; + public static final int NM_STATE_CONNECTED = 3; + public static final int NM_STATE_DISCONNECTED = 4; + + /* + * Types of NetworkManager states for versions >= 0.9 + */ + public static final int NM9_STATE_UNKNOWN = 0; + public static final int NM9_STATE_ASLEEP = 10; + public static final int NM9_STATE_DISCONNECTED = 20; + public static final int NM9_STATE_DISCONNECTING = 30; + public static final int NM9_STATE_CONNECTING = 40; + public static final int NM9_STATE_CONNECTED_LOCAL = 50; + public static final int NM9_STATE_CONNECTED_SITE = 60; + public static final int NM9_STATE_CONNECTED_GLOBAL = 70; + + /** + * State change signal. + */ + public class StateChange extends DBusSignal + { + /** + * The name of the signal. + */ + public final String name; + + /** + * The current status it holds. + */ + public final UInt32 status; + + /** + * Creates status change. + * @param path the path + * @param status the status + * @throws DBusException + */ + public StateChange(String path, UInt32 status) + throws DBusException + { + super(path, status); + name = path; + this.status = status; + } + + /** + * The current status. + * @return the current status + */ + public int getStatus() + { + return status.intValue(); + } + + /** + * Returns status description + * @return the status description + */ + public String getStatusName() + { + switch(status.intValue()) + { + case NM_STATE_ASLEEP : return "Asleep"; + case NM_STATE_CONNECTING : return "Connecting"; + case NM_STATE_CONNECTED : return "Connected"; + case NM_STATE_DISCONNECTED : return "Disconnected"; + default : return "Unknown"; + } + } + } + + /** + * State changed signal. + */ + public static class StateChanged extends StateChange + { + /** + * Creates status changed. + * @param path the path + * @param status the status + * @throws DBusException + */ + public StateChanged(String path, UInt32 status) + throws DBusException + { + super(path, status); + } + + /** + * Returns status description + * @return the status name + */ + @Override + public String getStatusName() + { + switch(status.intValue()) + { + case NM9_STATE_UNKNOWN: return "Unknown"; + case NM9_STATE_ASLEEP: return "Asleep"; + case NM9_STATE_DISCONNECTED: return "Disconnected"; + case NM9_STATE_DISCONNECTING: return "Disconnecting"; + case NM9_STATE_CONNECTING: return "Connecting"; + case NM9_STATE_CONNECTED_LOCAL: return "LocalConnectivity"; + case NM9_STATE_CONNECTED_SITE: return "SiteConnectivity"; + case NM9_STATE_CONNECTED_GLOBAL: return "GlobalConnectivity"; + default : return "Unknown"; + } + } + } +} diff --git a/src/net/java/sip/communicator/impl/sysactivity/NetworkManagerListenerImpl.java b/src/net/java/sip/communicator/impl/sysactivity/NetworkManagerListenerImpl.java index 952645a..94f8748 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/NetworkManagerListenerImpl.java +++ b/src/net/java/sip/communicator/impl/sysactivity/NetworkManagerListenerImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,164 +15,164 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.sysactivity; - -import net.java.sip.communicator.service.sysactivity.event.*; -import net.java.sip.communicator.util.*; - -import org.freedesktop.*; -import org.freedesktop.dbus.*; -import org.freedesktop.dbus.exceptions.*; - -/** - * Responsible for subscribe and dispatch signals from NetworkManager. - * Uses dbus to connect. - * - * @author Damian Minkov - */ -@SuppressWarnings("rawtypes") -public class NetworkManagerListenerImpl - implements DBusSigHandler, - SystemActivityManager -{ - /** - * The logger. - */ - private Logger logger = Logger.getLogger( - NetworkManagerListenerImpl.class.getName()); - - /** - * Dbus connection we use. - */ - private DBusConnection dbusConn; - - /** - * Make only one instance. - */ - public NetworkManagerListenerImpl() - { - try - { - dbusConn = DBusConnection.getConnection(DBusConnection.SYSTEM); - } - catch(DBusException e) - { - logger.error("Cannot obtain dbus connection", e); - } - } - - /** - * Starts - */ - @SuppressWarnings("unchecked") - public void start() - { - // on error connecting to dbus do nothing - if(dbusConn == null) - return; - - try - { - dbusConn.addSigHandler(DBus.NameOwnerChanged.class, this); - dbusConn.addSigHandler(DBusNetworkManager.StateChange.class, this); - dbusConn.addSigHandler(DBusNetworkManager.StateChanged.class, this); - } - catch(DBusException e) - { - logger.error("Error adding dbus signal handlers", e); - } - } - - /** - * Stops. - */ - @SuppressWarnings("unchecked") - public void stop() - { - // on error connecting to dbus do nothing - if(dbusConn == null) - return; - - try - { - dbusConn.removeSigHandler(DBus.NameOwnerChanged.class, this); - dbusConn.removeSigHandler( - DBusNetworkManager.StateChange.class, this); - dbusConn.removeSigHandler( - DBusNetworkManager.StateChanged.class, this); - } - catch(DBusException e) - { - logger.error("Error removing dbus signal handlers", e); - } - } - - /** - * Receives signals and dispatch them. - * @param dBusSignal signal to handle. - */ - public void handle(DBusSignal dBusSignal) - { - if(dBusSignal instanceof DBus.NameOwnerChanged) - { - DBus.NameOwnerChanged nameOwnerChanged = - (DBus.NameOwnerChanged)dBusSignal; - - if(nameOwnerChanged.name.equals("org.freedesktop.NetworkManager")) - { - boolean b1 = nameOwnerChanged.old_owner != null - && nameOwnerChanged.old_owner.length() > 0; - boolean b2 = nameOwnerChanged.new_owner != null - && nameOwnerChanged.new_owner.length() > 0; - - if(b1 && !b2) - { - SystemActivityEvent evt = new SystemActivityEvent( - SysActivityActivator.getSystemActivityService(), - SystemActivityEvent.EVENT_NETWORK_CHANGE); - SysActivityActivator.getSystemActivityService() - .fireSystemActivityEvent(evt); - } - } - } - else if(dBusSignal instanceof DBusNetworkManager.StateChange) - { - DBusNetworkManager.StateChange stateChange = - (DBusNetworkManager.StateChange)dBusSignal; - - SystemActivityEvent evt = null; - switch(stateChange.getStatus()) - { - case DBusNetworkManager.NM_STATE_CONNECTED: - case DBusNetworkManager.NM_STATE_DISCONNECTED: - case DBusNetworkManager.NM9_STATE_DISCONNECTED: - case DBusNetworkManager.NM9_STATE_CONNECTED_LOCAL: - case DBusNetworkManager.NM9_STATE_CONNECTED_SITE: - case DBusNetworkManager.NM9_STATE_CONNECTED_GLOBAL: - evt = new SystemActivityEvent( - SysActivityActivator.getSystemActivityService(), - SystemActivityEvent.EVENT_NETWORK_CHANGE); - break; - case DBusNetworkManager.NM_STATE_ASLEEP: - case DBusNetworkManager.NM9_STATE_ASLEEP: - evt = new SystemActivityEvent( - SysActivityActivator.getSystemActivityService(), - SystemActivityEvent.EVENT_SLEEP); - break; - } - - if(evt != null) - SysActivityActivator.getSystemActivityService() - .fireSystemActivityEvent(evt); - } - } - - /** - * Whether we are connected to the network manager through dbus. - * @return whether we are connected to the network manager. - */ - public boolean isConnected() - { - return dbusConn != null; - } -} +package net.java.sip.communicator.impl.sysactivity; + +import net.java.sip.communicator.service.sysactivity.event.*; +import net.java.sip.communicator.util.*; + +import org.freedesktop.*; +import org.freedesktop.dbus.*; +import org.freedesktop.dbus.exceptions.*; + +/** + * Responsible for subscribe and dispatch signals from NetworkManager. + * Uses dbus to connect. + * + * @author Damian Minkov + */ +@SuppressWarnings("rawtypes") +public class NetworkManagerListenerImpl + implements DBusSigHandler, + SystemActivityManager +{ + /** + * The logger. + */ + private Logger logger = Logger.getLogger( + NetworkManagerListenerImpl.class.getName()); + + /** + * Dbus connection we use. + */ + private DBusConnection dbusConn; + + /** + * Make only one instance. + */ + public NetworkManagerListenerImpl() + { + try + { + dbusConn = DBusConnection.getConnection(DBusConnection.SYSTEM); + } + catch(DBusException e) + { + logger.error("Cannot obtain dbus connection", e); + } + } + + /** + * Starts + */ + @SuppressWarnings("unchecked") + public void start() + { + // on error connecting to dbus do nothing + if(dbusConn == null) + return; + + try + { + dbusConn.addSigHandler(DBus.NameOwnerChanged.class, this); + dbusConn.addSigHandler(DBusNetworkManager.StateChange.class, this); + dbusConn.addSigHandler(DBusNetworkManager.StateChanged.class, this); + } + catch(DBusException e) + { + logger.error("Error adding dbus signal handlers", e); + } + } + + /** + * Stops. + */ + @SuppressWarnings("unchecked") + public void stop() + { + // on error connecting to dbus do nothing + if(dbusConn == null) + return; + + try + { + dbusConn.removeSigHandler(DBus.NameOwnerChanged.class, this); + dbusConn.removeSigHandler( + DBusNetworkManager.StateChange.class, this); + dbusConn.removeSigHandler( + DBusNetworkManager.StateChanged.class, this); + } + catch(DBusException e) + { + logger.error("Error removing dbus signal handlers", e); + } + } + + /** + * Receives signals and dispatch them. + * @param dBusSignal signal to handle. + */ + public void handle(DBusSignal dBusSignal) + { + if(dBusSignal instanceof DBus.NameOwnerChanged) + { + DBus.NameOwnerChanged nameOwnerChanged = + (DBus.NameOwnerChanged)dBusSignal; + + if(nameOwnerChanged.name.equals("org.freedesktop.NetworkManager")) + { + boolean b1 = nameOwnerChanged.old_owner != null + && nameOwnerChanged.old_owner.length() > 0; + boolean b2 = nameOwnerChanged.new_owner != null + && nameOwnerChanged.new_owner.length() > 0; + + if(b1 && !b2) + { + SystemActivityEvent evt = new SystemActivityEvent( + SysActivityActivator.getSystemActivityService(), + SystemActivityEvent.EVENT_NETWORK_CHANGE); + SysActivityActivator.getSystemActivityService() + .fireSystemActivityEvent(evt); + } + } + } + else if(dBusSignal instanceof DBusNetworkManager.StateChange) + { + DBusNetworkManager.StateChange stateChange = + (DBusNetworkManager.StateChange)dBusSignal; + + SystemActivityEvent evt = null; + switch(stateChange.getStatus()) + { + case DBusNetworkManager.NM_STATE_CONNECTED: + case DBusNetworkManager.NM_STATE_DISCONNECTED: + case DBusNetworkManager.NM9_STATE_DISCONNECTED: + case DBusNetworkManager.NM9_STATE_CONNECTED_LOCAL: + case DBusNetworkManager.NM9_STATE_CONNECTED_SITE: + case DBusNetworkManager.NM9_STATE_CONNECTED_GLOBAL: + evt = new SystemActivityEvent( + SysActivityActivator.getSystemActivityService(), + SystemActivityEvent.EVENT_NETWORK_CHANGE); + break; + case DBusNetworkManager.NM_STATE_ASLEEP: + case DBusNetworkManager.NM9_STATE_ASLEEP: + evt = new SystemActivityEvent( + SysActivityActivator.getSystemActivityService(), + SystemActivityEvent.EVENT_SLEEP); + break; + } + + if(evt != null) + SysActivityActivator.getSystemActivityService() + .fireSystemActivityEvent(evt); + } + } + + /** + * Whether we are connected to the network manager through dbus. + * @return whether we are connected to the network manager. + */ + public boolean isConnected() + { + return dbusConn != null; + } +} diff --git a/src/net/java/sip/communicator/impl/sysactivity/SysActivityActivator.java b/src/net/java/sip/communicator/impl/sysactivity/SysActivityActivator.java index 6a46e18..96cea29 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SysActivityActivator.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SysActivityActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,101 +15,101 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.sysactivity; - -import net.java.sip.communicator.service.sysactivity.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Listens for system activity changes like sleep, network change, inactivity - * and informs all its listeners. - * - * @author Damian Minkov - */ -public class SysActivityActivator - implements BundleActivator -{ - /** - * The Logger used by this SysActivityActivator for - * logging output. - */ - private final Logger logger = Logger.getLogger(SysActivityActivator.class); - - /** - * The OSGi BundleContext. - */ - private static BundleContext bundleContext = null; - - /** - * The system activity service impl. - */ - private static SystemActivityNotificationsServiceImpl - sysActivitiesServiceImpl; - - /** - * Called when this bundle is started so the Framework can perform the - * bundle-specific activities necessary to start this bundle. - * - * @param bundleContext The execution context of the bundle being started. - * @throws Exception If this method throws an exception, this bundle is - * marked as stopped and the Framework will remove this bundle's listeners, - * unregister all services registered by this bundle, and release all - * services used by this bundle. - */ - public void start(BundleContext bundleContext) - throws Exception - { - SysActivityActivator.bundleContext = bundleContext; - - if (logger.isDebugEnabled()) - logger.debug("Started."); - - sysActivitiesServiceImpl = new SystemActivityNotificationsServiceImpl(); - sysActivitiesServiceImpl.start(); - - bundleContext.registerService( - SystemActivityNotificationsService.class.getName(), - sysActivitiesServiceImpl, - null); - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return a reference to the BundleContext instance that we were started - * with. - */ - public static SystemActivityNotificationsServiceImpl - getSystemActivityService() - { - return sysActivitiesServiceImpl; - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param bundleContext The execution context of the bundle being stopped. - * @throws Exception If this method throws an exception, the bundle is still - * marked as stopped, and the Framework will remove the bundle's listeners, - * unregister all services registered by the bundle, and release all - * services used by the bundle. - */ - public void stop(BundleContext bundleContext) - throws Exception - { - if (sysActivitiesServiceImpl != null) - sysActivitiesServiceImpl.stop(); - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return a reference to the BundleContext instance that we were started - * with. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } -} +package net.java.sip.communicator.impl.sysactivity; + +import net.java.sip.communicator.service.sysactivity.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * Listens for system activity changes like sleep, network change, inactivity + * and informs all its listeners. + * + * @author Damian Minkov + */ +public class SysActivityActivator + implements BundleActivator +{ + /** + * The Logger used by this SysActivityActivator for + * logging output. + */ + private final Logger logger = Logger.getLogger(SysActivityActivator.class); + + /** + * The OSGi BundleContext. + */ + private static BundleContext bundleContext = null; + + /** + * The system activity service impl. + */ + private static SystemActivityNotificationsServiceImpl + sysActivitiesServiceImpl; + + /** + * Called when this bundle is started so the Framework can perform the + * bundle-specific activities necessary to start this bundle. + * + * @param bundleContext The execution context of the bundle being started. + * @throws Exception If this method throws an exception, this bundle is + * marked as stopped and the Framework will remove this bundle's listeners, + * unregister all services registered by this bundle, and release all + * services used by this bundle. + */ + public void start(BundleContext bundleContext) + throws Exception + { + SysActivityActivator.bundleContext = bundleContext; + + if (logger.isDebugEnabled()) + logger.debug("Started."); + + sysActivitiesServiceImpl = new SystemActivityNotificationsServiceImpl(); + sysActivitiesServiceImpl.start(); + + bundleContext.registerService( + SystemActivityNotificationsService.class.getName(), + sysActivitiesServiceImpl, + null); + } + + /** + * Returns a reference to the bundle context that we were started with. + * @return a reference to the BundleContext instance that we were started + * with. + */ + public static SystemActivityNotificationsServiceImpl + getSystemActivityService() + { + return sysActivitiesServiceImpl; + } + + /** + * Called when this bundle is stopped so the Framework can perform the + * bundle-specific activities necessary to stop the bundle. + * + * @param bundleContext The execution context of the bundle being stopped. + * @throws Exception If this method throws an exception, the bundle is still + * marked as stopped, and the Framework will remove the bundle's listeners, + * unregister all services registered by the bundle, and release all + * services used by the bundle. + */ + public void stop(BundleContext bundleContext) + throws Exception + { + if (sysActivitiesServiceImpl != null) + sysActivitiesServiceImpl.stop(); + } + + /** + * Returns a reference to the bundle context that we were started with. + * @return a reference to the BundleContext instance that we were started + * with. + */ + public static BundleContext getBundleContext() + { + return bundleContext; + } +} diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java index c25504f..c58805b 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotificationsServiceImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,639 +15,639 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.sysactivity; - -import java.util.*; - -import net.java.sip.communicator.service.sysactivity.*; -import net.java.sip.communicator.service.sysactivity.event.*; -import net.java.sip.communicator.util.Logger; - -import org.jitsi.util.*; - -/** - * Service implementation listens for computer changes as sleeping, network - * change, inactivity. - * - * @author Damian Minkov - */ -public class SystemActivityNotificationsServiceImpl - implements SystemActivityNotifications.NotificationsDelegate, - SystemActivityNotificationsService, - Runnable -{ - /** - * The Logger used by this - * SystemActivityNotificationsServiceImpl for logging output. - */ - private final Logger logger - = Logger.getLogger(SystemActivityNotificationsServiceImpl.class); - - /** - * The thread dispatcher of network change events. - */ - private final SystemActivityEventDispatcher eventDispatcher - = new SystemActivityEventDispatcher(); - - /** - * A list of listeners registered for idle events. - */ - private final Map idleChangeListeners - = new HashMap(); - - /** - * Listeners which are fired for idle state and which will be fired - * with idle end when needed. - */ - private final List listenersInIdleState - = new ArrayList(); - - /** - * The interval between checks when not idle. - */ - private static final int CHECK_FOR_IDLE_DEFAULT = 30 * 1000; - - /** - * The interval between checks when idle. The interval is shorter - * so we can react almost immediately when we are active again. - */ - private static final int CHECK_FOR_IDLE_WHEN_IDLE = 1000; - - /** - * The time in milliseconds between two checks for system idle. - */ - private static int idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; - - /** - * Whether current service is started or stopped. - */ - private boolean running = false; - - /** - * The time when we received latest network change event. - */ - private long lastNetworkChange = -1; - - /** - * Sometimes (on windows) we got several network change events - * this is the time after which latest event we will skip next events. - */ - private static final long NETWORK_EVENT_SILENT_TIME = 10*1000; - - /** - * Whether network is currently connected. - */ - private Boolean networkIsConnected = null; - - /** - * The linux impl class name. - */ - private static final String SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS - = "net.java.sip.communicator.impl.sysactivity.NetworkManagerListenerImpl"; - - /** - * The android impl class name. - */ - private static final String SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS - = "net.java.sip.communicator.impl.sysactivity.ConnectivityManagerListenerImpl"; - - /** - * The currently instantiated and working manager. - */ - private SystemActivityManager currentRunningManager = null; - - /** - * Init and start notifications. - */ - public void start() - { - running = true; - - // set the delegate and start notification in new thread - // make sure we don't block startup process - Thread notifystartThread - = new Thread( - new Runnable() - { - public void run() - { - SystemActivityNotifications.setDelegate( - SystemActivityNotificationsServiceImpl.this); - SystemActivityNotifications.start(); - } - }, - "SystemActivityNotificationsServiceImpl"); - notifystartThread.setDaemon(true); - notifystartThread.start(); - - if(isSupported(SystemActivityEvent.EVENT_SYSTEM_IDLE)) - { - // a thread periodically checks system idle state and if it pass the - // idle time for a particular listener, will inform it. - Thread idleNotifyThread = new Thread( - this, - "SystemActivityNotificationsServiceImpl.IdleNotifyThread"); - idleNotifyThread.setDaemon(true); - idleNotifyThread.start(); - } - - if (getCurrentRunningManager() != null) - getCurrentRunningManager().start(); - } - - /** - * Stop notifications. - */ - public void stop() - { - SystemActivityNotifications.stop(); - - if (getCurrentRunningManager() != null) - getCurrentRunningManager().stop(); - - eventDispatcher.stop(); - - running = false; - - synchronized(this) - { - this.notifyAll(); - } - } - - /** - * Registers a listener that would be notified of changes that have occurred - * in the underlying system. - * - * @param listener the listener that we'd like to register for changes in - * the underlying system. - */ - public void addSystemActivityChangeListener( - SystemActivityChangeListener listener) - { - eventDispatcher.addSystemActivityChangeListener(listener); - } - - /** - * Remove the specified listener so that it won't receive further - * notifications of changes that occur in the underlying system - * - * @param listener the listener to remove. - */ - public void removeSystemActivityChangeListener( - SystemActivityChangeListener listener) - { - eventDispatcher.removeSystemActivityChangeListener(listener); - } - - /** - * Registers a listener that would be notified for idle of the system - * for idleTime. - * - * @param idleTime the time in milliseconds after which we will consider - * system to be idle. This doesn't count when system seems idle as - * monitor is off or screensaver is on, or desktop is locked. - * @param listener the listener that we'd like to register for changes in - * the underlying system. - */ - public void addIdleSystemChangeListener( - long idleTime, - SystemActivityChangeListener listener) - { - synchronized (idleChangeListeners) - { - if (idleTime > 0 - && !idleChangeListeners.containsKey(listener)) - idleChangeListeners.put(listener, idleTime); - } - } - - /** - * Remove the specified listener so that it won't receive further - * notifications for idle system. - * - * @param listener the listener to remove. - */ - public void removeIdleSystemChangeListener( - SystemActivityChangeListener listener) - { - synchronized (idleChangeListeners) - { - idleChangeListeners.remove(listener); - } - } - - /** - * The time since last user input. The time the system has been idle. - * @return time the system has been idle. - */ - public long getTimeSinceLastInput() - { - if(SystemActivityNotifications.isLoaded()) - return SystemActivityNotifications.getLastInput(); - else - return -1; - } - - /** - * Callback method when receiving notifications. - * - * @param type type of the notification. - */ - public void notify(int type) - { - SystemActivityEvent evt = null; - switch(type) - { - case SystemActivityNotifications.NOTIFY_SLEEP : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SLEEP); - break; - case SystemActivityNotifications.NOTIFY_WAKE : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_WAKE); - break; - case SystemActivityNotifications.NOTIFY_DISPLAY_SLEEP : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_DISPLAY_SLEEP); - break; - case SystemActivityNotifications.NOTIFY_DISPLAY_WAKE : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_DISPLAY_WAKE); - break; - case SystemActivityNotifications.NOTIFY_SCREENSAVER_START : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SCREENSAVER_START); - break; - case SystemActivityNotifications.NOTIFY_SCREENSAVER_WILL_STOP : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SCREENSAVER_WILL_STOP); - break; - case SystemActivityNotifications.NOTIFY_SCREENSAVER_STOP : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SCREENSAVER_STOP); - break; - case SystemActivityNotifications.NOTIFY_SCREEN_LOCKED : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SCREEN_LOCKED); - break; - case SystemActivityNotifications.NOTIFY_SCREEN_UNLOCKED : - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_SCREEN_UNLOCKED); - break; - case SystemActivityNotifications.NOTIFY_NETWORK_CHANGE : - { - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_NETWORK_CHANGE); - break; - } - case SystemActivityNotifications.NOTIFY_DNS_CHANGE : - { - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_DNS_CHANGE); - break; - } - case SystemActivityNotifications.NOTIFY_QUERY_ENDSESSION : - { - // both events QUERY_ENDSESSION and ENDSESSION - // depend on the result one after another - // we don't put them in new thread in order to give control - // in the bundles using this events. - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_QUERY_ENDSESSION); - eventDispatcher.fireSystemActivityEventCurrentThread(evt); - - return; - } - case SystemActivityNotifications.NOTIFY_ENDSESSION : - { - // both events QUERY_ENDSESSION and ENDSESSION - // depend on the result one after another - // we don't put them in new thread in order to give control - // in the bundles using this events. - evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_ENDSESSION); - eventDispatcher.fireSystemActivityEventCurrentThread(evt); - - return; - } - } - - if (evt != null) - fireSystemActivityEvent(evt); - } - - /** - * Callback method when receiving special network notifications. - * - * @param family family of network change (ipv6, ipv4) - * AF_UNSPEC = 0 (The address family is unspecified.) - * AF_INET = 2 (The Internet Protocol version 4 (IPv4) address family) - * AF_INET6 = 23 (The Internet Protocol version 6 (IPv6) address family) - * @param luidIndex unique index of interface - * @param name name of the interface - * @param type of the interface - * Possible values for the interface type are listed in the Ipifcons.h file. - * common values: - * IF_TYPE_OTHER = 1 (Some other type of network interface.) - * IF_TYPE_ETHERNET_CSMACD = 6 (An Ethernet network interface.) - * IF_TYPE_ISO88025_TOKENRING = 9 (A token ring network interface.) - * IF_TYPE_PPP = 23 (A PPP network interface.) - * IF_TYPE_SOFTWARE_LOOPBACK = 24 (A software loopback network interface.) - * IF_TYPE_IEEE80211 = 71 (An IEEE 802.11 wireless network interface.) - * IF_TYPE_TUNNEL = 131 (A tunnel type encapsulation network interface.) - * IF_TYPE_IEEE1394 = 144 (An IEEE 1394 (Firewire) high performance - * serial bus network interface.) - * @param connected whether interface is connected or not. - */ - public void notifyNetworkChange( - int family, - long luidIndex, - String name, - long type, - boolean connected) - { - long current = System.currentTimeMillis(); - if(current - lastNetworkChange <= NETWORK_EVENT_SILENT_TIME - && (networkIsConnected != null && networkIsConnected.equals(connected))) - { - networkIsConnected = connected; - return; - } - - lastNetworkChange = current; - networkIsConnected = connected; - - SystemActivityEvent evt = new SystemActivityEvent(this, - SystemActivityEvent.EVENT_NETWORK_CHANGE); - fireSystemActivityEvent(evt); - } - - /** - * The thread run method that handles idle notifies. - * - * @see Thread#run() - */ - public void run() - { - while(running) - { - try - { - long idleTime = 0; - if(idleChangeListeners.size() > 0) - { - // check - idleTime = SystemActivityNotifications.getLastInput(); - - if((idleTime < idleStateCheckDelay) - && (listenersInIdleState.size() > 0)) - { - for(SystemActivityChangeListener l - : listenersInIdleState) - { - fireSystemIdleEndEvent(l); - } - listenersInIdleState.clear(); - } - - for(Map.Entry entry - : idleChangeListeners.entrySet()) - { - SystemActivityChangeListener listener = - entry.getKey(); - - if(!listenersInIdleState.contains(listener) - && (entry.getValue() <= idleTime)) - { - fireSystemIdleEvent(listener); - - listenersInIdleState.add(listener); - } - } - } - - // if the minimum check for idle is X minutes - // we will wait before checking (X - Y + 1sec) - // where Y is the last idle time returned by OS - if(listenersInIdleState.size() > 0) - { - idleStateCheckDelay = CHECK_FOR_IDLE_WHEN_IDLE; - } - else if(idleTime != 0) - { - long minIdleSetting = CHECK_FOR_IDLE_DEFAULT; - - if(!idleChangeListeners.isEmpty()) - minIdleSetting = - Collections.min(idleChangeListeners.values()); - - int newSetting = (int)(minIdleSetting - idleTime) + 1000; - - if(newSetting > 0) - idleStateCheckDelay = newSetting; - else - idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; - } - else - { - idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; - } - - // wait for the specified time - synchronized(this) - { - this.wait(idleStateCheckDelay); - } - } - catch(UnsatisfiedLinkError t) - { - logger.error("Missing native impl", t); - return; - } - catch(Throwable t) - { - logger.error("Error checking for idle", t); - } - } - } - - /** - * Delivers the specified event to all registered listeners. - * - * @param evt the SystemActivityEvent that we'd like delivered to - * all registered message listeners. - */ - protected void fireSystemActivityEvent(SystemActivityEvent evt) - { - int eventID = evt.getEventID(); - - // Add network activity info to track wake up problems. - if (logger.isInfoEnabled() - && ((eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) - || (eventID == SystemActivityEvent.EVENT_DNS_CHANGE))) - { - logger.info("Received system activity event: " + evt); - } - - if (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) - { - // Give time to Java to dispatch same event and populate its network - // interfaces. - eventDispatcher.fireSystemActivityEvent(evt, 500); - } - else - eventDispatcher.fireSystemActivityEvent(evt); - } - - /** - * Delivers the specified event to all registered listeners. - * - * @param listener listener to inform - */ - protected void fireSystemIdleEvent(SystemActivityChangeListener listener) - { - SystemActivityEvent evt - = new SystemActivityEvent( - this, - SystemActivityEvent.EVENT_SYSTEM_IDLE); - - if (logger.isDebugEnabled()) - logger.debug("Dispatching SystemActivityEvent evt=" + evt); - - try - { - listener.activityChanged(evt); - } - catch (Throwable t) - { - if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - else - logger.error("Error delivering event", t); - } - } - - /** - * Delivers the specified event to listener. - * - * @param listener listener to inform - */ - protected void fireSystemIdleEndEvent( - SystemActivityChangeListener listener) - { - SystemActivityEvent evt - = new SystemActivityEvent( - this, - SystemActivityEvent.EVENT_SYSTEM_IDLE_END); - - if (logger.isDebugEnabled()) - logger.debug("Dispatching SystemActivityEvent evt=" + evt); - - try - { - listener.activityChanged(evt); - } - catch (Throwable t) - { - if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - else - logger.error("Error delivering event", t); - } - } - - /** - * Can check whether an event id is supported on - * current operation system. - * Simple return what is implemented in native, and checks - * are made when possible, for example linux cannot connect - * to NM through dbus. - * @param eventID the event to check. - * @return whether the supplied event id is supported. - */ - public boolean isSupported(int eventID) - { - if(OSUtils.IS_WINDOWS) - { - switch(eventID) - { - case SystemActivityEvent.EVENT_SLEEP: - case SystemActivityEvent.EVENT_WAKE: - case SystemActivityEvent.EVENT_NETWORK_CHANGE: - case SystemActivityEvent.EVENT_SYSTEM_IDLE: - case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: - return SystemActivityNotifications.isLoaded(); - default: - return false; - } - } - else if(OSUtils.IS_MAC) - { - return SystemActivityNotifications.isLoaded(); - } - else if(OSUtils.IS_LINUX) - { - switch(eventID) - { - case SystemActivityEvent.EVENT_SLEEP: - case SystemActivityEvent.EVENT_NETWORK_CHANGE: - { - SystemActivityManager currentRunningManager - = getCurrentRunningManager(); - - return - (currentRunningManager == null) - ? false - : currentRunningManager.isConnected(); - } - case SystemActivityEvent.EVENT_SYSTEM_IDLE: - case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: - return SystemActivityNotifications.isLoaded(); - default: - return false; - } - } - else if(OSUtils.IS_ANDROID) - { - return (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE); - } - else - { - return false; - } - } - - /** - * Returns or instantiate the manager. - * @return - */ - private SystemActivityManager getCurrentRunningManager() - { - if(currentRunningManager == null) - { - try - { - String className = null; - if(OSUtils.IS_LINUX) - { - className = SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS; - } - else if(OSUtils.IS_ANDROID) - { - className = SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS; - } - - if(className != null) - currentRunningManager = (SystemActivityManager) - Class.forName(className).newInstance(); - } - catch(Throwable t) - { - logger.error("Error creating manager", t); - } - } - - return currentRunningManager; - } -} +package net.java.sip.communicator.impl.sysactivity; + +import java.util.*; + +import net.java.sip.communicator.service.sysactivity.*; +import net.java.sip.communicator.service.sysactivity.event.*; +import net.java.sip.communicator.util.Logger; + +import org.jitsi.util.*; + +/** + * Service implementation listens for computer changes as sleeping, network + * change, inactivity. + * + * @author Damian Minkov + */ +public class SystemActivityNotificationsServiceImpl + implements SystemActivityNotifications.NotificationsDelegate, + SystemActivityNotificationsService, + Runnable +{ + /** + * The Logger used by this + * SystemActivityNotificationsServiceImpl for logging output. + */ + private final Logger logger + = Logger.getLogger(SystemActivityNotificationsServiceImpl.class); + + /** + * The thread dispatcher of network change events. + */ + private final SystemActivityEventDispatcher eventDispatcher + = new SystemActivityEventDispatcher(); + + /** + * A list of listeners registered for idle events. + */ + private final Map idleChangeListeners + = new HashMap(); + + /** + * Listeners which are fired for idle state and which will be fired + * with idle end when needed. + */ + private final List listenersInIdleState + = new ArrayList(); + + /** + * The interval between checks when not idle. + */ + private static final int CHECK_FOR_IDLE_DEFAULT = 30 * 1000; + + /** + * The interval between checks when idle. The interval is shorter + * so we can react almost immediately when we are active again. + */ + private static final int CHECK_FOR_IDLE_WHEN_IDLE = 1000; + + /** + * The time in milliseconds between two checks for system idle. + */ + private static int idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + + /** + * Whether current service is started or stopped. + */ + private boolean running = false; + + /** + * The time when we received latest network change event. + */ + private long lastNetworkChange = -1; + + /** + * Sometimes (on windows) we got several network change events + * this is the time after which latest event we will skip next events. + */ + private static final long NETWORK_EVENT_SILENT_TIME = 10*1000; + + /** + * Whether network is currently connected. + */ + private Boolean networkIsConnected = null; + + /** + * The linux impl class name. + */ + private static final String SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS + = "net.java.sip.communicator.impl.sysactivity.NetworkManagerListenerImpl"; + + /** + * The android impl class name. + */ + private static final String SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS + = "net.java.sip.communicator.impl.sysactivity.ConnectivityManagerListenerImpl"; + + /** + * The currently instantiated and working manager. + */ + private SystemActivityManager currentRunningManager = null; + + /** + * Init and start notifications. + */ + public void start() + { + running = true; + + // set the delegate and start notification in new thread + // make sure we don't block startup process + Thread notifystartThread + = new Thread( + new Runnable() + { + public void run() + { + SystemActivityNotifications.setDelegate( + SystemActivityNotificationsServiceImpl.this); + SystemActivityNotifications.start(); + } + }, + "SystemActivityNotificationsServiceImpl"); + notifystartThread.setDaemon(true); + notifystartThread.start(); + + if(isSupported(SystemActivityEvent.EVENT_SYSTEM_IDLE)) + { + // a thread periodically checks system idle state and if it pass the + // idle time for a particular listener, will inform it. + Thread idleNotifyThread = new Thread( + this, + "SystemActivityNotificationsServiceImpl.IdleNotifyThread"); + idleNotifyThread.setDaemon(true); + idleNotifyThread.start(); + } + + if (getCurrentRunningManager() != null) + getCurrentRunningManager().start(); + } + + /** + * Stop notifications. + */ + public void stop() + { + SystemActivityNotifications.stop(); + + if (getCurrentRunningManager() != null) + getCurrentRunningManager().stop(); + + eventDispatcher.stop(); + + running = false; + + synchronized(this) + { + this.notifyAll(); + } + } + + /** + * Registers a listener that would be notified of changes that have occurred + * in the underlying system. + * + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addSystemActivityChangeListener( + SystemActivityChangeListener listener) + { + eventDispatcher.addSystemActivityChangeListener(listener); + } + + /** + * Remove the specified listener so that it won't receive further + * notifications of changes that occur in the underlying system + * + * @param listener the listener to remove. + */ + public void removeSystemActivityChangeListener( + SystemActivityChangeListener listener) + { + eventDispatcher.removeSystemActivityChangeListener(listener); + } + + /** + * Registers a listener that would be notified for idle of the system + * for idleTime. + * + * @param idleTime the time in milliseconds after which we will consider + * system to be idle. This doesn't count when system seems idle as + * monitor is off or screensaver is on, or desktop is locked. + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addIdleSystemChangeListener( + long idleTime, + SystemActivityChangeListener listener) + { + synchronized (idleChangeListeners) + { + if (idleTime > 0 + && !idleChangeListeners.containsKey(listener)) + idleChangeListeners.put(listener, idleTime); + } + } + + /** + * Remove the specified listener so that it won't receive further + * notifications for idle system. + * + * @param listener the listener to remove. + */ + public void removeIdleSystemChangeListener( + SystemActivityChangeListener listener) + { + synchronized (idleChangeListeners) + { + idleChangeListeners.remove(listener); + } + } + + /** + * The time since last user input. The time the system has been idle. + * @return time the system has been idle. + */ + public long getTimeSinceLastInput() + { + if(SystemActivityNotifications.isLoaded()) + return SystemActivityNotifications.getLastInput(); + else + return -1; + } + + /** + * Callback method when receiving notifications. + * + * @param type type of the notification. + */ + public void notify(int type) + { + SystemActivityEvent evt = null; + switch(type) + { + case SystemActivityNotifications.NOTIFY_SLEEP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SLEEP); + break; + case SystemActivityNotifications.NOTIFY_WAKE : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_WAKE); + break; + case SystemActivityNotifications.NOTIFY_DISPLAY_SLEEP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DISPLAY_SLEEP); + break; + case SystemActivityNotifications.NOTIFY_DISPLAY_WAKE : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DISPLAY_WAKE); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_START : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_START); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_WILL_STOP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_WILL_STOP); + break; + case SystemActivityNotifications.NOTIFY_SCREENSAVER_STOP : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREENSAVER_STOP); + break; + case SystemActivityNotifications.NOTIFY_SCREEN_LOCKED : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREEN_LOCKED); + break; + case SystemActivityNotifications.NOTIFY_SCREEN_UNLOCKED : + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_SCREEN_UNLOCKED); + break; + case SystemActivityNotifications.NOTIFY_NETWORK_CHANGE : + { + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_NETWORK_CHANGE); + break; + } + case SystemActivityNotifications.NOTIFY_DNS_CHANGE : + { + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_DNS_CHANGE); + break; + } + case SystemActivityNotifications.NOTIFY_QUERY_ENDSESSION : + { + // both events QUERY_ENDSESSION and ENDSESSION + // depend on the result one after another + // we don't put them in new thread in order to give control + // in the bundles using this events. + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_QUERY_ENDSESSION); + eventDispatcher.fireSystemActivityEventCurrentThread(evt); + + return; + } + case SystemActivityNotifications.NOTIFY_ENDSESSION : + { + // both events QUERY_ENDSESSION and ENDSESSION + // depend on the result one after another + // we don't put them in new thread in order to give control + // in the bundles using this events. + evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_ENDSESSION); + eventDispatcher.fireSystemActivityEventCurrentThread(evt); + + return; + } + } + + if (evt != null) + fireSystemActivityEvent(evt); + } + + /** + * Callback method when receiving special network notifications. + * + * @param family family of network change (ipv6, ipv4) + * AF_UNSPEC = 0 (The address family is unspecified.) + * AF_INET = 2 (The Internet Protocol version 4 (IPv4) address family) + * AF_INET6 = 23 (The Internet Protocol version 6 (IPv6) address family) + * @param luidIndex unique index of interface + * @param name name of the interface + * @param type of the interface + * Possible values for the interface type are listed in the Ipifcons.h file. + * common values: + * IF_TYPE_OTHER = 1 (Some other type of network interface.) + * IF_TYPE_ETHERNET_CSMACD = 6 (An Ethernet network interface.) + * IF_TYPE_ISO88025_TOKENRING = 9 (A token ring network interface.) + * IF_TYPE_PPP = 23 (A PPP network interface.) + * IF_TYPE_SOFTWARE_LOOPBACK = 24 (A software loopback network interface.) + * IF_TYPE_IEEE80211 = 71 (An IEEE 802.11 wireless network interface.) + * IF_TYPE_TUNNEL = 131 (A tunnel type encapsulation network interface.) + * IF_TYPE_IEEE1394 = 144 (An IEEE 1394 (Firewire) high performance + * serial bus network interface.) + * @param connected whether interface is connected or not. + */ + public void notifyNetworkChange( + int family, + long luidIndex, + String name, + long type, + boolean connected) + { + long current = System.currentTimeMillis(); + if(current - lastNetworkChange <= NETWORK_EVENT_SILENT_TIME + && (networkIsConnected != null && networkIsConnected.equals(connected))) + { + networkIsConnected = connected; + return; + } + + lastNetworkChange = current; + networkIsConnected = connected; + + SystemActivityEvent evt = new SystemActivityEvent(this, + SystemActivityEvent.EVENT_NETWORK_CHANGE); + fireSystemActivityEvent(evt); + } + + /** + * The thread run method that handles idle notifies. + * + * @see Thread#run() + */ + public void run() + { + while(running) + { + try + { + long idleTime = 0; + if(idleChangeListeners.size() > 0) + { + // check + idleTime = SystemActivityNotifications.getLastInput(); + + if((idleTime < idleStateCheckDelay) + && (listenersInIdleState.size() > 0)) + { + for(SystemActivityChangeListener l + : listenersInIdleState) + { + fireSystemIdleEndEvent(l); + } + listenersInIdleState.clear(); + } + + for(Map.Entry entry + : idleChangeListeners.entrySet()) + { + SystemActivityChangeListener listener = + entry.getKey(); + + if(!listenersInIdleState.contains(listener) + && (entry.getValue() <= idleTime)) + { + fireSystemIdleEvent(listener); + + listenersInIdleState.add(listener); + } + } + } + + // if the minimum check for idle is X minutes + // we will wait before checking (X - Y + 1sec) + // where Y is the last idle time returned by OS + if(listenersInIdleState.size() > 0) + { + idleStateCheckDelay = CHECK_FOR_IDLE_WHEN_IDLE; + } + else if(idleTime != 0) + { + long minIdleSetting = CHECK_FOR_IDLE_DEFAULT; + + if(!idleChangeListeners.isEmpty()) + minIdleSetting = + Collections.min(idleChangeListeners.values()); + + int newSetting = (int)(minIdleSetting - idleTime) + 1000; + + if(newSetting > 0) + idleStateCheckDelay = newSetting; + else + idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + } + else + { + idleStateCheckDelay = CHECK_FOR_IDLE_DEFAULT; + } + + // wait for the specified time + synchronized(this) + { + this.wait(idleStateCheckDelay); + } + } + catch(UnsatisfiedLinkError t) + { + logger.error("Missing native impl", t); + return; + } + catch(Throwable t) + { + logger.error("Error checking for idle", t); + } + } + } + + /** + * Delivers the specified event to all registered listeners. + * + * @param evt the SystemActivityEvent that we'd like delivered to + * all registered message listeners. + */ + protected void fireSystemActivityEvent(SystemActivityEvent evt) + { + int eventID = evt.getEventID(); + + // Add network activity info to track wake up problems. + if (logger.isInfoEnabled() + && ((eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) + || (eventID == SystemActivityEvent.EVENT_DNS_CHANGE))) + { + logger.info("Received system activity event: " + evt); + } + + if (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE) + { + // Give time to Java to dispatch same event and populate its network + // interfaces. + eventDispatcher.fireSystemActivityEvent(evt, 500); + } + else + eventDispatcher.fireSystemActivityEvent(evt); + } + + /** + * Delivers the specified event to all registered listeners. + * + * @param listener listener to inform + */ + protected void fireSystemIdleEvent(SystemActivityChangeListener listener) + { + SystemActivityEvent evt + = new SystemActivityEvent( + this, + SystemActivityEvent.EVENT_SYSTEM_IDLE); + + if (logger.isDebugEnabled()) + logger.debug("Dispatching SystemActivityEvent evt=" + evt); + + try + { + listener.activityChanged(evt); + } + catch (Throwable t) + { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + else + logger.error("Error delivering event", t); + } + } + + /** + * Delivers the specified event to listener. + * + * @param listener listener to inform + */ + protected void fireSystemIdleEndEvent( + SystemActivityChangeListener listener) + { + SystemActivityEvent evt + = new SystemActivityEvent( + this, + SystemActivityEvent.EVENT_SYSTEM_IDLE_END); + + if (logger.isDebugEnabled()) + logger.debug("Dispatching SystemActivityEvent evt=" + evt); + + try + { + listener.activityChanged(evt); + } + catch (Throwable t) + { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + else + logger.error("Error delivering event", t); + } + } + + /** + * Can check whether an event id is supported on + * current operation system. + * Simple return what is implemented in native, and checks + * are made when possible, for example linux cannot connect + * to NM through dbus. + * @param eventID the event to check. + * @return whether the supplied event id is supported. + */ + public boolean isSupported(int eventID) + { + if(OSUtils.IS_WINDOWS) + { + switch(eventID) + { + case SystemActivityEvent.EVENT_SLEEP: + case SystemActivityEvent.EVENT_WAKE: + case SystemActivityEvent.EVENT_NETWORK_CHANGE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: + return SystemActivityNotifications.isLoaded(); + default: + return false; + } + } + else if(OSUtils.IS_MAC) + { + return SystemActivityNotifications.isLoaded(); + } + else if(OSUtils.IS_LINUX) + { + switch(eventID) + { + case SystemActivityEvent.EVENT_SLEEP: + case SystemActivityEvent.EVENT_NETWORK_CHANGE: + { + SystemActivityManager currentRunningManager + = getCurrentRunningManager(); + + return + (currentRunningManager == null) + ? false + : currentRunningManager.isConnected(); + } + case SystemActivityEvent.EVENT_SYSTEM_IDLE: + case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: + return SystemActivityNotifications.isLoaded(); + default: + return false; + } + } + else if(OSUtils.IS_ANDROID) + { + return (eventID == SystemActivityEvent.EVENT_NETWORK_CHANGE); + } + else + { + return false; + } + } + + /** + * Returns or instantiate the manager. + * @return + */ + private SystemActivityManager getCurrentRunningManager() + { + if(currentRunningManager == null) + { + try + { + String className = null; + if(OSUtils.IS_LINUX) + { + className = SYSTEM_ACTIVITY_MANAGER_LINUX_CLASS; + } + else if(OSUtils.IS_ANDROID) + { + className = SYSTEM_ACTIVITY_MANAGER_ANDROID_CLASS; + } + + if(className != null) + currentRunningManager = (SystemActivityManager) + Class.forName(className).newInstance(); + } + catch(Throwable t) + { + logger.error("Error creating manager", t); + } + } + + return currentRunningManager; + } +} diff --git a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java index f2181cd..06b595e 100644 --- a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java +++ b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,163 +15,163 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.accountinfo; - -import java.util.*; - -import net.java.sip.communicator.service.globaldisplaydetails.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * Starts the account info bundle. - * - * @author Adam Glodstein - * @author Marin Dzhigarov - */ -public class AccountInfoActivator - implements BundleActivator -{ - private static final Logger logger = - Logger.getLogger(AccountInfoActivator.class); - - /** - * Property to disable account info in tools menu. - */ - private static final String ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP = - "net.java.sip.communicator.plugin.accountinfo" + - ".ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP"; - - /** - * Property to disable account info in account config. - */ - private static final String ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP = - "net.java.sip.communicator.plugin.accountinfo" + - ".ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP"; - - /** - * The OSGi bundle context. - */ - public static BundleContext bundleContext; - - private static GlobalDisplayDetailsService globalDisplayDetailsService; - - public void start(BundleContext bc) throws Exception - { - AccountInfoActivator.bundleContext = bc; - - ConfigurationService config = ServiceUtils.getService( - bundleContext, ConfigurationService.class); - - if(!config.getBoolean(ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP, false)) - { - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_TOOLS_MENU.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new PluginComponentFactory(Container.CONTAINER_TOOLS_MENU) - { - @Override - protected PluginComponent getPluginInstance() - { - return new AccountInfoMenuItemComponent( - getContainer(), this); - } - }, - containerFilter); - } - - if(!config.getBoolean(ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP, false)) - { - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new PluginComponentFactory( - Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU) - { - @Override - protected PluginComponent getPluginInstance() - { - return new AccountInfoMenuItemComponent( - getContainer(), this); - } - }, - containerFilter); - } - } - - public void stop(BundleContext bc) throws Exception {} - - /** - * Returns all ProtocolProviderFactorys obtained from the bundle - * context. - * - * @return all ProtocolProviderFactorys obtained from the bundle - * context - */ - public static Map - getProtocolProviderFactories() - { - Map providerFactoriesMap = - new Hashtable(); - - ServiceReference[] serRefs = null; - try - { - // get all registered provider factories - serRefs = - bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), null); - - } - catch (InvalidSyntaxException e) - { - logger.error("LoginManager : " + e); - } - - for (int i = 0; i < serRefs.length; i++) - { - - ProtocolProviderFactory providerFactory = - (ProtocolProviderFactory) bundleContext.getService(serRefs[i]); - - providerFactoriesMap - .put(serRefs[i].getProperty(ProtocolProviderFactory.PROTOCOL), - providerFactory); - } - - return providerFactoriesMap; - } - - /** - * Returns the GlobalDisplayDetailsService obtained from the bundle - * context. - * - * @return the GlobalDisplayDetailsService obtained from the bundle - * context - */ - public static GlobalDisplayDetailsService getGlobalDisplayDetailsService() - { - if (globalDisplayDetailsService == null) - { - globalDisplayDetailsService - = ServiceUtils.getService( - bundleContext, - GlobalDisplayDetailsService.class); - } - return globalDisplayDetailsService; - } -} +package net.java.sip.communicator.plugin.accountinfo; + +import java.util.*; + +import net.java.sip.communicator.service.globaldisplaydetails.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * Starts the account info bundle. + * + * @author Adam Glodstein + * @author Marin Dzhigarov + */ +public class AccountInfoActivator + implements BundleActivator +{ + private static final Logger logger = + Logger.getLogger(AccountInfoActivator.class); + + /** + * Property to disable account info in tools menu. + */ + private static final String ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP = + "net.java.sip.communicator.plugin.accountinfo" + + ".ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP"; + + /** + * Property to disable account info in account config. + */ + private static final String ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP = + "net.java.sip.communicator.plugin.accountinfo" + + ".ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP"; + + /** + * The OSGi bundle context. + */ + public static BundleContext bundleContext; + + private static GlobalDisplayDetailsService globalDisplayDetailsService; + + public void start(BundleContext bc) throws Exception + { + AccountInfoActivator.bundleContext = bc; + + ConfigurationService config = ServiceUtils.getService( + bundleContext, ConfigurationService.class); + + if(!config.getBoolean(ACCOUNT_INFO_TOOLS_MENU_DISABLED_PROP, false)) + { + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_TOOLS_MENU.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new PluginComponentFactory(Container.CONTAINER_TOOLS_MENU) + { + @Override + protected PluginComponent getPluginInstance() + { + return new AccountInfoMenuItemComponent( + getContainer(), this); + } + }, + containerFilter); + } + + if(!config.getBoolean(ACCOUNT_INFO_ACC_CONFIG_DISABLED_PROP, false)) + { + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new PluginComponentFactory( + Container.CONTAINER_ACCOUNT_RIGHT_BUTTON_MENU) + { + @Override + protected PluginComponent getPluginInstance() + { + return new AccountInfoMenuItemComponent( + getContainer(), this); + } + }, + containerFilter); + } + } + + public void stop(BundleContext bc) throws Exception {} + + /** + * Returns all ProtocolProviderFactorys obtained from the bundle + * context. + * + * @return all ProtocolProviderFactorys obtained from the bundle + * context + */ + public static Map + getProtocolProviderFactories() + { + Map providerFactoriesMap = + new Hashtable(); + + ServiceReference[] serRefs = null; + try + { + // get all registered provider factories + serRefs = + bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), null); + + } + catch (InvalidSyntaxException e) + { + logger.error("LoginManager : " + e); + } + + for (int i = 0; i < serRefs.length; i++) + { + + ProtocolProviderFactory providerFactory = + (ProtocolProviderFactory) bundleContext.getService(serRefs[i]); + + providerFactoriesMap + .put(serRefs[i].getProperty(ProtocolProviderFactory.PROTOCOL), + providerFactory); + } + + return providerFactoriesMap; + } + + /** + * Returns the GlobalDisplayDetailsService obtained from the bundle + * context. + * + * @return the GlobalDisplayDetailsService obtained from the bundle + * context + */ + public static GlobalDisplayDetailsService getGlobalDisplayDetailsService() + { + if (globalDisplayDetailsService == null) + { + globalDisplayDetailsService + = ServiceUtils.getService( + bundleContext, + GlobalDisplayDetailsService.class); + } + return globalDisplayDetailsService; + } +} diff --git a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoPanel.java b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoPanel.java index 075aa33..92f0b9a 100644 --- a/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoPanel.java +++ b/src/net/java/sip/communicator/plugin/accountinfo/AccountInfoPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,349 +15,349 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.accountinfo; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.plugin.accountinfo.AccountInfoMenuItemComponent.*; - -import org.osgi.framework.*; - -/** - * A GUI plug-in for Jitsi that will allow users to set cross - * protocol account information. - * - * @author Adam Goldstein - * @author Marin Dzhigarov - */ -public class AccountInfoPanel - extends TransparentPanel - implements ServiceListener, - RegistrationStateChangeListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The panel that contains the currently active AccountDetailsPanel - */ - private final JPanel centerPanel = - new TransparentPanel(new BorderLayout(10, 10)); - - /** - * The currently active AccountDetailsPanel - */ - private AccountDetailsPanel currentDetailsPanel; - - /** - * Combo box that is used for switching between accounts. - */ - private final JComboBox accountsComboBox; - - /** - * Instances of the AccountDetailsPanel are created for every - * registered AccountID. All such pairs are stored in - * this map. - */ - private final Map - accountsTable = - new HashMap(); - - /** - * The parent dialog. - */ - private AccountInfoDialog dialog; - - /** - * Creates an instance of AccountInfoPanel that contains combo box - * component with active user accounts and AccountDetailsPanel to - * display and edit account information. - */ - public AccountInfoPanel(AccountInfoDialog dialog) - { - this.dialog = dialog; - - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - accountsComboBox = new JComboBox(); - accountsComboBox.setOpaque(false); - accountsComboBox.addItemListener(new ItemListener() - { - @Override - public void itemStateChanged(ItemEvent e) - { - if (e.getStateChange() == ItemEvent.SELECTED) - { - AccountDetailsPanel panel = - (AccountDetailsPanel) e.getItem(); - panel.setOpaque(false); - centerPanel.removeAll(); - centerPanel.add(panel, BorderLayout.CENTER); - centerPanel.revalidate(); - centerPanel.repaint(); - currentDetailsPanel = panel; - } - } - }); - - init(); - - centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - ComboBoxRenderer renderer = new ComboBoxRenderer(); - accountsComboBox.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - accountsComboBox.setRenderer(renderer); - - JLabel comboLabel = new JLabel( - Resources.getString( - "plugin.accountinfo.SELECT_ACCOUNT")); - comboLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); - - JPanel comboBoxPanel = new TransparentPanel(); - comboBoxPanel.setLayout(new BoxLayout(comboBoxPanel, BoxLayout.X_AXIS)); - comboBoxPanel.setBorder( - BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - comboBoxPanel.add(comboLabel); - comboBoxPanel.add(accountsComboBox); - - add(comboBoxPanel); - add(centerPanel); - } - - /** - * Initialize. - */ - private void init() - { - AccountInfoActivator.bundleContext.addServiceListener(this); - - for (ProtocolProviderFactory providerFactory : AccountInfoActivator - .getProtocolProviderFactories().values()) - { - ArrayList accountsList = - providerFactory.getRegisteredAccounts(); - - ServiceReference serRef; - ProtocolProviderService protocolProvider; - - for (AccountID accountID : accountsList) - { - serRef = providerFactory.getProviderForAccount(accountID); - - protocolProvider = (ProtocolProviderService)AccountInfoActivator - .bundleContext.getService(serRef); - - currentDetailsPanel = new AccountDetailsPanel( - dialog, - protocolProvider); - - accountsTable.put( - protocolProvider.getAccountID(), currentDetailsPanel); - - accountsComboBox.addItem(currentDetailsPanel); - - protocolProvider.addRegistrationStateChangeListener(this); - } - } - } - - /** - * Clears all listeners. - */ - public void dispose() - { - AccountInfoActivator.bundleContext.removeServiceListener(this); - - for(AccountDetailsPanel pan : accountsTable.values()) - { - pan.getProtocolProvider() - .removeRegistrationStateChangeListener(this); - } - } - - /** - * A custom renderer to display properly AccountDetailsPanel - * in a combo box. - */ - private class ComboBoxRenderer extends DefaultListCellRenderer - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - @Override - public Component getListCellRendererComponent( - JList list, Object value, int index, - boolean isSelected, boolean hasFocus) - { - JLabel renderer - = (JLabel) super.getListCellRendererComponent( - list, value, index, isSelected, hasFocus); - - if (value != null) - { - AccountDetailsPanel panel = (AccountDetailsPanel) value; - - renderer.setText( - panel.protocolProvider.getAccountID().getUserID()); - ImageIcon protocolIcon = - new ImageIcon(panel.protocolProvider.getProtocolIcon(). - getIcon((ProtocolIcon.ICON_SIZE_16x16))); - renderer.setIcon(protocolIcon); - } - - return renderer; - } - } - - public void registrationStateChanged(final RegistrationStateChangeEvent evt) - { - if(!SwingUtilities.isEventDispatchThread()) - { - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - registrationStateChanged(evt); - } - }); - return; - } - - ProtocolProviderService protocolProvider = evt.getProvider(); - - if (evt.getNewState() == RegistrationState.REGISTERED) - { - if (accountsTable.containsKey(protocolProvider.getAccountID())) - { - AccountDetailsPanel detailsPanel - = accountsTable.get(protocolProvider.getAccountID()); - detailsPanel.loadDetails(); - } - else - { - AccountDetailsPanel panel = - new AccountDetailsPanel(dialog, protocolProvider); - accountsTable.put(protocolProvider.getAccountID(), panel); - accountsComboBox.addItem(panel); - } - } - else if (evt.getNewState() == RegistrationState.UNREGISTERING) - { - AccountDetailsPanel panel - = accountsTable.get(protocolProvider.getAccountID()); - if (panel != null) - { - accountsTable.remove(protocolProvider.getAccountID()); - accountsComboBox.removeItem(panel); - if (currentDetailsPanel == panel) - { - currentDetailsPanel = null; - centerPanel.removeAll(); - centerPanel.revalidate(); - centerPanel.repaint(); - } - } - } - } - - /** - * Handles registration and unregistration of - * ProtocolProviderService - * - * @param event - */ - @Override - public void serviceChanged(final ServiceEvent event) - { - if(!SwingUtilities.isEventDispatchThread()) - { - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - serviceChanged(event); - } - }); - return; - } - - // Get the service from the event. - Object service - = AccountInfoActivator.bundleContext.getService( - event.getServiceReference()); - - // We are not interested in any services - // other than ProtocolProviderService - if (!(service instanceof ProtocolProviderService)) - return; - - ProtocolProviderService protocolProvider = - (ProtocolProviderService) service; - - // If a new protocol provider is registered we to add new - // AccountDetailsPanel to the combo box containing active accounts. - if (event.getType() == ServiceEvent.REGISTERED) - { - if (accountsTable.get(protocolProvider.getAccountID()) == null) - { - AccountDetailsPanel panel = - new AccountDetailsPanel(dialog, protocolProvider); - accountsTable.put(protocolProvider.getAccountID(), panel); - accountsComboBox.addItem(panel); - protocolProvider.addRegistrationStateChangeListener(this); - } - } - // If the protocol provider is being unregistered we have to remove - // a AccountDetailsPanel from the combo box containing active accounts. - else if (event.getType() == ServiceEvent.UNREGISTERING) - { - AccountDetailsPanel panel - = accountsTable.get(protocolProvider.getAccountID()); - if (panel != null) - { - accountsTable.remove(protocolProvider.getAccountID()); - accountsComboBox.removeItem(panel); - if (currentDetailsPanel == panel) - { - currentDetailsPanel = null; - centerPanel.removeAll(); - centerPanel.revalidate(); - centerPanel.repaint(); - } - } - } - } - - /** - * Returns the combo box that switches between account detail panels. - * - * @return The combo box that switches between account detail panels. - */ - public JComboBox getAccountsComboBox() - { - return accountsComboBox; - } - - /** - * Returns mapping between registered AccountIDs and their respective - * AccountDetailsPanel that contains all the details for the account. - * - * @return mapping between registered AccountIDs and AccountDetailsPanel. - */ - public Map getAccountsTable() - { - return accountsTable; - } -} +package net.java.sip.communicator.plugin.accountinfo; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.plugin.accountinfo.AccountInfoMenuItemComponent.*; + +import org.osgi.framework.*; + +/** + * A GUI plug-in for Jitsi that will allow users to set cross + * protocol account information. + * + * @author Adam Goldstein + * @author Marin Dzhigarov + */ +public class AccountInfoPanel + extends TransparentPanel + implements ServiceListener, + RegistrationStateChangeListener +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The panel that contains the currently active AccountDetailsPanel + */ + private final JPanel centerPanel = + new TransparentPanel(new BorderLayout(10, 10)); + + /** + * The currently active AccountDetailsPanel + */ + private AccountDetailsPanel currentDetailsPanel; + + /** + * Combo box that is used for switching between accounts. + */ + private final JComboBox accountsComboBox; + + /** + * Instances of the AccountDetailsPanel are created for every + * registered AccountID. All such pairs are stored in + * this map. + */ + private final Map + accountsTable = + new HashMap(); + + /** + * The parent dialog. + */ + private AccountInfoDialog dialog; + + /** + * Creates an instance of AccountInfoPanel that contains combo box + * component with active user accounts and AccountDetailsPanel to + * display and edit account information. + */ + public AccountInfoPanel(AccountInfoDialog dialog) + { + this.dialog = dialog; + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + accountsComboBox = new JComboBox(); + accountsComboBox.setOpaque(false); + accountsComboBox.addItemListener(new ItemListener() + { + @Override + public void itemStateChanged(ItemEvent e) + { + if (e.getStateChange() == ItemEvent.SELECTED) + { + AccountDetailsPanel panel = + (AccountDetailsPanel) e.getItem(); + panel.setOpaque(false); + centerPanel.removeAll(); + centerPanel.add(panel, BorderLayout.CENTER); + centerPanel.revalidate(); + centerPanel.repaint(); + currentDetailsPanel = panel; + } + } + }); + + init(); + + centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + ComboBoxRenderer renderer = new ComboBoxRenderer(); + accountsComboBox.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + accountsComboBox.setRenderer(renderer); + + JLabel comboLabel = new JLabel( + Resources.getString( + "plugin.accountinfo.SELECT_ACCOUNT")); + comboLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + + JPanel comboBoxPanel = new TransparentPanel(); + comboBoxPanel.setLayout(new BoxLayout(comboBoxPanel, BoxLayout.X_AXIS)); + comboBoxPanel.setBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + comboBoxPanel.add(comboLabel); + comboBoxPanel.add(accountsComboBox); + + add(comboBoxPanel); + add(centerPanel); + } + + /** + * Initialize. + */ + private void init() + { + AccountInfoActivator.bundleContext.addServiceListener(this); + + for (ProtocolProviderFactory providerFactory : AccountInfoActivator + .getProtocolProviderFactories().values()) + { + ArrayList accountsList = + providerFactory.getRegisteredAccounts(); + + ServiceReference serRef; + ProtocolProviderService protocolProvider; + + for (AccountID accountID : accountsList) + { + serRef = providerFactory.getProviderForAccount(accountID); + + protocolProvider = (ProtocolProviderService)AccountInfoActivator + .bundleContext.getService(serRef); + + currentDetailsPanel = new AccountDetailsPanel( + dialog, + protocolProvider); + + accountsTable.put( + protocolProvider.getAccountID(), currentDetailsPanel); + + accountsComboBox.addItem(currentDetailsPanel); + + protocolProvider.addRegistrationStateChangeListener(this); + } + } + } + + /** + * Clears all listeners. + */ + public void dispose() + { + AccountInfoActivator.bundleContext.removeServiceListener(this); + + for(AccountDetailsPanel pan : accountsTable.values()) + { + pan.getProtocolProvider() + .removeRegistrationStateChangeListener(this); + } + } + + /** + * A custom renderer to display properly AccountDetailsPanel + * in a combo box. + */ + private class ComboBoxRenderer extends DefaultListCellRenderer + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + @Override + public Component getListCellRendererComponent( + JList list, Object value, int index, + boolean isSelected, boolean hasFocus) + { + JLabel renderer + = (JLabel) super.getListCellRendererComponent( + list, value, index, isSelected, hasFocus); + + if (value != null) + { + AccountDetailsPanel panel = (AccountDetailsPanel) value; + + renderer.setText( + panel.protocolProvider.getAccountID().getUserID()); + ImageIcon protocolIcon = + new ImageIcon(panel.protocolProvider.getProtocolIcon(). + getIcon((ProtocolIcon.ICON_SIZE_16x16))); + renderer.setIcon(protocolIcon); + } + + return renderer; + } + } + + public void registrationStateChanged(final RegistrationStateChangeEvent evt) + { + if(!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + registrationStateChanged(evt); + } + }); + return; + } + + ProtocolProviderService protocolProvider = evt.getProvider(); + + if (evt.getNewState() == RegistrationState.REGISTERED) + { + if (accountsTable.containsKey(protocolProvider.getAccountID())) + { + AccountDetailsPanel detailsPanel + = accountsTable.get(protocolProvider.getAccountID()); + detailsPanel.loadDetails(); + } + else + { + AccountDetailsPanel panel = + new AccountDetailsPanel(dialog, protocolProvider); + accountsTable.put(protocolProvider.getAccountID(), panel); + accountsComboBox.addItem(panel); + } + } + else if (evt.getNewState() == RegistrationState.UNREGISTERING) + { + AccountDetailsPanel panel + = accountsTable.get(protocolProvider.getAccountID()); + if (panel != null) + { + accountsTable.remove(protocolProvider.getAccountID()); + accountsComboBox.removeItem(panel); + if (currentDetailsPanel == panel) + { + currentDetailsPanel = null; + centerPanel.removeAll(); + centerPanel.revalidate(); + centerPanel.repaint(); + } + } + } + } + + /** + * Handles registration and unregistration of + * ProtocolProviderService + * + * @param event + */ + @Override + public void serviceChanged(final ServiceEvent event) + { + if(!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + serviceChanged(event); + } + }); + return; + } + + // Get the service from the event. + Object service + = AccountInfoActivator.bundleContext.getService( + event.getServiceReference()); + + // We are not interested in any services + // other than ProtocolProviderService + if (!(service instanceof ProtocolProviderService)) + return; + + ProtocolProviderService protocolProvider = + (ProtocolProviderService) service; + + // If a new protocol provider is registered we to add new + // AccountDetailsPanel to the combo box containing active accounts. + if (event.getType() == ServiceEvent.REGISTERED) + { + if (accountsTable.get(protocolProvider.getAccountID()) == null) + { + AccountDetailsPanel panel = + new AccountDetailsPanel(dialog, protocolProvider); + accountsTable.put(protocolProvider.getAccountID(), panel); + accountsComboBox.addItem(panel); + protocolProvider.addRegistrationStateChangeListener(this); + } + } + // If the protocol provider is being unregistered we have to remove + // a AccountDetailsPanel from the combo box containing active accounts. + else if (event.getType() == ServiceEvent.UNREGISTERING) + { + AccountDetailsPanel panel + = accountsTable.get(protocolProvider.getAccountID()); + if (panel != null) + { + accountsTable.remove(protocolProvider.getAccountID()); + accountsComboBox.removeItem(panel); + if (currentDetailsPanel == panel) + { + currentDetailsPanel = null; + centerPanel.removeAll(); + centerPanel.revalidate(); + centerPanel.repaint(); + } + } + } + } + + /** + * Returns the combo box that switches between account detail panels. + * + * @return The combo box that switches between account detail panels. + */ + public JComboBox getAccountsComboBox() + { + return accountsComboBox; + } + + /** + * Returns mapping between registered AccountIDs and their respective + * AccountDetailsPanel that contains all the details for the account. + * + * @return mapping between registered AccountIDs and AccountDetailsPanel. + */ + public Map getAccountsTable() + { + return accountsTable; + } +} diff --git a/src/net/java/sip/communicator/plugin/accountinfo/Resources.java b/src/net/java/sip/communicator/plugin/accountinfo/Resources.java index 4557782..7c5987a 100644 --- a/src/net/java/sip/communicator/plugin/accountinfo/Resources.java +++ b/src/net/java/sip/communicator/plugin/accountinfo/Resources.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,65 +15,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.accountinfo; - -import javax.swing.*; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author Yana Stamcheva - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - /** - * Returns an internationalized string corresponding to the given key. - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static ImageIcon getImage(String imageID) - { - return getResources().getImage(imageID); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImageInBytes(String imageID) - { - return getResources().getImageInBytes(imageID); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(AccountInfoActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.accountinfo; + +import javax.swing.*; + +import net.java.sip.communicator.service.resources.*; + +import org.jitsi.service.resources.*; + +/** + * The Resources class manages the access to the internationalization + * properties files and the image resources used in this plugin. + * + * @author Yana Stamcheva + */ +public class Resources +{ + private static ResourceManagementService resourcesService; + + /** + * Returns an internationalized string corresponding to the given key. + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + return getResources().getI18NString(key); + } + + /** + * Loads an image from a given image identifier. + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static ImageIcon getImage(String imageID) + { + return getResources().getImage(imageID); + } + + /** + * Loads an image from a given image identifier. + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static byte[] getImageInBytes(String imageID) + { + return getResources().getImageInBytes(imageID); + } + + /** + * Returns the ResourceManagementService. + * + * @return the ResourceManagementService. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(AccountInfoActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/addrbook/PtrCallback.java b/src/net/java/sip/communicator/plugin/addrbook/PtrCallback.java index a06c778..674f261 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/PtrCallback.java +++ b/src/net/java/sip/communicator/plugin/addrbook/PtrCallback.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,23 +15,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.addrbook; - -/** - * Defines the interface for a callback function which is called by the native - * counterpart of the support for the OS-specific Address Book with a pointer as - * its argument. - * - * @author Lyubomir Marinov - */ -public interface PtrCallback -{ - /** - * Notifies this PtrCallback about a specific pointer. - * - * @param ptr the pointer to notify this PtrCallback about - * @return true if this PtrCallback is to continue being - * called; otherwise, false - */ - boolean callback(long ptr); -} +package net.java.sip.communicator.plugin.addrbook; + +/** + * Defines the interface for a callback function which is called by the native + * counterpart of the support for the OS-specific Address Book with a pointer as + * its argument. + * + * @author Lyubomir Marinov + */ +public interface PtrCallback +{ + /** + * Notifies this PtrCallback about a specific pointer. + * + * @param ptr the pointer to notify this PtrCallback about + * @return true if this PtrCallback is to continue being + * called; otherwise, false + */ + boolean callback(long ptr); +} diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/DefaultMailClientMessageDialog.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/DefaultMailClientMessageDialog.java index 84d9525..afec158 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/DefaultMailClientMessageDialog.java +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/DefaultMailClientMessageDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,94 +15,94 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.addrbook.msoutlook; - -import java.awt.event.*; - -import javax.swing.*; - -import org.jitsi.service.resources.*; - -import net.java.sip.communicator.plugin.addrbook.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * A dialog with warning message that Outlook is not the default mail client - * shown when the contact source is started. - * - * @author Hristo Terezov - */ -public class DefaultMailClientMessageDialog - extends MessageDialog -{ - - /** - * Serial ID. - */ - private static final long serialVersionUID = -6321186451307613417L; - - /** - * The ResourceManagementService - */ - private static ResourceManagementService resources - = AddrBookActivator.getResources(); - - /** - * Make Outlook default mail client check box. - */ - private JCheckBox defaultMailClientCheckBox = new SIPCommCheckBox( - resources - .getI18NString("plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT")); - - public static int DONT_ASK_SELECTED_MASK = 1; - - public static int DEFAULT_MAIL_CLIENT_SELECTED_MASK = 2; - - /** - * Creates an instance of DefaultMailClientMessageDialog. - */ - public DefaultMailClientMessageDialog() - { - super(null, - AddrBookActivator.getResources().getI18NString( - "plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE"), - resources.getI18NString( - "plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT", - new String[]{ - resources.getSettingsString( - "service.gui.APPLICATION_NAME")}), false); - checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS)); - checkBoxPanel.add(defaultMailClientCheckBox); - } - - - /** - * Handles the ActionEvent. Depending on the user choice sets - * the return code to the appropriate value. - * - * @param e the ActionEvent that notified us - */ - public void actionPerformed(ActionEvent e) - { - JButton button = (JButton)e.getSource(); - - if(!button.equals(okButton)) - return; - - this.returnCode = 0; - - if (doNotAskAgain.isSelected()) - { - this.returnCode = this.returnCode | DONT_ASK_SELECTED_MASK; - } - - if (defaultMailClientCheckBox.isSelected()) - { - this.returnCode - = this.returnCode | DEFAULT_MAIL_CLIENT_SELECTED_MASK; - } - - this.dispose(); - } - -} +package net.java.sip.communicator.plugin.addrbook.msoutlook; + +import java.awt.event.*; + +import javax.swing.*; + +import org.jitsi.service.resources.*; + +import net.java.sip.communicator.plugin.addrbook.*; +import net.java.sip.communicator.plugin.desktoputil.*; + +/** + * A dialog with warning message that Outlook is not the default mail client + * shown when the contact source is started. + * + * @author Hristo Terezov + */ +public class DefaultMailClientMessageDialog + extends MessageDialog +{ + + /** + * Serial ID. + */ + private static final long serialVersionUID = -6321186451307613417L; + + /** + * The ResourceManagementService + */ + private static ResourceManagementService resources + = AddrBookActivator.getResources(); + + /** + * Make Outlook default mail client check box. + */ + private JCheckBox defaultMailClientCheckBox = new SIPCommCheckBox( + resources + .getI18NString("plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT")); + + public static int DONT_ASK_SELECTED_MASK = 1; + + public static int DEFAULT_MAIL_CLIENT_SELECTED_MASK = 2; + + /** + * Creates an instance of DefaultMailClientMessageDialog. + */ + public DefaultMailClientMessageDialog() + { + super(null, + AddrBookActivator.getResources().getI18NString( + "plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE"), + resources.getI18NString( + "plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT", + new String[]{ + resources.getSettingsString( + "service.gui.APPLICATION_NAME")}), false); + checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS)); + checkBoxPanel.add(defaultMailClientCheckBox); + } + + + /** + * Handles the ActionEvent. Depending on the user choice sets + * the return code to the appropriate value. + * + * @param e the ActionEvent that notified us + */ + public void actionPerformed(ActionEvent e) + { + JButton button = (JButton)e.getSource(); + + if(!button.equals(okButton)) + return; + + this.returnCode = 0; + + if (doNotAskAgain.isSelected()) + { + this.returnCode = this.returnCode | DONT_ASK_SELECTED_MASK; + } + + if (defaultMailClientCheckBox.isSelected()) + { + this.returnCode + = this.returnCode | DEFAULT_MAIL_CLIENT_SELECTED_MASK; + } + + this.dispose(); + } + +} diff --git a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java index ff4a614..f27b77d 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java +++ b/src/net/java/sip/communicator/plugin/addrbook/msoutlook/MsOutlookMAPIHResultException.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,110 +15,110 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.addrbook.msoutlook; - -/** - * Represents a specific Microsoft Outlook MAPI HRESULT as an - * Exception. - * - * @author Lyubomir Marinov - */ -public class MsOutlookMAPIHResultException - extends Exception -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The HRESULT which is represented by this Exception. - */ - private final long hResult; - - /** - * Initializes a new MsOutlookMAPIHResultException instance which - * is to represent a specific HRESULT. - * - * @param hResult the HRESULT to be represented by the new instance - */ - public MsOutlookMAPIHResultException(long hResult) - { - this(hResult, toString(hResult)); - } - - /** - * Initializes a new MsOutlookMAPIHResultException instance which - * is to represent a specific HRESULT and to provide a specific - * String message. - * - * @param hResult the HRESULT to be represented by the new instance - * @param message the String message to be provided by the new - * instance - */ - public MsOutlookMAPIHResultException(long hResult, String message) - { - super(message); - - this.hResult = hResult; - } - - /** - * Initializes a new MsOutlookMAPIHResultException instance with a - * specific String message. - * - * @param message the String message to be provided by the new - * instance - */ - public MsOutlookMAPIHResultException(String message) - { - this(0, message); - } - - /** - * Gets the HRESULT which is represented by this - * Exception. - * - * @return the HRESULT which is represented by this - * Exception - */ - public long getHResult() - { - return hResult; - } - - /** - * Converts a specific HRESULT to a touch more readable - * String in accord with the rule of constructing MAPI - * HRESULT values. - * - * @param hResult the HRESULT to convert - * @return a String which represents the specified hResult - * in a touch more readable form - */ - private static String toString(long hResult) - { - if (hResult == 0) - return "S_OK"; - else - { - StringBuilder s = new StringBuilder("MAPI_"); - - s.append(((hResult & 0x80000000L) == 0) ? 'W' : 'E'); - s.append("_0x"); - s.append(Long.toHexString(hResult & 0xFFFL)); - s.append(" (" + Long.toHexString(hResult) + ")"); - return s.toString(); - } - } - - /** - * Returns the string representation for the current hResult code. - * - * @return The string representation for the current hResult code. - */ - public String getHresultString() - { - return MsOutlookMAPIHResultException.toString(this.getHResult()); - } -} +package net.java.sip.communicator.plugin.addrbook.msoutlook; + +/** + * Represents a specific Microsoft Outlook MAPI HRESULT as an + * Exception. + * + * @author Lyubomir Marinov + */ +public class MsOutlookMAPIHResultException + extends Exception +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The HRESULT which is represented by this Exception. + */ + private final long hResult; + + /** + * Initializes a new MsOutlookMAPIHResultException instance which + * is to represent a specific HRESULT. + * + * @param hResult the HRESULT to be represented by the new instance + */ + public MsOutlookMAPIHResultException(long hResult) + { + this(hResult, toString(hResult)); + } + + /** + * Initializes a new MsOutlookMAPIHResultException instance which + * is to represent a specific HRESULT and to provide a specific + * String message. + * + * @param hResult the HRESULT to be represented by the new instance + * @param message the String message to be provided by the new + * instance + */ + public MsOutlookMAPIHResultException(long hResult, String message) + { + super(message); + + this.hResult = hResult; + } + + /** + * Initializes a new MsOutlookMAPIHResultException instance with a + * specific String message. + * + * @param message the String message to be provided by the new + * instance + */ + public MsOutlookMAPIHResultException(String message) + { + this(0, message); + } + + /** + * Gets the HRESULT which is represented by this + * Exception. + * + * @return the HRESULT which is represented by this + * Exception + */ + public long getHResult() + { + return hResult; + } + + /** + * Converts a specific HRESULT to a touch more readable + * String in accord with the rule of constructing MAPI + * HRESULT values. + * + * @param hResult the HRESULT to convert + * @return a String which represents the specified hResult + * in a touch more readable form + */ + private static String toString(long hResult) + { + if (hResult == 0) + return "S_OK"; + else + { + StringBuilder s = new StringBuilder("MAPI_"); + + s.append(((hResult & 0x80000000L) == 0) ? 'W' : 'E'); + s.append("_0x"); + s.append(Long.toHexString(hResult & 0xFFFL)); + s.append(" (" + Long.toHexString(hResult) + ")"); + return s.toString(); + } + } + + /** + * Returns the string representation for the current hResult code. + * + * @return The string representation for the current hResult code. + */ + public String getHresultString() + { + return MsOutlookMAPIHResultException.toString(this.getHResult()); + } +} diff --git a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java index 086d891..a010592 100644 --- a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java +++ b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,473 +15,473 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; - -import javax.imageio.*; -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.plugin.desktoputil.plaf.*; -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.util.Logger; -import net.java.sip.communicator.util.skin.*; - -import org.jitsi.service.resources.*; -import org.jitsi.util.*; -import org.osgi.framework.*; - -/** - * The AboutWindow is containing information about the application - * name, version, license etc.. - * - * @author Yana Stamcheva - * @author Adam Netocny - * @author Lyubomir Marinov - */ -public class AboutWindow - extends JDialog - implements HyperlinkListener, - ActionListener, - ExportedWindow, - Skinnable -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The global/shared AboutWindow currently showing. - */ - private static AboutWindow aboutWindow; - - /** - * Class id key used in UIDefaults for the version label. - */ - private static final String uiClassID = - AboutWindow.class.getName() + "$VersionTextFieldUI"; - - /** - * Adds the ui class to UIDefaults. - */ - static - { - UIManager.getDefaults().put(uiClassID, - SIPCommTextFieldUI.class.getName()); - } - - private final JTextField versionLabel; - - /** - * Shows a AboutWindow creating it first if necessary. The - * shown instance is shared in order to prevent displaying multiple - * instances of one and the same AboutWindow. - */ - public static void showAboutWindow() - { - if (aboutWindow == null) - { - aboutWindow = new AboutWindow(null); - - /* - * When the global/shared AboutWindow closes, don't keep a reference - * to it and let it be garbage-collected. - */ - aboutWindow.addWindowListener(new WindowAdapter() - { - @Override - public void windowClosed(WindowEvent e) - { - if (aboutWindow == e.getWindow()) - aboutWindow = null; - } - }); - } - aboutWindow.setVisible(true); - } - - private static final int DEFAULT_TEXT_INDENT - = BrandingActivator.getResources() - .getSettingsInt("plugin.branding.ABOUT_TEXT_INDENT"); - - /** - * Creates an AboutWindow by specifying the parent frame owner. - * @param owner the parent owner - */ - public AboutWindow(Frame owner) - { - super(owner); - - ResourceManagementService resources = BrandingActivator.getResources(); - - String applicationName - = resources.getSettingsString("service.gui.APPLICATION_NAME"); - - this.setTitle( - resources.getI18NString("plugin.branding.ABOUT_WINDOW_TITLE", - new String[]{applicationName})); - - setModal(false); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - setResizable(false); - - JPanel mainPanel = new WindowBackground(); - mainPanel.setLayout(new BorderLayout()); - - JPanel textPanel = new JPanel(); - textPanel.setPreferredSize(new Dimension(470, 280)); - textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); - textPanel.setBorder(BorderFactory - .createEmptyBorder(15, 15, 15, 15)); - textPanel.setOpaque(false); - - JLabel titleLabel = null; - if (isApplicationNameShown()) - { - titleLabel = new JLabel(applicationName); - titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28)); - titleLabel.setForeground(Constants.TITLE_COLOR); - titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - } - - // Force the use of the custom text field UI in order to fix an - // incorrect rendering on Ubuntu. - versionLabel - = new JTextField(" " - + System.getProperty("sip-communicator.version")) - { - /** - * Returns the name of the L&F class that renders this component. - * - * @return the string "TreeUI" - * @see JComponent#getUIClassID - * @see UIDefaults#getUI - */ - @Override - public String getUIClassID() - { - return uiClassID; - } - }; - - versionLabel.setBorder(null); - versionLabel.setOpaque(false); - versionLabel.setEditable(false); - versionLabel.setFont(versionLabel.getFont().deriveFont(Font.BOLD, 18)); - versionLabel.setForeground(Constants.TITLE_COLOR); - versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - versionLabel.setHorizontalAlignment(JTextField.RIGHT); - - int logoAreaFontSize - = resources.getSettingsInt("plugin.branding.ABOUT_LOGO_FONT_SIZE"); - - // FIXME: the message exceeds the window length - JTextArea logoArea = - new JTextArea(resources.getI18NString( - "plugin.branding.LOGO_MESSAGE")); - logoArea.setFont( - logoArea.getFont().deriveFont(Font.BOLD, logoAreaFontSize)); - logoArea.setForeground(Constants.TITLE_COLOR); - logoArea.setOpaque(false); - logoArea.setLineWrap(true); - logoArea.setWrapStyleWord(true); - logoArea.setEditable(false); - logoArea.setPreferredSize(new Dimension(100, 20)); - logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - logoArea.setBorder(BorderFactory - .createEmptyBorder(30, DEFAULT_TEXT_INDENT, 0, 0)); - - StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); - rightsArea.setContentType("text/html"); - - rightsArea.appendToEnd(resources.getI18NString( - "plugin.branding.COPYRIGHT", - new String[] - { Constants.TEXT_COLOR })); - - rightsArea.setPreferredSize(new Dimension(50, 20)); - rightsArea - .setBorder(BorderFactory - .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); - rightsArea.setOpaque(false); - rightsArea.setEditable(false); - rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - rightsArea.addHyperlinkListener(this); - - StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); - licenseArea.setContentType("text/html"); - licenseArea.appendToEnd(resources. - getI18NString("plugin.branding.LICENSE", - new String[]{Constants.TEXT_COLOR})); - - licenseArea.setPreferredSize(new Dimension(50, 20)); - licenseArea.setBorder( - BorderFactory.createEmptyBorder( - resources.getSettingsInt("plugin.branding.ABOUT_PARAGRAPH_GAP"), - DEFAULT_TEXT_INDENT, - 0, 0)); - licenseArea.setOpaque(false); - licenseArea.setEditable(false); - licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - licenseArea.addHyperlinkListener(this); - - if (titleLabel != null) - textPanel.add(titleLabel); - - textPanel.add(versionLabel); - textPanel.add(logoArea); - textPanel.add(rightsArea); - textPanel.add(licenseArea); - - JButton okButton - = new JButton(resources.getI18NString("service.gui.OK")); - - this.getRootPane().setDefaultButton(okButton); - - okButton.setMnemonic(resources.getI18nMnemonic("service.gui.OK")); - okButton.addActionListener(this); - - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonPanel.add(okButton); - buttonPanel.setOpaque(false); - - mainPanel.add(textPanel, BorderLayout.CENTER); - mainPanel.add(buttonPanel, BorderLayout.SOUTH); - - this.getContentPane().add(mainPanel); - - this.pack(); - - setLocationRelativeTo(getParent()); - - this.getRootPane().getActionMap().put("close", new CloseAction()); - - InputMap imap = this.getRootPane().getInputMap( - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); - - if(OSUtils.IS_MAC) - { - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), - "close"); - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), - "close"); - } - - WindowUtils.addWindow(this); - } - - /** - * Reloads text field UI. - */ - public void loadSkin() - { - if(versionLabel.getUI() instanceof Skinnable) - ((Skinnable)versionLabel.getUI()).loadSkin(); - } - - /** - * Constructs the window background in order to have a background image. - */ - private static class WindowBackground - extends JPanel - implements Skinnable - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private static final Logger logger - = Logger.getLogger(WindowBackground.class); - - private Image bgImage = null; - - public WindowBackground() - { - loadSkin(); - } - - /** - * Reloads resources for this component. - */ - public void loadSkin() - { - try - { - bgImage = ImageIO.read(BrandingActivator.getResources(). - getImageURL("plugin.branding.ABOUT_WINDOW_BACKGROUND")); - - this.setPreferredSize(new Dimension(bgImage.getWidth(this), - bgImage.getHeight(this))); - } - catch (IOException e) - { - logger.error("Error cannot obtain background image", e); - bgImage = null; - } - } - - @Override - protected void paintComponent(Graphics g) - { - super.paintComponent(g); - - g = g.create(); - try - { - AntialiasingManager.activateAntialiasing(g); - - int bgImageWidth = bgImage.getWidth(null); - int bgImageHeight = bgImage.getHeight(null); - boolean bgImageHasBeenDrawn = false; - - if ((bgImageWidth != -1) && (bgImageHeight != -1)) - { - int width = getWidth(); - int height = getHeight(); - - if ((bgImageWidth < width) || (bgImageHeight < height)) - { - g.drawImage(bgImage, 0, 0, width, height, null); - bgImageHasBeenDrawn = true; - } - } - - if (!bgImageHasBeenDrawn) - g.drawImage(bgImage, 0, 0, null); - } - finally - { - g.dispose(); - } - } - } - - /** - * Opens a browser when the link has been activated (clicked). - * @param e the HyperlinkEvent that notified us - */ - public void hyperlinkUpdate(HyperlinkEvent e) - { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) - { - String href = e.getDescription(); - ServiceReference serviceReference = BrandingActivator - .getBundleContext().getServiceReference( - BrowserLauncherService.class.getName()); - - if (serviceReference != null) - { - BrowserLauncherService browserLauncherService - = (BrowserLauncherService) BrandingActivator - .getBundleContext().getService(serviceReference); - - browserLauncherService.openURL(href); - } - } - } - - /** - * Indicates that the ok button has been pressed. Closes the window. - * @param e the ActionEvent that notified us - */ - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - - /** - * Implements the ExportedWindow.getIdentifier() method. - * @return the identifier of this exported window - */ - public WindowID getIdentifier() - { - return ExportedWindow.ABOUT_WINDOW; - } - - /** - * This dialog could not be minimized. - */ - public void minimize() - { - } - - /** - * This dialog could not be maximized. - */ - public void maximize() - { - } - - /** - * Implements the ExportedWindow.bringToFront() method. Brings - * this window to front. - */ - public void bringToFront() - { - this.toFront(); - } - - /** - * The source of the window - * @return the source of the window - */ - public Object getSource() - { - return this; - } - - /** - * Implementation of {@link ExportedWindow#setParams(Object[])}. - */ - public void setParams(Object[] windowParams) {} - - /** - * The action invoked when user presses Escape key. - */ - private class CloseAction extends UIAction - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - } - - /** - * Indicates if the application name should be shown. - * - * @return true if the application name should be shown, - * false - otherwise - */ - private boolean isApplicationNameShown() - { - String showApplicationNameProp - = BrandingActivator.getResources().getSettingsString( - "plugin.branding.IS_APPLICATION_NAME_SHOWN"); - - if (showApplicationNameProp != null - && showApplicationNameProp.length() > 0) - { - return Boolean.parseBoolean(showApplicationNameProp); - } - - return true; - } -} +package net.java.sip.communicator.plugin.branding; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; + +import javax.imageio.*; +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.desktoputil.plaf.*; +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.Logger; +import net.java.sip.communicator.util.skin.*; + +import org.jitsi.service.resources.*; +import org.jitsi.util.*; +import org.osgi.framework.*; + +/** + * The AboutWindow is containing information about the application + * name, version, license etc.. + * + * @author Yana Stamcheva + * @author Adam Netocny + * @author Lyubomir Marinov + */ +public class AboutWindow + extends JDialog + implements HyperlinkListener, + ActionListener, + ExportedWindow, + Skinnable +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The global/shared AboutWindow currently showing. + */ + private static AboutWindow aboutWindow; + + /** + * Class id key used in UIDefaults for the version label. + */ + private static final String uiClassID = + AboutWindow.class.getName() + "$VersionTextFieldUI"; + + /** + * Adds the ui class to UIDefaults. + */ + static + { + UIManager.getDefaults().put(uiClassID, + SIPCommTextFieldUI.class.getName()); + } + + private final JTextField versionLabel; + + /** + * Shows a AboutWindow creating it first if necessary. The + * shown instance is shared in order to prevent displaying multiple + * instances of one and the same AboutWindow. + */ + public static void showAboutWindow() + { + if (aboutWindow == null) + { + aboutWindow = new AboutWindow(null); + + /* + * When the global/shared AboutWindow closes, don't keep a reference + * to it and let it be garbage-collected. + */ + aboutWindow.addWindowListener(new WindowAdapter() + { + @Override + public void windowClosed(WindowEvent e) + { + if (aboutWindow == e.getWindow()) + aboutWindow = null; + } + }); + } + aboutWindow.setVisible(true); + } + + private static final int DEFAULT_TEXT_INDENT + = BrandingActivator.getResources() + .getSettingsInt("plugin.branding.ABOUT_TEXT_INDENT"); + + /** + * Creates an AboutWindow by specifying the parent frame owner. + * @param owner the parent owner + */ + public AboutWindow(Frame owner) + { + super(owner); + + ResourceManagementService resources = BrandingActivator.getResources(); + + String applicationName + = resources.getSettingsString("service.gui.APPLICATION_NAME"); + + this.setTitle( + resources.getI18NString("plugin.branding.ABOUT_WINDOW_TITLE", + new String[]{applicationName})); + + setModal(false); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setResizable(false); + + JPanel mainPanel = new WindowBackground(); + mainPanel.setLayout(new BorderLayout()); + + JPanel textPanel = new JPanel(); + textPanel.setPreferredSize(new Dimension(470, 280)); + textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); + textPanel.setBorder(BorderFactory + .createEmptyBorder(15, 15, 15, 15)); + textPanel.setOpaque(false); + + JLabel titleLabel = null; + if (isApplicationNameShown()) + { + titleLabel = new JLabel(applicationName); + titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28)); + titleLabel.setForeground(Constants.TITLE_COLOR); + titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); + } + + // Force the use of the custom text field UI in order to fix an + // incorrect rendering on Ubuntu. + versionLabel + = new JTextField(" " + + System.getProperty("sip-communicator.version")) + { + /** + * Returns the name of the L&F class that renders this component. + * + * @return the string "TreeUI" + * @see JComponent#getUIClassID + * @see UIDefaults#getUI + */ + @Override + public String getUIClassID() + { + return uiClassID; + } + }; + + versionLabel.setBorder(null); + versionLabel.setOpaque(false); + versionLabel.setEditable(false); + versionLabel.setFont(versionLabel.getFont().deriveFont(Font.BOLD, 18)); + versionLabel.setForeground(Constants.TITLE_COLOR); + versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); + versionLabel.setHorizontalAlignment(JTextField.RIGHT); + + int logoAreaFontSize + = resources.getSettingsInt("plugin.branding.ABOUT_LOGO_FONT_SIZE"); + + // FIXME: the message exceeds the window length + JTextArea logoArea = + new JTextArea(resources.getI18NString( + "plugin.branding.LOGO_MESSAGE")); + logoArea.setFont( + logoArea.getFont().deriveFont(Font.BOLD, logoAreaFontSize)); + logoArea.setForeground(Constants.TITLE_COLOR); + logoArea.setOpaque(false); + logoArea.setLineWrap(true); + logoArea.setWrapStyleWord(true); + logoArea.setEditable(false); + logoArea.setPreferredSize(new Dimension(100, 20)); + logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + logoArea.setBorder(BorderFactory + .createEmptyBorder(30, DEFAULT_TEXT_INDENT, 0, 0)); + + StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); + rightsArea.setContentType("text/html"); + + rightsArea.appendToEnd(resources.getI18NString( + "plugin.branding.COPYRIGHT", + new String[] + { Constants.TEXT_COLOR })); + + rightsArea.setPreferredSize(new Dimension(50, 20)); + rightsArea + .setBorder(BorderFactory + .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); + rightsArea.setOpaque(false); + rightsArea.setEditable(false); + rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + rightsArea.addHyperlinkListener(this); + + StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); + licenseArea.setContentType("text/html"); + licenseArea.appendToEnd(resources. + getI18NString("plugin.branding.LICENSE", + new String[]{Constants.TEXT_COLOR})); + + licenseArea.setPreferredSize(new Dimension(50, 20)); + licenseArea.setBorder( + BorderFactory.createEmptyBorder( + resources.getSettingsInt("plugin.branding.ABOUT_PARAGRAPH_GAP"), + DEFAULT_TEXT_INDENT, + 0, 0)); + licenseArea.setOpaque(false); + licenseArea.setEditable(false); + licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); + licenseArea.addHyperlinkListener(this); + + if (titleLabel != null) + textPanel.add(titleLabel); + + textPanel.add(versionLabel); + textPanel.add(logoArea); + textPanel.add(rightsArea); + textPanel.add(licenseArea); + + JButton okButton + = new JButton(resources.getI18NString("service.gui.OK")); + + this.getRootPane().setDefaultButton(okButton); + + okButton.setMnemonic(resources.getI18nMnemonic("service.gui.OK")); + okButton.addActionListener(this); + + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonPanel.add(okButton); + buttonPanel.setOpaque(false); + + mainPanel.add(textPanel, BorderLayout.CENTER); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + + this.getContentPane().add(mainPanel); + + this.pack(); + + setLocationRelativeTo(getParent()); + + this.getRootPane().getActionMap().put("close", new CloseAction()); + + InputMap imap = this.getRootPane().getInputMap( + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); + + if(OSUtils.IS_MAC) + { + imap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), + "close"); + imap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), + "close"); + } + + WindowUtils.addWindow(this); + } + + /** + * Reloads text field UI. + */ + public void loadSkin() + { + if(versionLabel.getUI() instanceof Skinnable) + ((Skinnable)versionLabel.getUI()).loadSkin(); + } + + /** + * Constructs the window background in order to have a background image. + */ + private static class WindowBackground + extends JPanel + implements Skinnable + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private static final Logger logger + = Logger.getLogger(WindowBackground.class); + + private Image bgImage = null; + + public WindowBackground() + { + loadSkin(); + } + + /** + * Reloads resources for this component. + */ + public void loadSkin() + { + try + { + bgImage = ImageIO.read(BrandingActivator.getResources(). + getImageURL("plugin.branding.ABOUT_WINDOW_BACKGROUND")); + + this.setPreferredSize(new Dimension(bgImage.getWidth(this), + bgImage.getHeight(this))); + } + catch (IOException e) + { + logger.error("Error cannot obtain background image", e); + bgImage = null; + } + } + + @Override + protected void paintComponent(Graphics g) + { + super.paintComponent(g); + + g = g.create(); + try + { + AntialiasingManager.activateAntialiasing(g); + + int bgImageWidth = bgImage.getWidth(null); + int bgImageHeight = bgImage.getHeight(null); + boolean bgImageHasBeenDrawn = false; + + if ((bgImageWidth != -1) && (bgImageHeight != -1)) + { + int width = getWidth(); + int height = getHeight(); + + if ((bgImageWidth < width) || (bgImageHeight < height)) + { + g.drawImage(bgImage, 0, 0, width, height, null); + bgImageHasBeenDrawn = true; + } + } + + if (!bgImageHasBeenDrawn) + g.drawImage(bgImage, 0, 0, null); + } + finally + { + g.dispose(); + } + } + } + + /** + * Opens a browser when the link has been activated (clicked). + * @param e the HyperlinkEvent that notified us + */ + public void hyperlinkUpdate(HyperlinkEvent e) + { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + { + String href = e.getDescription(); + ServiceReference serviceReference = BrandingActivator + .getBundleContext().getServiceReference( + BrowserLauncherService.class.getName()); + + if (serviceReference != null) + { + BrowserLauncherService browserLauncherService + = (BrowserLauncherService) BrandingActivator + .getBundleContext().getService(serviceReference); + + browserLauncherService.openURL(href); + } + } + } + + /** + * Indicates that the ok button has been pressed. Closes the window. + * @param e the ActionEvent that notified us + */ + public void actionPerformed(ActionEvent e) + { + setVisible(false); + dispose(); + } + + /** + * Implements the ExportedWindow.getIdentifier() method. + * @return the identifier of this exported window + */ + public WindowID getIdentifier() + { + return ExportedWindow.ABOUT_WINDOW; + } + + /** + * This dialog could not be minimized. + */ + public void minimize() + { + } + + /** + * This dialog could not be maximized. + */ + public void maximize() + { + } + + /** + * Implements the ExportedWindow.bringToFront() method. Brings + * this window to front. + */ + public void bringToFront() + { + this.toFront(); + } + + /** + * The source of the window + * @return the source of the window + */ + public Object getSource() + { + return this; + } + + /** + * Implementation of {@link ExportedWindow#setParams(Object[])}. + */ + public void setParams(Object[] windowParams) {} + + /** + * The action invoked when user presses Escape key. + */ + private class CloseAction extends UIAction + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + public void actionPerformed(ActionEvent e) + { + setVisible(false); + dispose(); + } + } + + /** + * Indicates if the application name should be shown. + * + * @return true if the application name should be shown, + * false - otherwise + */ + private boolean isApplicationNameShown() + { + String showApplicationNameProp + = BrandingActivator.getResources().getSettingsString( + "plugin.branding.IS_APPLICATION_NAME_SHOWN"); + + if (showApplicationNameProp != null + && showApplicationNameProp.length() > 0) + { + return Boolean.parseBoolean(showApplicationNameProp); + } + + return true; + } +} diff --git a/src/net/java/sip/communicator/plugin/branding/AboutWindowPluginComponent.java b/src/net/java/sip/communicator/plugin/branding/AboutWindowPluginComponent.java index 333781d..eb2d61a 100644 --- a/src/net/java/sip/communicator/plugin/branding/AboutWindowPluginComponent.java +++ b/src/net/java/sip/communicator/plugin/branding/AboutWindowPluginComponent.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,89 +15,89 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.gui.*; - -/** - * Implements an About menu item for the Help menu of the application in the - * form of a PluginComponent. - * - * @author Lyubomir Marinov - */ -public class AboutWindowPluginComponent - extends AbstractPluginComponent -{ - - /** - * Invokes the default action associated with Help > About regardless of the - * specifics of its visual representation. - */ - public static void actionPerformed() - { - AboutWindow.showAboutWindow(); - } - - private JMenuItem aboutMenuItem; - - /** - * Constructor. - * - * @param container parent container - */ - public AboutWindowPluginComponent(Container container, - PluginComponentFactory parentFactory) - { - super(container, parentFactory); - } - - public Object getComponent() - { - if (aboutMenuItem == null) - { - aboutMenuItem = new JMenuItem(getName()); - aboutMenuItem - .setMnemonic( - BrandingActivator - .getResources() - .getI18nMnemonic( - "plugin.branding.ABOUT_MENU_ENTRY")); - - aboutMenuItem.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - AboutWindowPluginComponent.actionPerformed(); - } - }); - } - return aboutMenuItem; - } - - public String getName() - { - return - BrandingActivator - .getResources() - .getI18NString("plugin.branding.ABOUT_MENU_ENTRY"); - } - - /** - * Implements {@link PluginComponent#getPositionIndex()}. Returns - * Integer#MAX_VALUE in order to indicate that the About menu item - * in the Help menu is conventionally displayed at the very bottom. - * - * @return Integer#MAX_VALUE in order to indicate that the About - * menu item in the Help menu is conventionally displayed at the very bottom - * @see AbstractPluginComponent#getPositionIndex() - */ - @Override - public int getPositionIndex() - { - return Integer.MAX_VALUE; - } -} +package net.java.sip.communicator.plugin.branding; + +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.gui.*; + +/** + * Implements an About menu item for the Help menu of the application in the + * form of a PluginComponent. + * + * @author Lyubomir Marinov + */ +public class AboutWindowPluginComponent + extends AbstractPluginComponent +{ + + /** + * Invokes the default action associated with Help > About regardless of the + * specifics of its visual representation. + */ + public static void actionPerformed() + { + AboutWindow.showAboutWindow(); + } + + private JMenuItem aboutMenuItem; + + /** + * Constructor. + * + * @param container parent container + */ + public AboutWindowPluginComponent(Container container, + PluginComponentFactory parentFactory) + { + super(container, parentFactory); + } + + public Object getComponent() + { + if (aboutMenuItem == null) + { + aboutMenuItem = new JMenuItem(getName()); + aboutMenuItem + .setMnemonic( + BrandingActivator + .getResources() + .getI18nMnemonic( + "plugin.branding.ABOUT_MENU_ENTRY")); + + aboutMenuItem.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + AboutWindowPluginComponent.actionPerformed(); + } + }); + } + return aboutMenuItem; + } + + public String getName() + { + return + BrandingActivator + .getResources() + .getI18NString("plugin.branding.ABOUT_MENU_ENTRY"); + } + + /** + * Implements {@link PluginComponent#getPositionIndex()}. Returns + * Integer#MAX_VALUE in order to indicate that the About menu item + * in the Help menu is conventionally displayed at the very bottom. + * + * @return Integer#MAX_VALUE in order to indicate that the About + * menu item in the Help menu is conventionally displayed at the very bottom + * @see AbstractPluginComponent#getPositionIndex() + */ + @Override + public int getPositionIndex() + { + return Integer.MAX_VALUE; + } +} diff --git a/src/net/java/sip/communicator/plugin/branding/Constants.java b/src/net/java/sip/communicator/plugin/branding/Constants.java index 9d15df4..b098e4d 100644 --- a/src/net/java/sip/communicator/plugin/branding/Constants.java +++ b/src/net/java/sip/communicator/plugin/branding/Constants.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,65 +15,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.*; -import java.io.*; - -import javax.swing.text.html.*; - -/** - * All look and feel related constants are stored here. - * - * @author Yana Stamcheva - */ -public class Constants -{ - /* - * ====================================================================== - * -------------------- FONTS AND COLOR CONSTANTS ------------------------ - * ====================================================================== - */ - - /** - * Dark blue color used in the about window and the splash screen. - */ - public static final Color TITLE_COLOR - = new Color(BrandingActivator.getResources() - .getColor("service.gui.SPLASH_SCREEN_TITLE_COLOR")); - - /** - * Text color used in the about window and the splash screen. - */ - public static final String TEXT_COLOR - = BrandingActivator.getResources() - .getColorString("service.gui.SPLASH_SCREEN_TEXT_COLOR"); - - - /* - * ====================================================================== - * --------------------------- FONT CONSTANTS --------------------------- - * ====================================================================== - */ - - /** - * Temporary method to load the css style used in the chat window. - * - * @param style - */ - public static void loadSimpleStyle(StyleSheet style) - { - InputStream is = BrandingActivator.getResources(). - getSettingsInputStream("service.gui.HTML_TEXT_STYLE"); - - Reader r = new BufferedReader(new InputStreamReader(is)); - try - { - style.loadRules(r, null); - r.close(); - } - catch (IOException e) - { - } - } -} +package net.java.sip.communicator.plugin.branding; + +import java.awt.*; +import java.io.*; + +import javax.swing.text.html.*; + +/** + * All look and feel related constants are stored here. + * + * @author Yana Stamcheva + */ +public class Constants +{ + /* + * ====================================================================== + * -------------------- FONTS AND COLOR CONSTANTS ------------------------ + * ====================================================================== + */ + + /** + * Dark blue color used in the about window and the splash screen. + */ + public static final Color TITLE_COLOR + = new Color(BrandingActivator.getResources() + .getColor("service.gui.SPLASH_SCREEN_TITLE_COLOR")); + + /** + * Text color used in the about window and the splash screen. + */ + public static final String TEXT_COLOR + = BrandingActivator.getResources() + .getColorString("service.gui.SPLASH_SCREEN_TEXT_COLOR"); + + + /* + * ====================================================================== + * --------------------------- FONT CONSTANTS --------------------------- + * ====================================================================== + */ + + /** + * Temporary method to load the css style used in the chat window. + * + * @param style + */ + public static void loadSimpleStyle(StyleSheet style) + { + InputStream is = BrandingActivator.getResources(). + getSettingsInputStream("service.gui.HTML_TEXT_STYLE"); + + Reader r = new BufferedReader(new InputStreamReader(is)); + try + { + style.loadRules(r, null); + r.close(); + } + catch (IOException e) + { + } + } +} diff --git a/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java b/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java index 0ca6a89..23c9880 100644 --- a/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java +++ b/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,189 +15,189 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.browserlauncher.*; - -import org.jitsi.service.resources.*; -import org.jitsi.util.*; -import org.osgi.framework.*; - -/** - * The JitsiWarningWindow. - * - * @author Yana Stamcheva - */ -public class JitsiWarningWindow - extends SIPCommDialog -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates an JitsiWarningWindow by specifying the parent frame - * owner. - * @param owner the parent owner - */ - public JitsiWarningWindow(Frame owner) - { - super(owner, false); - - ResourceManagementService resources = BrandingActivator.getResources(); - - this.setTitle( - resources.getI18NString("service.gui.UPDATE") - + " " + resources.getSettingsString( - "service.gui.APPLICATION_NAME")); - - setModal(false); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - - StyledHTMLEditorPane textArea = new StyledHTMLEditorPane(); - textArea.setContentType("text/html"); - textArea.setText(resources.getI18NString("service.gui.JITSI_WARNING")); - textArea.setOpaque(false); - textArea.setEditable(false); - - JLabel titleLabel = new JLabel( - resources.getI18NString("service.gui.JITSI_WARNING_TITLE")); - titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 14f)); - titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); - titleLabel.setMaximumSize(new Dimension(400, 50)); - - JPanel textPanel = new TransparentPanel(); - textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); - - textPanel.add(titleLabel); - textPanel.add(Box.createRigidArea(new Dimension(20, 20))); - textPanel.add(textArea); - - JButton downloadButton = new JButton( - resources.getI18NString("service.gui.DOWNLOAD_NOW")); - JButton remindButton = new JButton( - resources.getI18NString("service.gui.REMIND_ME_LATER")); - - this.getRootPane().setDefaultButton(downloadButton); - - downloadButton.setMnemonic( - resources.getI18nMnemonic("service.gui.DOWNLOAD_NOW")); - downloadButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - openURL(getDownloadLink()); - dispose(); - } - }); - remindButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - dispose(); - } - }); - - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonPanel.add(remindButton); - buttonPanel.add(downloadButton); - buttonPanel.setOpaque(false); - - JPanel mainPanel = new TransparentPanel(new BorderLayout(10, 10)); - mainPanel.add(new JLabel(resources.getImage( - "service.gui.SIP_COMMUNICATOR_LOGO_128x128")), BorderLayout.WEST); - mainPanel.add(textPanel, BorderLayout.CENTER); - mainPanel.add(buttonPanel, BorderLayout.SOUTH); - mainPanel.setPreferredSize(new Dimension(500, 200)); - mainPanel.setBorder( - BorderFactory.createEmptyBorder(20, 20, 20, 20)); - - getContentPane().add(mainPanel); - - this.pack(); - this.setResizable(false); - - setLocationRelativeTo(getParent()); - - this.getRootPane().getActionMap().put("close", new CloseAction()); - - InputMap imap = this.getRootPane().getInputMap( - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); - - if(OSUtils.IS_MAC) - { - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), - "close"); - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), - "close"); - } - } - - /** - * The action invoked when user presses Escape key. - */ - private class CloseAction extends UIAction - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - } - - /** - * Opens the given url in a new browser window. - * @param url the url to open - */ - private void openURL(String url) - { - ServiceReference serviceReference = BrandingActivator - .getBundleContext().getServiceReference( - BrowserLauncherService.class.getName()); - - if (serviceReference != null) - { - BrowserLauncherService browserLauncherService - = (BrowserLauncherService) BrandingActivator - .getBundleContext().getService( - serviceReference); - - browserLauncherService.openURL(url); - } - } - - /** - * Indicates if the application name should be shown. - * - * @return true if the application name should be shown, - * false - otherwise - */ - private String getDownloadLink() - { - if (OSUtils.IS_WINDOWS) - return "http://download.jitsi.org/jitsi/windows/"; - else if (OSUtils.IS_MAC) - return "http://download.jitsi.org/jitsi/macosx/"; - - return "http://download.jitsi.org"; - } - - @Override - protected void close(boolean escaped) {} -} +package net.java.sip.communicator.plugin.branding; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.browserlauncher.*; + +import org.jitsi.service.resources.*; +import org.jitsi.util.*; +import org.osgi.framework.*; + +/** + * The JitsiWarningWindow. + * + * @author Yana Stamcheva + */ +public class JitsiWarningWindow + extends SIPCommDialog +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Creates an JitsiWarningWindow by specifying the parent frame + * owner. + * @param owner the parent owner + */ + public JitsiWarningWindow(Frame owner) + { + super(owner, false); + + ResourceManagementService resources = BrandingActivator.getResources(); + + this.setTitle( + resources.getI18NString("service.gui.UPDATE") + + " " + resources.getSettingsString( + "service.gui.APPLICATION_NAME")); + + setModal(false); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + StyledHTMLEditorPane textArea = new StyledHTMLEditorPane(); + textArea.setContentType("text/html"); + textArea.setText(resources.getI18NString("service.gui.JITSI_WARNING")); + textArea.setOpaque(false); + textArea.setEditable(false); + + JLabel titleLabel = new JLabel( + resources.getI18NString("service.gui.JITSI_WARNING_TITLE")); + titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 14f)); + titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + titleLabel.setMaximumSize(new Dimension(400, 50)); + + JPanel textPanel = new TransparentPanel(); + textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); + + textPanel.add(titleLabel); + textPanel.add(Box.createRigidArea(new Dimension(20, 20))); + textPanel.add(textArea); + + JButton downloadButton = new JButton( + resources.getI18NString("service.gui.DOWNLOAD_NOW")); + JButton remindButton = new JButton( + resources.getI18NString("service.gui.REMIND_ME_LATER")); + + this.getRootPane().setDefaultButton(downloadButton); + + downloadButton.setMnemonic( + resources.getI18nMnemonic("service.gui.DOWNLOAD_NOW")); + downloadButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + openURL(getDownloadLink()); + dispose(); + } + }); + remindButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + dispose(); + } + }); + + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonPanel.add(remindButton); + buttonPanel.add(downloadButton); + buttonPanel.setOpaque(false); + + JPanel mainPanel = new TransparentPanel(new BorderLayout(10, 10)); + mainPanel.add(new JLabel(resources.getImage( + "service.gui.SIP_COMMUNICATOR_LOGO_128x128")), BorderLayout.WEST); + mainPanel.add(textPanel, BorderLayout.CENTER); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + mainPanel.setPreferredSize(new Dimension(500, 200)); + mainPanel.setBorder( + BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + getContentPane().add(mainPanel); + + this.pack(); + this.setResizable(false); + + setLocationRelativeTo(getParent()); + + this.getRootPane().getActionMap().put("close", new CloseAction()); + + InputMap imap = this.getRootPane().getInputMap( + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); + + if(OSUtils.IS_MAC) + { + imap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), + "close"); + imap.put( + KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), + "close"); + } + } + + /** + * The action invoked when user presses Escape key. + */ + private class CloseAction extends UIAction + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + public void actionPerformed(ActionEvent e) + { + setVisible(false); + dispose(); + } + } + + /** + * Opens the given url in a new browser window. + * @param url the url to open + */ + private void openURL(String url) + { + ServiceReference serviceReference = BrandingActivator + .getBundleContext().getServiceReference( + BrowserLauncherService.class.getName()); + + if (serviceReference != null) + { + BrowserLauncherService browserLauncherService + = (BrowserLauncherService) BrandingActivator + .getBundleContext().getService( + serviceReference); + + browserLauncherService.openURL(url); + } + } + + /** + * Indicates if the application name should be shown. + * + * @return true if the application name should be shown, + * false - otherwise + */ + private String getDownloadLink() + { + if (OSUtils.IS_WINDOWS) + return "http://download.jitsi.org/jitsi/windows/"; + else if (OSUtils.IS_MAC) + return "http://download.jitsi.org/jitsi/macosx/"; + + return "http://download.jitsi.org"; + } + + @Override + protected void close(boolean escaped) {} +} diff --git a/src/net/java/sip/communicator/plugin/branding/MacOSXAboutRegistration.java b/src/net/java/sip/communicator/plugin/branding/MacOSXAboutRegistration.java index 22ce126..0648e4b 100644 --- a/src/net/java/sip/communicator/plugin/branding/MacOSXAboutRegistration.java +++ b/src/net/java/sip/communicator/plugin/branding/MacOSXAboutRegistration.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,34 +15,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import com.apple.eawt.*; - -/** - * @author Lubomir Marinov - */ -public final class MacOSXAboutRegistration -{ - /** - * Show the about dialog on Mac OS X. - * - * @return true if the Mac OS X application is not null - */ - public static boolean run() - { - Application application = Application.getApplication(); - if (application != null) - { - application.setAboutHandler(new AboutHandler() - { - public void handleAbout(AppEvent.AboutEvent aboutEvent) - { - AboutWindowPluginComponent.actionPerformed(); - } - }); - return true; - } - return false; - } -} +package net.java.sip.communicator.plugin.branding; + +import com.apple.eawt.*; + +/** + * @author Lubomir Marinov + */ +public final class MacOSXAboutRegistration +{ + /** + * Show the about dialog on Mac OS X. + * + * @return true if the Mac OS X application is not null + */ + public static boolean run() + { + Application application = Application.getApplication(); + if (application != null) + { + application.setAboutHandler(new AboutHandler() + { + public void handleAbout(AppEvent.AboutEvent aboutEvent) + { + AboutWindowPluginComponent.actionPerformed(); + } + }); + return true; + } + return false; + } +} diff --git a/src/net/java/sip/communicator/plugin/branding/StyledHTMLEditorPane.java b/src/net/java/sip/communicator/plugin/branding/StyledHTMLEditorPane.java index 7eb02bc..d67050e 100644 --- a/src/net/java/sip/communicator/plugin/branding/StyledHTMLEditorPane.java +++ b/src/net/java/sip/communicator/plugin/branding/StyledHTMLEditorPane.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,64 +15,64 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.branding; - -import java.io.*; - -import javax.swing.*; -import javax.swing.text.*; -import javax.swing.text.html.*; - -import net.java.sip.communicator.util.*; - -public class StyledHTMLEditorPane - extends JEditorPane -{ - private final Logger logger = Logger.getLogger(StyledHTMLEditorPane.class); - - private final HTMLDocument document; - - public StyledHTMLEditorPane() - { - this.setContentType("text/html"); - - this.document - = (HTMLDocument) this.getDocument(); - - this.setDocument(document); - - Constants.loadSimpleStyle(document.getStyleSheet()); - } - - public void appendToEnd(String text) - { - Element root = document.getDefaultRootElement(); - try - { - document.insertAfterEnd(root - .getElement(root.getElementCount() - 1), text); - } - catch (BadLocationException e) - { - logger.error("Insert in the HTMLDocument failed.", e); - } - catch (IOException e) - { - logger.error("Insert in the HTMLDocument failed.", e); - } - } - - public void insertAfterStart(String text) - { - Element root = this.document.getDefaultRootElement(); - - try { - this.document.insertBeforeStart(root - .getElement(0), text); - } catch (BadLocationException e) { - logger.error("Insert in the HTMLDocument failed.", e); - } catch (IOException e) { - logger.error("Insert in the HTMLDocument failed.", e); - } - } -} +package net.java.sip.communicator.plugin.branding; + +import java.io.*; + +import javax.swing.*; +import javax.swing.text.*; +import javax.swing.text.html.*; + +import net.java.sip.communicator.util.*; + +public class StyledHTMLEditorPane + extends JEditorPane +{ + private final Logger logger = Logger.getLogger(StyledHTMLEditorPane.class); + + private final HTMLDocument document; + + public StyledHTMLEditorPane() + { + this.setContentType("text/html"); + + this.document + = (HTMLDocument) this.getDocument(); + + this.setDocument(document); + + Constants.loadSimpleStyle(document.getStyleSheet()); + } + + public void appendToEnd(String text) + { + Element root = document.getDefaultRootElement(); + try + { + document.insertAfterEnd(root + .getElement(root.getElementCount() - 1), text); + } + catch (BadLocationException e) + { + logger.error("Insert in the HTMLDocument failed.", e); + } + catch (IOException e) + { + logger.error("Insert in the HTMLDocument failed.", e); + } + } + + public void insertAfterStart(String text) + { + Element root = this.document.getDefaultRootElement(); + + try { + this.document.insertBeforeStart(root + .getElement(0), text); + } catch (BadLocationException e) { + logger.error("Insert in the HTMLDocument failed.", e); + } catch (IOException e) { + logger.error("Insert in the HTMLDocument failed.", e); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/certconfig/CertConfigEntryDialog.java b/src/net/java/sip/communicator/plugin/certconfig/CertConfigEntryDialog.java index 278af62..b729b35 100644 --- a/src/net/java/sip/communicator/plugin/certconfig/CertConfigEntryDialog.java +++ b/src/net/java/sip/communicator/plugin/certconfig/CertConfigEntryDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,573 +15,573 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.certconfig; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.lang.reflect.*; -import java.security.*; -import java.security.cert.*; -import java.util.*; - -import javax.security.auth.callback.*; -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.certificate.*; -import net.java.sip.communicator.util.Logger; - -import org.jitsi.service.resources.*; -import org.jitsi.util.*; - -/** - * Dialog window to add/edit client certificate configuration entries. - * - * @author Ingo Bauersachs - */ -public class CertConfigEntryDialog - extends SIPCommDialog - implements ActionListener, ItemListener, ChangeListener -{ - // ------------------------------------------------------------------------ - // Fields and services - // ------------------------------------------------------------------------ - private static final long serialVersionUID = 8361336563239745007L; - private static final Logger logger = Logger - .getLogger(CertConfigEntryDialog.class); - private ResourceManagementService R = CertConfigActivator.R; - private CertificateService cs = CertConfigActivator.getCertService(); - private CertificateConfigEntry entry; - private boolean success = false; - - // ------------------------------------------------------------------------ - // GUI members - // ------------------------------------------------------------------------ - private JButton cmdOk; - private JButton cmdCancel; - private JButton cmdBrowse; - private JTextField txtDisplayName; - private JTextField txtKeyStore; - private JComboBox cboKeyStoreTypes; - private JCheckBox chkSavePassword; - private JPasswordField txtKeyStorePassword; - private JComboBox cboAlias; - private JButton cmdShowCert; - private KeyStore keyStore; - - // ------------------------------------------------------------------------ - // Initialization - // ------------------------------------------------------------------------ - /** - * Constructor. - * - * @param e the CertificateConfigEntry - */ - public CertConfigEntryDialog(CertificateConfigEntry e) - { - super(false); - entry = e; - initComponents(); - setPreferredSize(new Dimension(650, 270)); - - try - { - if(entry.getKeyStore() != null) - { - txtKeyStorePassword.setText(entry.getKeyStorePassword()); - chkSavePassword.setSelected(entry.isSavePassword()); - cboKeyStoreTypes.setEnabled(true); - cboKeyStoreTypes.setSelectedItem(entry.getKeyStoreType()); - if(keyStore == null) - keyStore = loadKeyStore(); - cboAlias.setEnabled(true); - loadAliases(); - cboAlias.setSelectedItem(entry.getAlias()); - } - } - catch (KeyStoreException ex) - { - logger.error("Unable to load all data", ex); - showGenericError("plugin.certconfig.KEYSTORE_EXCEPTION", ex); - } - catch (ProviderException ex) - { - logger.error("Unable to load all data", ex); - showGenericError("plugin.certconfig.KEYSTORE_EXCEPTION", ex); - } - } - - private void initComponents() - { - setTitle(R.getI18NString("plugin.certconfig.EDIT_ENTRY")); - setLayout(new BorderLayout()); - JPanel fields = new TransparentPanel(); - fields.setLayout(new GridBagLayout()); - - JLabel lblDisplayName = new JLabel(); - lblDisplayName.setText(R.getI18NString("service.gui.DISPLAY_NAME")); - txtDisplayName = new JTextField(); - txtDisplayName.setText(entry.getDisplayName()); - - JLabel lblKeyStore = new JLabel(); - lblKeyStore.setText(R.getI18NString("plugin.certconfig.KEYSTORE")); - txtKeyStore = new JTextField(); - txtKeyStore.setText(entry.getKeyStore()); - txtKeyStore.setEditable(false); - - cmdBrowse = new JButton(); - cmdBrowse.setText(R.getI18NString("service.gui.BROWSE")); - cmdBrowse.addActionListener(this); - - JLabel lblKeyStorePassword = new JLabel(); - lblKeyStorePassword.setText( - R.getI18NString("plugin.certconfig.KEYSTORE_PASSWORD")); - txtKeyStorePassword = new JPasswordField(); - txtKeyStorePassword.setEditable(false); - - chkSavePassword = new SIPCommCheckBox(); - chkSavePassword.setText( - R.getI18NString("service.gui.REMEMBER_PASSWORD")); - chkSavePassword.addChangeListener(this); - chkSavePassword.setEnabled(false); - - JLabel lblKeyStoreType = new JLabel(); - lblKeyStoreType.setText( - R.getI18NString("plugin.certconfig.KEYSTORE_TYPE")); - cboKeyStoreTypes = - new JComboBox(cs.getSupportedKeyStoreTypes().toArray()); - cboKeyStoreTypes.addItemListener(this); - cboKeyStoreTypes.setEnabled(false); - - JLabel lblAlias = new JLabel(); - lblAlias.setText(R.getI18NString("plugin.certconfig.ALIAS")); - cboAlias = new JComboBox(); - cboAlias.addItemListener(this); - cboAlias.setEnabled(false); - - cmdShowCert = new JButton(); - cmdShowCert.setText(R.getI18NString("service.gui.SHOW_CERT") + "..."); - cmdShowCert.addActionListener(this); - cmdShowCert.setEnabled(false); - - cmdCancel = new JButton(); - cmdCancel.setText(R.getI18NString("service.gui.CANCEL")); - cmdCancel.addActionListener(this); - - cmdOk = new JButton(); - cmdOk.setText(R.getI18NString("service.gui.OK")); - cmdOk.addActionListener(this); - cmdOk.setPreferredSize(cmdCancel.getPreferredSize()); - - TransparentPanel buttons = new TransparentPanel(); - buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); - buttons.add(cmdOk); - buttons.add(cmdCancel); - - GridBagConstraints first = new GridBagConstraints(); - first.gridx = 0; - first.gridy = 0; - first.weightx = 0; - first.anchor = GridBagConstraints.LINE_START; - first.gridwidth = 1; - first.insets = new Insets(2,4,2,4); - first.fill = GridBagConstraints.HORIZONTAL; - - GridBagConstraints second = new GridBagConstraints(); - second.gridx = 1; - second.gridy = 0; - second.weightx = 2; - second.anchor = GridBagConstraints.LINE_START; - second.gridwidth = 1; //GridBagConstraints.REMAINDER; - second.insets = first.insets; - second.fill = GridBagConstraints.HORIZONTAL; - - GridBagConstraints third = new GridBagConstraints(); - third.gridx = 2; - third.gridy = 0; - third.weightx = 1; - third.anchor = GridBagConstraints.LINE_END; - third.gridwidth = 1; - third.insets = first.insets; - third.fill = GridBagConstraints.HORIZONTAL; - - fields.add(lblDisplayName, first); - fields.add(txtDisplayName, second); - - first.gridy = second.gridy = ++third.gridy; - fields.add(lblKeyStore, first); - fields.add(txtKeyStore, second); - fields.add(cmdBrowse, third); - - first.gridy = second.gridy = ++third.gridy; - fields.add(lblKeyStoreType, first); - fields.add(cboKeyStoreTypes, second); - - first.gridy = second.gridy = ++third.gridy; - fields.add(lblKeyStorePassword, first); - fields.add(txtKeyStorePassword, second); - - first.gridy = second.gridy = ++third.gridy; - fields.add(chkSavePassword, second); - - first.gridy = second.gridy = ++third.gridy; - fields.add(lblAlias, first); - fields.add(cboAlias, second); - fields.add(cmdShowCert, third); - - add(fields, BorderLayout.CENTER); - add(buttons, BorderLayout.SOUTH); - } - - // ------------------------------------------------------------------------ - // Event handling - // ------------------------------------------------------------------------ - @Override - protected void close(boolean escaped) - { - cmdCancel.doClick(); - } - - public void actionPerformed(ActionEvent e) - { - if(e.getSource() == cmdOk) - { - if(cboAlias.getSelectedItem() == null - || StringUtils.isNullOrEmpty(txtDisplayName.getText()) - || StringUtils.isNullOrEmpty(txtKeyStore.getText())) - { - JOptionPane.showMessageDialog(this, - R.getI18NString("plugin.certconfig.INCOMPLETE"), - R.getI18NString("service.gui.ERROR"), - JOptionPane.ERROR_MESSAGE); - return; - } - entry.setAlias(cboAlias.getSelectedItem().toString()); - entry.setDisplayName(txtDisplayName.getText()); - entry.setSavePassword(chkSavePassword.isSelected()); - entry.setKeyStorePassword( - new String(txtKeyStorePassword.getPassword())); - entry.setKeyStoreType( - (KeyStoreType) cboKeyStoreTypes.getSelectedItem()); - entry.setKeyStore(txtKeyStore.getText()); - success = true; - dispose(); - } - if(e.getSource() == cmdCancel) - { - dispose(); - } - if(e.getSource() == cmdBrowse) - { - browseKeyStore(); - } - if(e.getSource() == cmdShowCert) - { - showSelectedCertificate(); - } - } - - private void showSelectedCertificate() - { - try - { - @SuppressWarnings("serial") - SIPCommDialog dlg = new SIPCommDialog(this, false) - { - private JButton cmdClose; - { - setTitle(cboAlias.getSelectedItem().toString()); - setLayout(new BorderLayout()); - final JScrollPane certScroll = - new JScrollPane(new X509CertificatePanel( - (X509Certificate) keyStore.getCertificate(cboAlias - .getSelectedItem().toString()))); - certScroll.setPreferredSize(new Dimension(600, 300)); - certScroll.getVerticalScrollBar().setValue(0); - add(certScroll, BorderLayout.CENTER); - - SwingUtilities.invokeLater(new Runnable() - { - public void run() - { - certScroll.getVerticalScrollBar().setValue(0); - } - }); - - cmdClose = new JButton(); - cmdClose.setText(R.getI18NString("service.gui.CLOSE")); - cmdClose.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - dispose(); - } - }); - - TransparentPanel buttons = - new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); - buttons.add(cmdClose); - add(buttons, BorderLayout.SOUTH); - - setLocationRelativeTo(cmdShowCert); - } - - @Override - protected void close(boolean escaped) - { - cmdClose.doClick(); - } - }; - dlg.setModal(true); - dlg.setVisible(true); - } - catch (KeyStoreException e1) - { - logger.error("Unable to show the selected certificate", e1); - showGenericError("plugin.certconfig.SHOW_CERT_EXCEPTION", e1); - } - } - - /** - * Opens a FileChoserDialog to let the user pick a keystore and tries to - * auto-detect the keystore type using the file extension - */ - private void browseKeyStore() - { - SipCommFileChooser dlg = - GenericFileDialog.create(null, - R.getI18NString("plugin.certconfig.BROWSE_KEYSTORE"), - SipCommFileChooser.LOAD_FILE_OPERATION); - dlg.setSelectionMode(SipCommFileChooser.FILES_ONLY); - dlg.addFilter(new SipCommFileFilter() - { - @Override - public String getDescription() - { - return R - .getI18NString("plugin.certconfig.FILE_TYPE_DESCRIPTION"); - } - - @Override - public boolean accept(File f) - { - for(KeyStoreType kt : cs.getSupportedKeyStoreTypes()) - for(String ext : kt.getFileExtensions()) - if(f.getName().endsWith(ext)) - return true; - - return false; - } - }); - File f = dlg.getFileFromDialog(); - if(f != null) - { - cboKeyStoreTypes.setEnabled(true); - cboKeyStoreTypes.setSelectedItem(null); - cboAlias.setEnabled(true); - - txtKeyStore.setText(f.getAbsolutePath()); - for(KeyStoreType kt: cs.getSupportedKeyStoreTypes()) - for(String ext : kt.getFileExtensions()) - if(f.getName().endsWith(ext)) - cboKeyStoreTypes.setSelectedItem(kt); - } - } - - /** - * Open the keystore selected by the user. If the type is set as PKCS#11, - * the file is loaded as a provider. If the store is protected by a - * password, the user is being asked by an authentication dialog. - * - * @return The loaded keystore - * @throws KeyStoreException when something goes wrong - */ - private KeyStore loadKeyStore() throws KeyStoreException - { - final File f = new File(txtKeyStore.getText()); - final KeyStoreType kt = - (KeyStoreType) cboKeyStoreTypes.getSelectedItem(); - if("PKCS11".equals(kt.getName())) - { - String config = - "name=" + f.getName() + "\nlibrary=" + f.getAbsoluteFile(); - try - { - Class pkcs11c = - Class.forName("sun.security.pkcs11.SunPKCS11"); - Constructor c = pkcs11c.getConstructor(InputStream.class); - Provider p = - (Provider) c.newInstance(new ByteArrayInputStream(config - .getBytes())); - Security.insertProviderAt(p, 0); - } - catch (Exception e) - { - logger.error("Tried to access the PKCS11 provider on an " - + "unsupported platform or the load failed", e); - } - } - KeyStore.Builder ksBuilder = KeyStore.Builder.newInstance( - kt.getName(), - null, - f, - new KeyStore.CallbackHandlerProtection(new CallbackHandler() - { - public void handle(Callback[] callbacks) - throws IOException, - UnsupportedCallbackException - { - for(Callback cb : callbacks) - { - if(!(cb instanceof PasswordCallback)) - throw new UnsupportedCallbackException(cb); - PasswordCallback pwcb = (PasswordCallback)cb; - if( - ( - txtKeyStorePassword.getPassword() != null - && txtKeyStorePassword.getPassword().length>0 - ) - || chkSavePassword.isSelected()) - { - pwcb.setPassword(txtKeyStorePassword.getPassword()); - return; - } - AuthenticationWindow aw = new AuthenticationWindow( - CertConfigEntryDialog.this, - f.getName(), - null, - kt.getName(), - false, - null - ); - aw.setAllowSavePassword(!"PKCS11".equals(kt.getName())); - aw.setVisible(true); - if(!aw.isCanceled()) - { - pwcb.setPassword(aw.getPassword()); - if (!"PKCS11".equals(kt.getName()) - && aw.isRememberPassword()) - { - txtKeyStorePassword.setText(new String(aw - .getPassword())); - } - chkSavePassword.setSelected(aw - .isRememberPassword()); - } - else - throw new IOException("User cancel"); - } - } - })); - return ksBuilder.getKeyStore(); - } - - /** - * Load the certificate entry aliases from the chosen keystore. - */ - private void loadAliases() - { - String currentDisplayName = txtDisplayName.getText(); - String currentAlias = - cboAlias.getSelectedItem() == null ? null : cboAlias - .getSelectedItem().toString(); - try - { - cboAlias.removeAllItems(); - Enumeration e = keyStore.aliases(); - while(e.hasMoreElements()) - { - cboAlias.addItem(e.nextElement()); - } - // if the display name is empty or identical to the alias, set it - // to the alias of the newly selected cert - if( - ( - StringUtils.isNullOrEmpty(currentDisplayName) - || ( - currentDisplayName != null - && currentDisplayName.equals(currentAlias) - ) - ) - && cboAlias.getSelectedItem() != null) - { - txtDisplayName.setText(cboAlias.getSelectedItem().toString()); - } - - } - catch (KeyStoreException e) - { - cboAlias.removeAllItems(); - logger.error("Unable to obtain aliases from keystore", e); - showGenericError("plugin.certconfig.ALIAS_LOAD_EXCEPTION", e); - } - } - - private void showGenericError(String msg, Throwable e) - { - JOptionPane.showMessageDialog( - this, - R.getI18NString(msg, new String[]{e.getMessage()}), - R.getI18NString("service.gui.ERROR"), - JOptionPane.ERROR_MESSAGE - ); - } - - /** - * Show this dialog. - * - * @return true if OK has been pressed, false otherwise - */ - public boolean showDialog() - { - setModal(true); - setVisible(true); - setVisible(false); - return success; - } - - public void itemStateChanged(ItemEvent e) - { - if(e.getStateChange() != ItemEvent.SELECTED) - return; - if(e.getSource() == cboKeyStoreTypes) - { - KeyStoreType kt = (KeyStoreType)cboKeyStoreTypes.getSelectedItem(); - if(kt == null) - return; - try - { - if(!"PKCS11".equals(kt.getName())) - chkSavePassword.setEnabled(true); - txtKeyStorePassword.setEditable(kt.hasKeyStorePassword() - && chkSavePassword.isSelected()); - - keyStore = loadKeyStore(); - loadAliases(); - } - catch (KeyStoreException ex) - { - cboAlias.removeAllItems(); - showGenericError("plugin.certconfig.INVALID_KEYSTORE_TYPE", ex); - } - } - if(e.getSource() == cboAlias) - { - cmdShowCert.setEnabled(cboAlias.getSelectedItem() != null); - } - } - - public void stateChanged(ChangeEvent e) - { - if(e.getSource() == chkSavePassword) - { - txtKeyStorePassword.setEditable( - chkSavePassword.isSelected() - && ((KeyStoreType) cboKeyStoreTypes.getSelectedItem()) - .hasKeyStorePassword() - ); - } - } -} +package net.java.sip.communicator.plugin.certconfig; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.lang.reflect.*; +import java.security.*; +import java.security.cert.*; +import java.util.*; + +import javax.security.auth.callback.*; +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.certificate.*; +import net.java.sip.communicator.util.Logger; + +import org.jitsi.service.resources.*; +import org.jitsi.util.*; + +/** + * Dialog window to add/edit client certificate configuration entries. + * + * @author Ingo Bauersachs + */ +public class CertConfigEntryDialog + extends SIPCommDialog + implements ActionListener, ItemListener, ChangeListener +{ + // ------------------------------------------------------------------------ + // Fields and services + // ------------------------------------------------------------------------ + private static final long serialVersionUID = 8361336563239745007L; + private static final Logger logger = Logger + .getLogger(CertConfigEntryDialog.class); + private ResourceManagementService R = CertConfigActivator.R; + private CertificateService cs = CertConfigActivator.getCertService(); + private CertificateConfigEntry entry; + private boolean success = false; + + // ------------------------------------------------------------------------ + // GUI members + // ------------------------------------------------------------------------ + private JButton cmdOk; + private JButton cmdCancel; + private JButton cmdBrowse; + private JTextField txtDisplayName; + private JTextField txtKeyStore; + private JComboBox cboKeyStoreTypes; + private JCheckBox chkSavePassword; + private JPasswordField txtKeyStorePassword; + private JComboBox cboAlias; + private JButton cmdShowCert; + private KeyStore keyStore; + + // ------------------------------------------------------------------------ + // Initialization + // ------------------------------------------------------------------------ + /** + * Constructor. + * + * @param e the CertificateConfigEntry + */ + public CertConfigEntryDialog(CertificateConfigEntry e) + { + super(false); + entry = e; + initComponents(); + setPreferredSize(new Dimension(650, 270)); + + try + { + if(entry.getKeyStore() != null) + { + txtKeyStorePassword.setText(entry.getKeyStorePassword()); + chkSavePassword.setSelected(entry.isSavePassword()); + cboKeyStoreTypes.setEnabled(true); + cboKeyStoreTypes.setSelectedItem(entry.getKeyStoreType()); + if(keyStore == null) + keyStore = loadKeyStore(); + cboAlias.setEnabled(true); + loadAliases(); + cboAlias.setSelectedItem(entry.getAlias()); + } + } + catch (KeyStoreException ex) + { + logger.error("Unable to load all data", ex); + showGenericError("plugin.certconfig.KEYSTORE_EXCEPTION", ex); + } + catch (ProviderException ex) + { + logger.error("Unable to load all data", ex); + showGenericError("plugin.certconfig.KEYSTORE_EXCEPTION", ex); + } + } + + private void initComponents() + { + setTitle(R.getI18NString("plugin.certconfig.EDIT_ENTRY")); + setLayout(new BorderLayout()); + JPanel fields = new TransparentPanel(); + fields.setLayout(new GridBagLayout()); + + JLabel lblDisplayName = new JLabel(); + lblDisplayName.setText(R.getI18NString("service.gui.DISPLAY_NAME")); + txtDisplayName = new JTextField(); + txtDisplayName.setText(entry.getDisplayName()); + + JLabel lblKeyStore = new JLabel(); + lblKeyStore.setText(R.getI18NString("plugin.certconfig.KEYSTORE")); + txtKeyStore = new JTextField(); + txtKeyStore.setText(entry.getKeyStore()); + txtKeyStore.setEditable(false); + + cmdBrowse = new JButton(); + cmdBrowse.setText(R.getI18NString("service.gui.BROWSE")); + cmdBrowse.addActionListener(this); + + JLabel lblKeyStorePassword = new JLabel(); + lblKeyStorePassword.setText( + R.getI18NString("plugin.certconfig.KEYSTORE_PASSWORD")); + txtKeyStorePassword = new JPasswordField(); + txtKeyStorePassword.setEditable(false); + + chkSavePassword = new SIPCommCheckBox(); + chkSavePassword.setText( + R.getI18NString("service.gui.REMEMBER_PASSWORD")); + chkSavePassword.addChangeListener(this); + chkSavePassword.setEnabled(false); + + JLabel lblKeyStoreType = new JLabel(); + lblKeyStoreType.setText( + R.getI18NString("plugin.certconfig.KEYSTORE_TYPE")); + cboKeyStoreTypes = + new JComboBox(cs.getSupportedKeyStoreTypes().toArray()); + cboKeyStoreTypes.addItemListener(this); + cboKeyStoreTypes.setEnabled(false); + + JLabel lblAlias = new JLabel(); + lblAlias.setText(R.getI18NString("plugin.certconfig.ALIAS")); + cboAlias = new JComboBox(); + cboAlias.addItemListener(this); + cboAlias.setEnabled(false); + + cmdShowCert = new JButton(); + cmdShowCert.setText(R.getI18NString("service.gui.SHOW_CERT") + "..."); + cmdShowCert.addActionListener(this); + cmdShowCert.setEnabled(false); + + cmdCancel = new JButton(); + cmdCancel.setText(R.getI18NString("service.gui.CANCEL")); + cmdCancel.addActionListener(this); + + cmdOk = new JButton(); + cmdOk.setText(R.getI18NString("service.gui.OK")); + cmdOk.addActionListener(this); + cmdOk.setPreferredSize(cmdCancel.getPreferredSize()); + + TransparentPanel buttons = new TransparentPanel(); + buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); + buttons.add(cmdOk); + buttons.add(cmdCancel); + + GridBagConstraints first = new GridBagConstraints(); + first.gridx = 0; + first.gridy = 0; + first.weightx = 0; + first.anchor = GridBagConstraints.LINE_START; + first.gridwidth = 1; + first.insets = new Insets(2,4,2,4); + first.fill = GridBagConstraints.HORIZONTAL; + + GridBagConstraints second = new GridBagConstraints(); + second.gridx = 1; + second.gridy = 0; + second.weightx = 2; + second.anchor = GridBagConstraints.LINE_START; + second.gridwidth = 1; //GridBagConstraints.REMAINDER; + second.insets = first.insets; + second.fill = GridBagConstraints.HORIZONTAL; + + GridBagConstraints third = new GridBagConstraints(); + third.gridx = 2; + third.gridy = 0; + third.weightx = 1; + third.anchor = GridBagConstraints.LINE_END; + third.gridwidth = 1; + third.insets = first.insets; + third.fill = GridBagConstraints.HORIZONTAL; + + fields.add(lblDisplayName, first); + fields.add(txtDisplayName, second); + + first.gridy = second.gridy = ++third.gridy; + fields.add(lblKeyStore, first); + fields.add(txtKeyStore, second); + fields.add(cmdBrowse, third); + + first.gridy = second.gridy = ++third.gridy; + fields.add(lblKeyStoreType, first); + fields.add(cboKeyStoreTypes, second); + + first.gridy = second.gridy = ++third.gridy; + fields.add(lblKeyStorePassword, first); + fields.add(txtKeyStorePassword, second); + + first.gridy = second.gridy = ++third.gridy; + fields.add(chkSavePassword, second); + + first.gridy = second.gridy = ++third.gridy; + fields.add(lblAlias, first); + fields.add(cboAlias, second); + fields.add(cmdShowCert, third); + + add(fields, BorderLayout.CENTER); + add(buttons, BorderLayout.SOUTH); + } + + // ------------------------------------------------------------------------ + // Event handling + // ------------------------------------------------------------------------ + @Override + protected void close(boolean escaped) + { + cmdCancel.doClick(); + } + + public void actionPerformed(ActionEvent e) + { + if(e.getSource() == cmdOk) + { + if(cboAlias.getSelectedItem() == null + || StringUtils.isNullOrEmpty(txtDisplayName.getText()) + || StringUtils.isNullOrEmpty(txtKeyStore.getText())) + { + JOptionPane.showMessageDialog(this, + R.getI18NString("plugin.certconfig.INCOMPLETE"), + R.getI18NString("service.gui.ERROR"), + JOptionPane.ERROR_MESSAGE); + return; + } + entry.setAlias(cboAlias.getSelectedItem().toString()); + entry.setDisplayName(txtDisplayName.getText()); + entry.setSavePassword(chkSavePassword.isSelected()); + entry.setKeyStorePassword( + new String(txtKeyStorePassword.getPassword())); + entry.setKeyStoreType( + (KeyStoreType) cboKeyStoreTypes.getSelectedItem()); + entry.setKeyStore(txtKeyStore.getText()); + success = true; + dispose(); + } + if(e.getSource() == cmdCancel) + { + dispose(); + } + if(e.getSource() == cmdBrowse) + { + browseKeyStore(); + } + if(e.getSource() == cmdShowCert) + { + showSelectedCertificate(); + } + } + + private void showSelectedCertificate() + { + try + { + @SuppressWarnings("serial") + SIPCommDialog dlg = new SIPCommDialog(this, false) + { + private JButton cmdClose; + { + setTitle(cboAlias.getSelectedItem().toString()); + setLayout(new BorderLayout()); + final JScrollPane certScroll = + new JScrollPane(new X509CertificatePanel( + (X509Certificate) keyStore.getCertificate(cboAlias + .getSelectedItem().toString()))); + certScroll.setPreferredSize(new Dimension(600, 300)); + certScroll.getVerticalScrollBar().setValue(0); + add(certScroll, BorderLayout.CENTER); + + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + certScroll.getVerticalScrollBar().setValue(0); + } + }); + + cmdClose = new JButton(); + cmdClose.setText(R.getI18NString("service.gui.CLOSE")); + cmdClose.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + dispose(); + } + }); + + TransparentPanel buttons = + new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); + buttons.add(cmdClose); + add(buttons, BorderLayout.SOUTH); + + setLocationRelativeTo(cmdShowCert); + } + + @Override + protected void close(boolean escaped) + { + cmdClose.doClick(); + } + }; + dlg.setModal(true); + dlg.setVisible(true); + } + catch (KeyStoreException e1) + { + logger.error("Unable to show the selected certificate", e1); + showGenericError("plugin.certconfig.SHOW_CERT_EXCEPTION", e1); + } + } + + /** + * Opens a FileChoserDialog to let the user pick a keystore and tries to + * auto-detect the keystore type using the file extension + */ + private void browseKeyStore() + { + SipCommFileChooser dlg = + GenericFileDialog.create(null, + R.getI18NString("plugin.certconfig.BROWSE_KEYSTORE"), + SipCommFileChooser.LOAD_FILE_OPERATION); + dlg.setSelectionMode(SipCommFileChooser.FILES_ONLY); + dlg.addFilter(new SipCommFileFilter() + { + @Override + public String getDescription() + { + return R + .getI18NString("plugin.certconfig.FILE_TYPE_DESCRIPTION"); + } + + @Override + public boolean accept(File f) + { + for(KeyStoreType kt : cs.getSupportedKeyStoreTypes()) + for(String ext : kt.getFileExtensions()) + if(f.getName().endsWith(ext)) + return true; + + return false; + } + }); + File f = dlg.getFileFromDialog(); + if(f != null) + { + cboKeyStoreTypes.setEnabled(true); + cboKeyStoreTypes.setSelectedItem(null); + cboAlias.setEnabled(true); + + txtKeyStore.setText(f.getAbsolutePath()); + for(KeyStoreType kt: cs.getSupportedKeyStoreTypes()) + for(String ext : kt.getFileExtensions()) + if(f.getName().endsWith(ext)) + cboKeyStoreTypes.setSelectedItem(kt); + } + } + + /** + * Open the keystore selected by the user. If the type is set as PKCS#11, + * the file is loaded as a provider. If the store is protected by a + * password, the user is being asked by an authentication dialog. + * + * @return The loaded keystore + * @throws KeyStoreException when something goes wrong + */ + private KeyStore loadKeyStore() throws KeyStoreException + { + final File f = new File(txtKeyStore.getText()); + final KeyStoreType kt = + (KeyStoreType) cboKeyStoreTypes.getSelectedItem(); + if("PKCS11".equals(kt.getName())) + { + String config = + "name=" + f.getName() + "\nlibrary=" + f.getAbsoluteFile(); + try + { + Class pkcs11c = + Class.forName("sun.security.pkcs11.SunPKCS11"); + Constructor c = pkcs11c.getConstructor(InputStream.class); + Provider p = + (Provider) c.newInstance(new ByteArrayInputStream(config + .getBytes())); + Security.insertProviderAt(p, 0); + } + catch (Exception e) + { + logger.error("Tried to access the PKCS11 provider on an " + + "unsupported platform or the load failed", e); + } + } + KeyStore.Builder ksBuilder = KeyStore.Builder.newInstance( + kt.getName(), + null, + f, + new KeyStore.CallbackHandlerProtection(new CallbackHandler() + { + public void handle(Callback[] callbacks) + throws IOException, + UnsupportedCallbackException + { + for(Callback cb : callbacks) + { + if(!(cb instanceof PasswordCallback)) + throw new UnsupportedCallbackException(cb); + PasswordCallback pwcb = (PasswordCallback)cb; + if( + ( + txtKeyStorePassword.getPassword() != null + && txtKeyStorePassword.getPassword().length>0 + ) + || chkSavePassword.isSelected()) + { + pwcb.setPassword(txtKeyStorePassword.getPassword()); + return; + } + AuthenticationWindow aw = new AuthenticationWindow( + CertConfigEntryDialog.this, + f.getName(), + null, + kt.getName(), + false, + null + ); + aw.setAllowSavePassword(!"PKCS11".equals(kt.getName())); + aw.setVisible(true); + if(!aw.isCanceled()) + { + pwcb.setPassword(aw.getPassword()); + if (!"PKCS11".equals(kt.getName()) + && aw.isRememberPassword()) + { + txtKeyStorePassword.setText(new String(aw + .getPassword())); + } + chkSavePassword.setSelected(aw + .isRememberPassword()); + } + else + throw new IOException("User cancel"); + } + } + })); + return ksBuilder.getKeyStore(); + } + + /** + * Load the certificate entry aliases from the chosen keystore. + */ + private void loadAliases() + { + String currentDisplayName = txtDisplayName.getText(); + String currentAlias = + cboAlias.getSelectedItem() == null ? null : cboAlias + .getSelectedItem().toString(); + try + { + cboAlias.removeAllItems(); + Enumeration e = keyStore.aliases(); + while(e.hasMoreElements()) + { + cboAlias.addItem(e.nextElement()); + } + // if the display name is empty or identical to the alias, set it + // to the alias of the newly selected cert + if( + ( + StringUtils.isNullOrEmpty(currentDisplayName) + || ( + currentDisplayName != null + && currentDisplayName.equals(currentAlias) + ) + ) + && cboAlias.getSelectedItem() != null) + { + txtDisplayName.setText(cboAlias.getSelectedItem().toString()); + } + + } + catch (KeyStoreException e) + { + cboAlias.removeAllItems(); + logger.error("Unable to obtain aliases from keystore", e); + showGenericError("plugin.certconfig.ALIAS_LOAD_EXCEPTION", e); + } + } + + private void showGenericError(String msg, Throwable e) + { + JOptionPane.showMessageDialog( + this, + R.getI18NString(msg, new String[]{e.getMessage()}), + R.getI18NString("service.gui.ERROR"), + JOptionPane.ERROR_MESSAGE + ); + } + + /** + * Show this dialog. + * + * @return true if OK has been pressed, false otherwise + */ + public boolean showDialog() + { + setModal(true); + setVisible(true); + setVisible(false); + return success; + } + + public void itemStateChanged(ItemEvent e) + { + if(e.getStateChange() != ItemEvent.SELECTED) + return; + if(e.getSource() == cboKeyStoreTypes) + { + KeyStoreType kt = (KeyStoreType)cboKeyStoreTypes.getSelectedItem(); + if(kt == null) + return; + try + { + if(!"PKCS11".equals(kt.getName())) + chkSavePassword.setEnabled(true); + txtKeyStorePassword.setEditable(kt.hasKeyStorePassword() + && chkSavePassword.isSelected()); + + keyStore = loadKeyStore(); + loadAliases(); + } + catch (KeyStoreException ex) + { + cboAlias.removeAllItems(); + showGenericError("plugin.certconfig.INVALID_KEYSTORE_TYPE", ex); + } + } + if(e.getSource() == cboAlias) + { + cmdShowCert.setEnabled(cboAlias.getSelectedItem() != null); + } + } + + public void stateChanged(ChangeEvent e) + { + if(e.getSource() == chkSavePassword) + { + txtKeyStorePassword.setEditable( + chkSavePassword.isSelected() + && ((KeyStoreType) cboKeyStoreTypes.getSelectedItem()) + .hasKeyStorePassword() + ); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/certconfig/CertConfigPanel.java b/src/net/java/sip/communicator/plugin/certconfig/CertConfigPanel.java index 57c7606..6f7bf67 100644 --- a/src/net/java/sip/communicator/plugin/certconfig/CertConfigPanel.java +++ b/src/net/java/sip/communicator/plugin/certconfig/CertConfigPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,267 +15,267 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.certconfig; - -import java.awt.*; -import java.awt.event.*; -import java.security.*; - -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.event.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.certificate.*; -import net.java.sip.communicator.service.gui.*; - -import org.jitsi.service.resources.*; -import org.jitsi.util.*; - -/** - * Advanced configuration form to define client TLS certificate templates. - * - * @author Ingo Bauersachs - */ -public class CertConfigPanel - extends TransparentPanel - implements ConfigurationForm, ActionListener, ListSelectionListener -{ - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - private static final long serialVersionUID = 2324122652952574574L; - private ResourceManagementService R; - private CertConfigTableModel model; - - // ------------------------------------------------------------------------ - // GUI members - // ------------------------------------------------------------------------ - private JButton cmdAdd; - private JButton cmdRemove; - private JButton cmdEdit; - private JTable tblCertList; - private JRadioButton rdoUseWindows; - private JRadioButton rdoUseJava; - private SIPCommCheckBox chkEnableRevocationCheck; - private SIPCommCheckBox chkEnableOcsp; - - // ------------------------------------------------------------------------ - // initialization - // ------------------------------------------------------------------------ - /** - * Creates a new instance of this class. - */ - public CertConfigPanel() - { - R = CertConfigActivator.R; - model = new CertConfigTableModel(); - initComponents(); - valueChanged(null); - } - - private void initComponents() - { - this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - - // trusted root CA source selection - if (OSUtils.IS_WINDOWS) - { - JPanel pnlCertConfig = new TransparentPanel(new GridLayout(2, 1)); - pnlCertConfig.setBorder(BorderFactory.createTitledBorder( - R.getI18NString("plugin.certconfig.TRUSTSTORE_CONFIG"))); - add(pnlCertConfig); - - ButtonGroup grpTrustStore = new ButtonGroup(); - - rdoUseJava = new SIPCommRadioButton(); - rdoUseJava.setText( - R.getI18NString("plugin.certconfig.JAVA_TRUSTSTORE")); - rdoUseJava.addActionListener(this); - grpTrustStore.add(rdoUseJava); - pnlCertConfig.add(rdoUseJava); - - rdoUseWindows = new SIPCommRadioButton(); - rdoUseWindows.setText( - R.getI18NString("plugin.certconfig.WINDOWS_TRUSTSTORE")); - rdoUseWindows.addActionListener(this); - grpTrustStore.add(rdoUseWindows); - pnlCertConfig.add(rdoUseWindows); - - if ("Windows-ROOT".equals(CertConfigActivator.getConfigService() - .getProperty(CertificateService.PNAME_TRUSTSTORE_TYPE))) - { - rdoUseWindows.setSelected(true); - } - else - { - rdoUseJava.setSelected(true); - } - } - - // revocation options - JPanel pnlRevocation = new TransparentPanel(new GridLayout(2, 1)); - pnlRevocation.setBorder(BorderFactory.createTitledBorder( - R.getI18NString("plugin.certconfig.REVOCATION_TITLE"))); - add(pnlRevocation); - - chkEnableRevocationCheck = new SIPCommCheckBox( - R.getI18NString("plugin.certconfig.REVOCATION_CHECK_ENABLED")); - chkEnableRevocationCheck.addActionListener(this); - chkEnableRevocationCheck.setSelected( - "true".equals( - System.getProperty("com.sun.net.ssl.checkRevocation"))); - pnlRevocation.add(chkEnableRevocationCheck); - - chkEnableOcsp = new SIPCommCheckBox( - R.getI18NString("plugin.certconfig.REVOCATION_OCSP_ENABLED")); - chkEnableOcsp.addActionListener(this); - chkEnableOcsp.setSelected( - "true".equals(Security.getProperty("ocsp.enable"))); - chkEnableOcsp.setEnabled(chkEnableRevocationCheck.isSelected()); - pnlRevocation.add(chkEnableOcsp); - - // Client certificate authentication list - JPanel pnlCertList = new TransparentPanel(new BorderLayout()); - pnlCertList.setBorder(BorderFactory.createTitledBorder( - R.getI18NString("plugin.certconfig.CERT_LIST_TITLE"))); - add(pnlCertList); - - JLabel lblNote = new JLabel(); - lblNote.setText( - R.getI18NString("plugin.certconfig.CERT_LIST_DESCRIPTION")); - lblNote.setBorder(new EmptyBorder(7, 7, 7, 7)); - pnlCertList.add(lblNote, BorderLayout.NORTH); - - tblCertList = new JTable(); - tblCertList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - tblCertList.getSelectionModel().addListSelectionListener(this); - tblCertList.setModel(model); - pnlCertList.add(new JScrollPane(tblCertList), BorderLayout.CENTER); - - TransparentPanel buttons = new TransparentPanel(); - buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); - pnlCertList.add(buttons, BorderLayout.SOUTH); - - cmdAdd = new JButton(); - cmdAdd.setText(R.getI18NString("service.gui.ADD")); - cmdAdd.addActionListener(this); - buttons.add(cmdAdd); - - cmdRemove = new JButton(); - cmdRemove.setText(R.getI18NString("service.gui.REMOVE")); - cmdRemove.addActionListener(this); - buttons.add(cmdRemove); - - cmdEdit = new JButton(); - cmdEdit.setText(R.getI18NString("service.gui.EDIT")); - cmdEdit.addActionListener(this); - buttons.add(cmdEdit); - } - - // ------------------------------------------------------------------------ - // event handling - // ------------------------------------------------------------------------ - public void valueChanged(ListSelectionEvent e) - { - int row = tblCertList.getSelectedRow(); - cmdRemove.setEnabled(row > -1); - cmdEdit.setEnabled(row > -1); - } - - public void actionPerformed(ActionEvent e) - { - if (e.getSource() == cmdAdd) - { - CertificateConfigEntry newEntry = new CertificateConfigEntry(); - CertConfigEntryDialog dlg = new CertConfigEntryDialog(newEntry); - if (dlg.showDialog()) - CertConfigActivator.getCertService() - .setClientAuthCertificateConfig(newEntry); - } - if (e.getSource() == cmdRemove) - { - CertConfigActivator.getCertService() - .removeClientAuthCertificateConfig( - model.getItem(tblCertList.getSelectedRow()).getId()); - } - if (e.getSource() == cmdEdit) - { - CertificateConfigEntry entry = - model.getItem(tblCertList.getSelectedRow()); - CertConfigEntryDialog dlg = new CertConfigEntryDialog(entry); - if (dlg.showDialog()) - CertConfigActivator.getCertService() - .setClientAuthCertificateConfig(entry); - } - if (e.getSource() == rdoUseJava) - { - CertConfigActivator.getConfigService().setProperty( - CertificateService.PNAME_TRUSTSTORE_TYPE, - "meta:default"); - CertConfigActivator.getConfigService().removeProperty( - CertificateService.PNAME_TRUSTSTORE_FILE); - CertConfigActivator.getCredService().removePassword( - CertificateService.PNAME_TRUSTSTORE_PASSWORD); - } - if (e.getSource() == rdoUseWindows) - { - CertConfigActivator.getConfigService().setProperty( - CertificateService.PNAME_TRUSTSTORE_TYPE, "Windows-ROOT"); - CertConfigActivator.getConfigService().removeProperty( - CertificateService.PNAME_TRUSTSTORE_FILE); - CertConfigActivator.getCredService().removePassword( - CertificateService.PNAME_TRUSTSTORE_PASSWORD); - } - if (e.getSource() == chkEnableRevocationCheck) - { - CertConfigActivator.getConfigService().setProperty( - CertificateService.PNAME_REVOCATION_CHECK_ENABLED, - chkEnableRevocationCheck.isSelected()); - - String enabled = new Boolean( - chkEnableRevocationCheck.isSelected()).toString(); - System.setProperty("com.sun.security.enableCRLDP", enabled); - System.setProperty("com.sun.net.ssl.checkRevocation", enabled); - chkEnableOcsp.setEnabled(chkEnableRevocationCheck.isSelected()); - } - if (e.getSource() == chkEnableOcsp) - { - CertConfigActivator.getConfigService().setProperty( - CertificateService.PNAME_OCSP_ENABLED, - chkEnableOcsp.isSelected()); - - Security.setProperty("ocsp.enable", - new Boolean(chkEnableOcsp.isSelected()).toString()); - } - } - - // ------------------------------------------------------------------------ - // Configuration form members - // ------------------------------------------------------------------------ - public String getTitle() - { - return CertConfigActivator.R.getI18NString("plugin.certconfig.TITLE"); - } - - public byte[] getIcon() - { - return null; - } - - public Object getForm() - { - return this; - } - - public int getIndex() - { - return -1; - } - - public boolean isAdvanced() - { - return true; - } - -} +package net.java.sip.communicator.plugin.certconfig; + +import java.awt.*; +import java.awt.event.*; +import java.security.*; + +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.event.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.certificate.*; +import net.java.sip.communicator.service.gui.*; + +import org.jitsi.service.resources.*; +import org.jitsi.util.*; + +/** + * Advanced configuration form to define client TLS certificate templates. + * + * @author Ingo Bauersachs + */ +public class CertConfigPanel + extends TransparentPanel + implements ConfigurationForm, ActionListener, ListSelectionListener +{ + // ------------------------------------------------------------------------ + // Fields + // ------------------------------------------------------------------------ + private static final long serialVersionUID = 2324122652952574574L; + private ResourceManagementService R; + private CertConfigTableModel model; + + // ------------------------------------------------------------------------ + // GUI members + // ------------------------------------------------------------------------ + private JButton cmdAdd; + private JButton cmdRemove; + private JButton cmdEdit; + private JTable tblCertList; + private JRadioButton rdoUseWindows; + private JRadioButton rdoUseJava; + private SIPCommCheckBox chkEnableRevocationCheck; + private SIPCommCheckBox chkEnableOcsp; + + // ------------------------------------------------------------------------ + // initialization + // ------------------------------------------------------------------------ + /** + * Creates a new instance of this class. + */ + public CertConfigPanel() + { + R = CertConfigActivator.R; + model = new CertConfigTableModel(); + initComponents(); + valueChanged(null); + } + + private void initComponents() + { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + // trusted root CA source selection + if (OSUtils.IS_WINDOWS) + { + JPanel pnlCertConfig = new TransparentPanel(new GridLayout(2, 1)); + pnlCertConfig.setBorder(BorderFactory.createTitledBorder( + R.getI18NString("plugin.certconfig.TRUSTSTORE_CONFIG"))); + add(pnlCertConfig); + + ButtonGroup grpTrustStore = new ButtonGroup(); + + rdoUseJava = new SIPCommRadioButton(); + rdoUseJava.setText( + R.getI18NString("plugin.certconfig.JAVA_TRUSTSTORE")); + rdoUseJava.addActionListener(this); + grpTrustStore.add(rdoUseJava); + pnlCertConfig.add(rdoUseJava); + + rdoUseWindows = new SIPCommRadioButton(); + rdoUseWindows.setText( + R.getI18NString("plugin.certconfig.WINDOWS_TRUSTSTORE")); + rdoUseWindows.addActionListener(this); + grpTrustStore.add(rdoUseWindows); + pnlCertConfig.add(rdoUseWindows); + + if ("Windows-ROOT".equals(CertConfigActivator.getConfigService() + .getProperty(CertificateService.PNAME_TRUSTSTORE_TYPE))) + { + rdoUseWindows.setSelected(true); + } + else + { + rdoUseJava.setSelected(true); + } + } + + // revocation options + JPanel pnlRevocation = new TransparentPanel(new GridLayout(2, 1)); + pnlRevocation.setBorder(BorderFactory.createTitledBorder( + R.getI18NString("plugin.certconfig.REVOCATION_TITLE"))); + add(pnlRevocation); + + chkEnableRevocationCheck = new SIPCommCheckBox( + R.getI18NString("plugin.certconfig.REVOCATION_CHECK_ENABLED")); + chkEnableRevocationCheck.addActionListener(this); + chkEnableRevocationCheck.setSelected( + "true".equals( + System.getProperty("com.sun.net.ssl.checkRevocation"))); + pnlRevocation.add(chkEnableRevocationCheck); + + chkEnableOcsp = new SIPCommCheckBox( + R.getI18NString("plugin.certconfig.REVOCATION_OCSP_ENABLED")); + chkEnableOcsp.addActionListener(this); + chkEnableOcsp.setSelected( + "true".equals(Security.getProperty("ocsp.enable"))); + chkEnableOcsp.setEnabled(chkEnableRevocationCheck.isSelected()); + pnlRevocation.add(chkEnableOcsp); + + // Client certificate authentication list + JPanel pnlCertList = new TransparentPanel(new BorderLayout()); + pnlCertList.setBorder(BorderFactory.createTitledBorder( + R.getI18NString("plugin.certconfig.CERT_LIST_TITLE"))); + add(pnlCertList); + + JLabel lblNote = new JLabel(); + lblNote.setText( + R.getI18NString("plugin.certconfig.CERT_LIST_DESCRIPTION")); + lblNote.setBorder(new EmptyBorder(7, 7, 7, 7)); + pnlCertList.add(lblNote, BorderLayout.NORTH); + + tblCertList = new JTable(); + tblCertList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + tblCertList.getSelectionModel().addListSelectionListener(this); + tblCertList.setModel(model); + pnlCertList.add(new JScrollPane(tblCertList), BorderLayout.CENTER); + + TransparentPanel buttons = new TransparentPanel(); + buttons.setLayout(new FlowLayout(FlowLayout.RIGHT)); + pnlCertList.add(buttons, BorderLayout.SOUTH); + + cmdAdd = new JButton(); + cmdAdd.setText(R.getI18NString("service.gui.ADD")); + cmdAdd.addActionListener(this); + buttons.add(cmdAdd); + + cmdRemove = new JButton(); + cmdRemove.setText(R.getI18NString("service.gui.REMOVE")); + cmdRemove.addActionListener(this); + buttons.add(cmdRemove); + + cmdEdit = new JButton(); + cmdEdit.setText(R.getI18NString("service.gui.EDIT")); + cmdEdit.addActionListener(this); + buttons.add(cmdEdit); + } + + // ------------------------------------------------------------------------ + // event handling + // ------------------------------------------------------------------------ + public void valueChanged(ListSelectionEvent e) + { + int row = tblCertList.getSelectedRow(); + cmdRemove.setEnabled(row > -1); + cmdEdit.setEnabled(row > -1); + } + + public void actionPerformed(ActionEvent e) + { + if (e.getSource() == cmdAdd) + { + CertificateConfigEntry newEntry = new CertificateConfigEntry(); + CertConfigEntryDialog dlg = new CertConfigEntryDialog(newEntry); + if (dlg.showDialog()) + CertConfigActivator.getCertService() + .setClientAuthCertificateConfig(newEntry); + } + if (e.getSource() == cmdRemove) + { + CertConfigActivator.getCertService() + .removeClientAuthCertificateConfig( + model.getItem(tblCertList.getSelectedRow()).getId()); + } + if (e.getSource() == cmdEdit) + { + CertificateConfigEntry entry = + model.getItem(tblCertList.getSelectedRow()); + CertConfigEntryDialog dlg = new CertConfigEntryDialog(entry); + if (dlg.showDialog()) + CertConfigActivator.getCertService() + .setClientAuthCertificateConfig(entry); + } + if (e.getSource() == rdoUseJava) + { + CertConfigActivator.getConfigService().setProperty( + CertificateService.PNAME_TRUSTSTORE_TYPE, + "meta:default"); + CertConfigActivator.getConfigService().removeProperty( + CertificateService.PNAME_TRUSTSTORE_FILE); + CertConfigActivator.getCredService().removePassword( + CertificateService.PNAME_TRUSTSTORE_PASSWORD); + } + if (e.getSource() == rdoUseWindows) + { + CertConfigActivator.getConfigService().setProperty( + CertificateService.PNAME_TRUSTSTORE_TYPE, "Windows-ROOT"); + CertConfigActivator.getConfigService().removeProperty( + CertificateService.PNAME_TRUSTSTORE_FILE); + CertConfigActivator.getCredService().removePassword( + CertificateService.PNAME_TRUSTSTORE_PASSWORD); + } + if (e.getSource() == chkEnableRevocationCheck) + { + CertConfigActivator.getConfigService().setProperty( + CertificateService.PNAME_REVOCATION_CHECK_ENABLED, + chkEnableRevocationCheck.isSelected()); + + String enabled = new Boolean( + chkEnableRevocationCheck.isSelected()).toString(); + System.setProperty("com.sun.security.enableCRLDP", enabled); + System.setProperty("com.sun.net.ssl.checkRevocation", enabled); + chkEnableOcsp.setEnabled(chkEnableRevocationCheck.isSelected()); + } + if (e.getSource() == chkEnableOcsp) + { + CertConfigActivator.getConfigService().setProperty( + CertificateService.PNAME_OCSP_ENABLED, + chkEnableOcsp.isSelected()); + + Security.setProperty("ocsp.enable", + new Boolean(chkEnableOcsp.isSelected()).toString()); + } + } + + // ------------------------------------------------------------------------ + // Configuration form members + // ------------------------------------------------------------------------ + public String getTitle() + { + return CertConfigActivator.R.getI18NString("plugin.certconfig.TITLE"); + } + + public byte[] getIcon() + { + return null; + } + + public Object getForm() + { + return this; + } + + public int getIndex() + { + return -1; + } + + public boolean isAdvanced() + { + return true; + } + +} diff --git a/src/net/java/sip/communicator/plugin/certconfig/CertConfigTableModel.java b/src/net/java/sip/communicator/plugin/certconfig/CertConfigTableModel.java index 7ef76d5..99391bf 100644 --- a/src/net/java/sip/communicator/plugin/certconfig/CertConfigTableModel.java +++ b/src/net/java/sip/communicator/plugin/certconfig/CertConfigTableModel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,99 +15,99 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.certconfig; - -import java.beans.*; -import java.util.*; - -import javax.swing.table.*; - -import net.java.sip.communicator.service.certificate.*; - -import org.jitsi.service.resources.*; - -/** - * Backing data model for a JTable that displays the client certificate - * configuration entries. - * - * @author Ingo Bauersachs - */ -public class CertConfigTableModel - extends AbstractTableModel - implements PropertyChangeListener -{ - private static final long serialVersionUID = -6369348252411082340L; - private CertificateService cvs; - private List model; - private ResourceManagementService R = CertConfigActivator.R; - - /** - * Constructor. - */ - public CertConfigTableModel() - { - CertConfigActivator.getConfigService().addPropertyChangeListener(this); - cvs = CertConfigActivator.getCertService(); - model = cvs.getClientAuthCertificateConfigs(); - } - - public int getRowCount() - { - return model.size(); - } - - public int getColumnCount() - { - return 3; - } - - public Object getValueAt(int rowIndex, int columnIndex) - { - switch(columnIndex) - { - case 0: - return model.get(rowIndex).getDisplayName(); - case 1: - return model.get(rowIndex).getAlias(); - case 2: - return model.get(rowIndex).getKeyStoreType(); - } - return null; - } - - /** - * Get CertificateConfigEntry located at rowIndex. - * - * @param rowIndex row index - * @return CertificateConfigEntry - */ - public CertificateConfigEntry getItem(int rowIndex) - { - return model.get(rowIndex); - } - - @Override - public String getColumnName(int column) - { - switch(column) - { - case 0: - return R.getI18NString("service.gui.DISPLAY_NAME"); - case 1: - return R.getI18NString("plugin.certconfig.ALIAS"); - case 2: - return R.getI18NString("plugin.certconfig.KEYSTORE_TYPE"); - } - return super.getColumnName(column); - } - - public void propertyChange(PropertyChangeEvent evt) - { - if (evt.getPropertyName().startsWith( - CertificateService.PNAME_CLIENTAUTH_CERTCONFIG_BASE)) - { - model = cvs.getClientAuthCertificateConfigs(); - super.fireTableDataChanged(); - } - } -} +package net.java.sip.communicator.plugin.certconfig; + +import java.beans.*; +import java.util.*; + +import javax.swing.table.*; + +import net.java.sip.communicator.service.certificate.*; + +import org.jitsi.service.resources.*; + +/** + * Backing data model for a JTable that displays the client certificate + * configuration entries. + * + * @author Ingo Bauersachs + */ +public class CertConfigTableModel + extends AbstractTableModel + implements PropertyChangeListener +{ + private static final long serialVersionUID = -6369348252411082340L; + private CertificateService cvs; + private List model; + private ResourceManagementService R = CertConfigActivator.R; + + /** + * Constructor. + */ + public CertConfigTableModel() + { + CertConfigActivator.getConfigService().addPropertyChangeListener(this); + cvs = CertConfigActivator.getCertService(); + model = cvs.getClientAuthCertificateConfigs(); + } + + public int getRowCount() + { + return model.size(); + } + + public int getColumnCount() + { + return 3; + } + + public Object getValueAt(int rowIndex, int columnIndex) + { + switch(columnIndex) + { + case 0: + return model.get(rowIndex).getDisplayName(); + case 1: + return model.get(rowIndex).getAlias(); + case 2: + return model.get(rowIndex).getKeyStoreType(); + } + return null; + } + + /** + * Get CertificateConfigEntry located at rowIndex. + * + * @param rowIndex row index + * @return CertificateConfigEntry + */ + public CertificateConfigEntry getItem(int rowIndex) + { + return model.get(rowIndex); + } + + @Override + public String getColumnName(int column) + { + switch(column) + { + case 0: + return R.getI18NString("service.gui.DISPLAY_NAME"); + case 1: + return R.getI18NString("plugin.certconfig.ALIAS"); + case 2: + return R.getI18NString("plugin.certconfig.KEYSTORE_TYPE"); + } + return super.getColumnName(column); + } + + public void propertyChange(PropertyChangeEvent evt) + { + if (evt.getPropertyName().startsWith( + CertificateService.PNAME_CLIENTAUTH_CERTCONFIG_BASE)) + { + model = cvs.getClientAuthCertificateConfigs(); + super.fireTableDataChanged(); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java index 9fd1bb6..4eba597 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,198 +15,198 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.awt.*; -import java.util.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * The left side panel of ContactInfoDialog. Display all associated subcontacts - * and their respective protocols in a JList. If a user is selected, the - * ContactInfoDetailsPanel will be updated to the current contact. - * - * @author Adam Goldstein - * @author Yana Stamcheva - */ -public class ContactInfoContactPanel - extends TransparentPanel -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The list of all subcontacts related to the selected contact. - */ - private JList contactList = new JList(); - - /** - * The scroll pane containing the list of all sub contacts of a selected - * contact. - */ - private JScrollPane contactScrollPane = new JScrollPane(); - - private DefaultListModel contactListModel = new DefaultListModel(); - - /** - * The parent dialog that makes the connection between the contacts and - * the details panel. - */ - private ContactInfoDialog contactInfoDialog; - - /** - * Create a panel with a list of all sub-contacts associated with the - * contact that was originally selected. Whenever a sub-contact is picked, - * notifies the protocolPanel of the change and it will update the displayed - * details. - * - * @param contacts the list of contacts - * @param dialog the contact info dialog - */ - public ContactInfoContactPanel( Iterator contacts, - ContactInfoDialog dialog) - { - super(new BorderLayout()); - - this.contactInfoDialog = dialog; - - this.setBorder(BorderFactory.createCompoundBorder(BorderFactory - .createTitledBorder(Resources.getString("service.gui.CONTACTS")), - BorderFactory.createEmptyBorder(5, 5, 5, 5))); - - this.contactList.setOpaque(false); - this.contactList.setModel(contactListModel); - this.contactList.setCellRenderer(new ContactPanelCellRenderer()); - this.contactList.addListSelectionListener(new ListSelectionListener() - { - public void valueChanged(ListSelectionEvent e) - { - // When the user release the mouse button and completes the - // selection, getValueIsAdjusting() becomes false - if (!e.getValueIsAdjusting()) - { - JList list = (JList) e.getSource(); - - Contact selectedContact - = (Contact) list.getSelectedValue(); - - contactInfoDialog.loadContactDetails(selectedContact); - } - } - }); - - boolean isFirstIter = true; - while (contacts.hasNext()) - { - Contact contact = contacts.next(); - - this.contactListModel.addElement(contact); - - if (isFirstIter) - { - isFirstIter = false; - contactInfoDialog.loadContactDetails(contact); - contactList.setSelectedIndex(0); - } - } - - this.contactScrollPane.setPreferredSize(new Dimension(100, 200)); - this.contactScrollPane.getViewport().add(contactList); - this.add(contactScrollPane); - } - - /** - * A cell renderer that allows both text and icons in our contactList. - */ - private static class ContactPanelCellRenderer - extends DefaultListCellRenderer - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private boolean isSelected; - - private Color blueGreyBorderColor = new Color(131, 149, 178); - - private Color selectedColor = new Color(209, 212, 225); - - public ContactPanelCellRenderer() - { - this.setOpaque(false); - } - - /** - * Renders a Contact object in a JList, by visualizing - * the contact name and the protocol icon. - * - * @param list the rendered JList - * @param value the object to be rendered - * @param index the index of the object in the list - * @param isSelected indicates if the rendered object is selected - * @param cellHasFocus indicates if the rendered object is in a focused - * cell - */ - @Override - public Component getListCellRendererComponent( JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - super.getListCellRendererComponent(list, value, index, isSelected, - cellHasFocus); - - this.isSelected = isSelected; - - Contact contact = (Contact) value; - - this.setIcon(new ImageIcon(contact.getProtocolProvider() - .getProtocolIcon().getIcon(ProtocolIcon.ICON_SIZE_16x16))); - this.setText(((Contact) value).getDisplayName()); - - return this; - } - - /** - * Paint a round blue border and background when a cell is selected. - */ - @Override - public void paintComponent(Graphics g) - { - if (this.isSelected) - { - Graphics2D g2 = (Graphics2D) g.create(); - - try - { - AntialiasingManager.activateAntialiasing(g2); - - int width = getWidth(); - int height = getHeight(); - - g2.setColor(selectedColor); - g2.fillRoundRect(1, 0, width, height, 7, 7); - - g2.setColor(blueGreyBorderColor); - g2.setStroke(new BasicStroke(1.5f)); - g2.drawRoundRect(1, 0, width - 2, height - 1, 7, 7); - } - finally - { - g2.dispose(); - } - } - - super.paintComponent(g); - } - } -} +package net.java.sip.communicator.plugin.contactinfo; + +import java.awt.*; +import java.util.*; + +import javax.swing.*; +import javax.swing.event.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * The left side panel of ContactInfoDialog. Display all associated subcontacts + * and their respective protocols in a JList. If a user is selected, the + * ContactInfoDetailsPanel will be updated to the current contact. + * + * @author Adam Goldstein + * @author Yana Stamcheva + */ +public class ContactInfoContactPanel + extends TransparentPanel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The list of all subcontacts related to the selected contact. + */ + private JList contactList = new JList(); + + /** + * The scroll pane containing the list of all sub contacts of a selected + * contact. + */ + private JScrollPane contactScrollPane = new JScrollPane(); + + private DefaultListModel contactListModel = new DefaultListModel(); + + /** + * The parent dialog that makes the connection between the contacts and + * the details panel. + */ + private ContactInfoDialog contactInfoDialog; + + /** + * Create a panel with a list of all sub-contacts associated with the + * contact that was originally selected. Whenever a sub-contact is picked, + * notifies the protocolPanel of the change and it will update the displayed + * details. + * + * @param contacts the list of contacts + * @param dialog the contact info dialog + */ + public ContactInfoContactPanel( Iterator contacts, + ContactInfoDialog dialog) + { + super(new BorderLayout()); + + this.contactInfoDialog = dialog; + + this.setBorder(BorderFactory.createCompoundBorder(BorderFactory + .createTitledBorder(Resources.getString("service.gui.CONTACTS")), + BorderFactory.createEmptyBorder(5, 5, 5, 5))); + + this.contactList.setOpaque(false); + this.contactList.setModel(contactListModel); + this.contactList.setCellRenderer(new ContactPanelCellRenderer()); + this.contactList.addListSelectionListener(new ListSelectionListener() + { + public void valueChanged(ListSelectionEvent e) + { + // When the user release the mouse button and completes the + // selection, getValueIsAdjusting() becomes false + if (!e.getValueIsAdjusting()) + { + JList list = (JList) e.getSource(); + + Contact selectedContact + = (Contact) list.getSelectedValue(); + + contactInfoDialog.loadContactDetails(selectedContact); + } + } + }); + + boolean isFirstIter = true; + while (contacts.hasNext()) + { + Contact contact = contacts.next(); + + this.contactListModel.addElement(contact); + + if (isFirstIter) + { + isFirstIter = false; + contactInfoDialog.loadContactDetails(contact); + contactList.setSelectedIndex(0); + } + } + + this.contactScrollPane.setPreferredSize(new Dimension(100, 200)); + this.contactScrollPane.getViewport().add(contactList); + this.add(contactScrollPane); + } + + /** + * A cell renderer that allows both text and icons in our contactList. + */ + private static class ContactPanelCellRenderer + extends DefaultListCellRenderer + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private boolean isSelected; + + private Color blueGreyBorderColor = new Color(131, 149, 178); + + private Color selectedColor = new Color(209, 212, 225); + + public ContactPanelCellRenderer() + { + this.setOpaque(false); + } + + /** + * Renders a Contact object in a JList, by visualizing + * the contact name and the protocol icon. + * + * @param list the rendered JList + * @param value the object to be rendered + * @param index the index of the object in the list + * @param isSelected indicates if the rendered object is selected + * @param cellHasFocus indicates if the rendered object is in a focused + * cell + */ + @Override + public Component getListCellRendererComponent( JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + super.getListCellRendererComponent(list, value, index, isSelected, + cellHasFocus); + + this.isSelected = isSelected; + + Contact contact = (Contact) value; + + this.setIcon(new ImageIcon(contact.getProtocolProvider() + .getProtocolIcon().getIcon(ProtocolIcon.ICON_SIZE_16x16))); + this.setText(((Contact) value).getDisplayName()); + + return this; + } + + /** + * Paint a round blue border and background when a cell is selected. + */ + @Override + public void paintComponent(Graphics g) + { + if (this.isSelected) + { + Graphics2D g2 = (Graphics2D) g.create(); + + try + { + AntialiasingManager.activateAntialiasing(g2); + + int width = getWidth(); + int height = getHeight(); + + g2.setColor(selectedColor); + g2.fillRoundRect(1, 0, width, height, 7, 7); + + g2.setColor(blueGreyBorderColor); + g2.setStroke(new BasicStroke(1.5f)); + g2.drawRoundRect(1, 0, width - 2, height - 1, 7, 7); + } + finally + { + g2.dispose(); + } + } + + super.paintComponent(g); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java index 49fdccb..941160a 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,678 +15,678 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.awt.*; -import java.awt.event.*; -import java.text.*; -import java.util.*; -import java.util.regex.*; - -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.text.html.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.BinaryDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.BirthDateDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.CalendarDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.EmailAddressDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.FirstNameDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenderDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.LastNameDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.LocaleDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.MiddleNameDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.PhoneNumberDetail; -import net.java.sip.communicator.service.protocol.ServerStoredDetails.TimeZoneDetail; - -/** - * The right side panel of ContactInfoDialog. Shows one tab of a summary of - * contact information for the selected subcontact, and has an extended tab - * listing all of the details. - * - * @author Adam Goldstein - * @author Yana Stamcheva - */ -public class ContactInfoDetailsPanel - extends TransparentPanel -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The tabbed pane containing the two different tabs for details. - */ - private final JTabbedPane tabbedPane = new SIPCommTabbedPane(); - - /** - * The operation set giving access to the server stored contact details. - */ - private OperationSetServerStoredContactInfo contactInfoOpSet; - - /** - * The currently selected sub-contact we are displaying information about. - */ - private Contact contact; - - /** - * The default width of hte avater area. - */ - private static final int AVATAR_AREA_WIDTH = 105; - - /** - * The default height of hte avater area. - */ - private static final int AVATAR_AREA_HEIGHT = 130; - - /** - * Construct a tabbed pane that will have one tab with a summary of info for - * the selected subcontact and one tab for all of the extended details. - */ - public ContactInfoDetailsPanel() - { - this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - this.setPreferredSize(new Dimension(400, 300)); - - this.tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); - } - - /** - * Retrieve and display the information for the newly selected contact, c. - * - * @param c the sub-contact we are now focusing on. - */ - public void loadContactDetails(Contact c) - { - this.contact = c; - - ProtocolProviderService pps = contact.getProtocolProvider(); - contactInfoOpSet - = pps.getOperationSet(OperationSetServerStoredContactInfo.class); - - this.removeAll(); - - if (contactInfoOpSet == null || !pps.isRegistered()) - { - JPanel unsupportedPanel = createUnsupportedPanel(); - - this.add(unsupportedPanel); - - this.revalidate(); - this.repaint(); - - return; - } - - this.tabbedPane.removeAll(); - - ImageIcon icon = - new ImageIcon(contact.getProtocolProvider().getProtocolIcon() - .getIcon(ProtocolIcon.ICON_SIZE_16x16)); - - JPanel summaryPanel = createSummaryInfoPanel(); - - JPanel extendedPanel = createExtendedInfoPanel(); - - JScrollPane extendedScrollPane = new JScrollPane(extendedPanel); - - this.tabbedPane.addTab( - Resources.getString("service.gui.SUMMARY"), icon, - summaryPanel, - Resources.getString( - "plugin.contactinfo.CONTACT_SUMMARY_DESCRIPTION") - + contact.getDisplayName()); - - this.tabbedPane.setMnemonicAt(0, KeyEvent.VK_1); - - this.tabbedPane.addTab( - Resources.getString("plugin.accountinfo.EXTENDED"), icon, - extendedScrollPane, - Resources.getString( - "plugin.contactinfo.CONTACT_EXTENDED_DESCRIPTION") - + contact.getDisplayName()); - - this.tabbedPane.setMnemonicAt(1, KeyEvent.VK_2); - - this.add(tabbedPane); - - this.revalidate(); - this.repaint(); - } - - /** - * Creates the panel that indicates to the user that the currently selected - * contact does not support server stored contact info. - * - * @return the panel that is added and shows a message that the selected - * sub-contact does not have the operation set for server stored - * contact info supported. - */ - private JPanel createUnsupportedPanel() - { - JTextArea unsupportedTextArea = new JTextArea( - Resources.getString("service.gui.CONTACT_INFO_NOT_SUPPORTED")); - - unsupportedTextArea.setEditable(false); - unsupportedTextArea.setLineWrap(true); - - JPanel unsupportedPanel = new TransparentPanel(new BorderLayout()); - - unsupportedPanel.add(unsupportedTextArea); - - return unsupportedPanel; - } - - /** - * Creates a panel that can be added as the summary tab that displays the - * following details: - - *

    - * Avatar(Contact image) - FirstNameDetail - MiddleNameDetail - - * LastNameDetail - BirthdateDetail (and calculate age) - GenderDetail - - * EmailAddressDetail - PhoneNumberDetail. All other details will be* added - * to our list of extended details. - * - * @return the panel that will be added as the summary tab. - */ - private JPanel createSummaryInfoPanel() - { - JPanel summaryPanel = new TransparentPanel(); - - summaryPanel.setLayout(new BorderLayout(10, 5)); - summaryPanel.setSize(this.getWidth(), this.getHeight()); - - // Create the avatar panel. - JPanel avatarPanel = new TransparentPanel(); - - avatarPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - byte[] bytes = this.contact.getImage(); - - ImageIcon scaledImage = null; - // If the user has a contact image, let's use it. If not, add the - // default - if (bytes != null) - { - scaledImage = ImageUtils.getScaledRoundedIcon( - bytes, - AVATAR_AREA_WIDTH, - AVATAR_AREA_HEIGHT - ); - } - else - scaledImage = - ImageUtils.getScaledRoundedIcon(Resources - .getImage("service.gui.DEFAULT_USER_PHOTO"), - AVATAR_AREA_WIDTH, AVATAR_AREA_HEIGHT); - - JLabel label = new JLabel(scaledImage); - label.setVerticalAlignment(JLabel.CENTER); - label.setHorizontalAlignment(JLabel.CENTER); - label.setPreferredSize(new Dimension( - AVATAR_AREA_WIDTH, - AVATAR_AREA_HEIGHT) - ); - avatarPanel.add(label); - summaryPanel.add(avatarPanel, BorderLayout.WEST); - - // Create the summary details panel. - JPanel detailsPanel = new TransparentPanel(); - detailsPanel.setLayout(new BorderLayout()); - detailsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - summaryPanel.add(detailsPanel); - - // Labels panel. - JPanel labelsPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5)); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.FIRST_NAME"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.MIDDLE_NAME"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.LAST_NAME"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.GENDER"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.BDAY"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.AGE"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.EMAIL"))); - labelsPanel.add(new JLabel( - Resources.getString("plugin.accountinfo.PHONE"))); - - detailsPanel.add(labelsPanel, BorderLayout.WEST); - - // Values panel. - JPanel valuesPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5)); - - detailsPanel.add(valuesPanel, BorderLayout.CENTER); - - Iterator contactDetails; - GenericDetail genericDetail; - - // First name details. - contactDetails = - contactInfoOpSet.getDetails(contact, FirstNameDetail.class); - - String firstNameDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - - firstNameDetail = - firstNameDetail + " " + genericDetail.getDetailValue(); - } - - if (firstNameDetail.equals("")) - firstNameDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(firstNameDetail)); - - // Middle name details. - contactDetails = - contactInfoOpSet.getDetails(contact, MiddleNameDetail.class); - - String middleNameDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - middleNameDetail = - middleNameDetail + " " + genericDetail.getDetailValue(); - } - - if (middleNameDetail.trim().equals("")) - middleNameDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(middleNameDetail)); - - // Last name details. - contactDetails = - contactInfoOpSet.getDetails(contact, LastNameDetail.class); - - String lastNameDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - - lastNameDetail = - lastNameDetail + " " + genericDetail.getDetailValue(); - } - - if (lastNameDetail.trim().equals("")) - lastNameDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(lastNameDetail)); - - // Gender details. - contactDetails = - contactInfoOpSet.getDetails(contact, GenderDetail.class); - - String genderDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - genderDetail = genderDetail + " " + genericDetail.getDetailValue(); - } - - if (genderDetail.trim().equals("")) - genderDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(genderDetail)); - - // Birthday details. - contactDetails = - contactInfoOpSet.getDetails(contact, BirthDateDetail.class); - - String birthDateDetail = ""; - String ageDetail = ""; - if (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - - Calendar calendarDetail = - (Calendar) genericDetail.getDetailValue(); - - Date birthDate = calendarDetail.getTime(); - DateFormat dateFormat = DateFormat.getDateInstance(); - - birthDateDetail = dateFormat.format(birthDate).trim(); - - Calendar c = Calendar.getInstance(); - int age = c.get(Calendar.YEAR) - calendarDetail.get(Calendar.YEAR); - - if (c.get(Calendar.MONTH) < calendarDetail.get(Calendar.MONTH)) - age--; - - ageDetail = Integer.toString(age).trim(); - } - - if (birthDateDetail.equals("")) - birthDateDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - if (ageDetail.equals("")) - ageDetail = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(birthDateDetail)); - valuesPanel.add(new JLabel(ageDetail)); - - // Email details. - contactDetails = - contactInfoOpSet.getDetails(contact, EmailAddressDetail.class); - - String emailDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - emailDetail = emailDetail + " " + genericDetail.getDetailValue(); - } - - if (emailDetail.trim().equals("")) - emailDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(emailDetail)); - - // Phone number details. - contactDetails = - contactInfoOpSet.getDetails(contact, PhoneNumberDetail.class); - - String phoneNumberDetail = ""; - while (contactDetails.hasNext()) - { - genericDetail = contactDetails.next(); - phoneNumberDetail = - phoneNumberDetail + " " + genericDetail.getDetailValue(); - } - - if (phoneNumberDetail.trim().equals("")) - phoneNumberDetail - = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); - - valuesPanel.add(new JLabel(phoneNumberDetail)); - - return summaryPanel; - } - - /** - * A panel that displays all of the details retrieved from the opSet. - * - * @return a panel that will be added as the extended tab. - */ - private JPanel createExtendedInfoPanel() - { - JPanel mainExtendedPanel = new TransparentPanel(new BorderLayout()); - - JPanel extendedPanel = new TransparentPanel(); - extendedPanel.setLayout(new BoxLayout(extendedPanel, BoxLayout.Y_AXIS)); - - JPanel imagePanel = new TransparentPanel(); - - // The imagePanel will be used for any BinaryDetails and will be added at - // the bottom so we don't disrupt the standard look of the other details - imagePanel.setLayout(new BoxLayout(imagePanel, BoxLayout.LINE_AXIS)); - imagePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory - .createTitledBorder( - Resources.getString("plugin.contactinfo.USER_PICTURES")), - - BorderFactory.createEmptyBorder(0, 5, 5, 5))); - - // Obtain all the details for a contact. - Iterator iter - = contactInfoOpSet.getAllDetailsForContact(contact); - - GenericDetail detail; - JLabel detailLabel; - JTextArea detailValueArea; - JPanel detailPanel; - - while (iter.hasNext()) - { - detail = iter.next(); - - if (detail.getDetailValue().toString().equals("")) - continue; - - detailLabel = new JLabel(); - detailValueArea = new JTextArea(); - detailPanel = new TransparentPanel(new BorderLayout(10, 10)); - - detailValueArea.setAlignmentX(JTextArea.CENTER_ALIGNMENT); - detailValueArea.setEditable(false); - detailValueArea.setLineWrap(true); - - detailPanel.add(detailLabel, BorderLayout.WEST); - detailPanel.add(detailValueArea, BorderLayout.CENTER); - detailPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - extendedPanel.add(detailPanel); - - if (detail instanceof BinaryDetail) - { - JLabel imageLabel = - new JLabel(new ImageIcon((byte[]) detail - .getDetailValue())); - - imagePanel.add(imageLabel); - } - else if (detail instanceof CalendarDetail) - { - detailLabel.setText(detail.getDetailDisplayName() + ": "); - - Date detailDate = - ((Calendar) detail.getDetailValue()).getTime(); - DateFormat df = DateFormat.getDateInstance(); - - detailValueArea.setText(df.format(detailDate).trim()); - } - else if (detail instanceof LocaleDetail) - { - detailLabel.setText(detail.getDetailDisplayName() + ": "); - - Object value = detail.getDetailValue(); - String valueStr = ""; - - if(value instanceof Locale) - valueStr = ((Locale) value).getDisplayName().trim(); - else if(value instanceof String) - valueStr = (String)value; - - detailValueArea.setText(valueStr); - } - else if (detail instanceof TimeZoneDetail) - { - detailLabel.setText(detail.getDetailDisplayName() + ": "); - - detailValueArea.setText(((TimeZone) detail.getDetailValue()) - .getDisplayName().trim()); - } - else - { - detailLabel.setText(detail.getDetailDisplayName() + ": "); - - detailValueArea.setText( - detail.getDetailValue().toString().trim()); - } - } - - // Add users status message to extended details if it exists - String statusMessage = contact.getStatusMessage(); - if(statusMessage != null && statusMessage.length() > 0) - { - detailLabel = new JLabel(); - HTMLTextPane detailValuePane = new HTMLTextPane(); - detailPanel = new TransparentPanel(new BorderLayout(10, 10)); - - detailValuePane.setEditable(false); - detailValuePane.setOpaque(false); - - detailPanel.add(detailLabel, BorderLayout.WEST); - detailPanel.add(detailValuePane, BorderLayout.CENTER); - detailPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - extendedPanel.add(detailPanel); - - detailLabel.setText(Resources.getString( - "plugin.contactinfo.USER_STATUS_MESSAGE") + ": "); - - detailValuePane.setText(statusMessage); - } - - // If the contact's protocol supports web info, give them a button to - // get it - OperationSetWebContactInfo webContactInfo - = contact - .getProtocolProvider() - .getOperationSet(OperationSetWebContactInfo.class); - - if (webContactInfo != null) - { - final String urlString - = webContactInfo.getWebContactInfo(contact).toString(); - - JLabel webInfoLabel = new JLabel("Click to see web info: "); - JEditorPane webInfoValue = new JEditorPane(); - JPanel webInfoPanel = new TransparentPanel(new BorderLayout()); - - webInfoPanel.add(webInfoLabel, BorderLayout.WEST); - webInfoPanel.add(webInfoValue, BorderLayout.CENTER); - - extendedPanel.add(webInfoPanel); - - webInfoValue.setOpaque(false); - webInfoValue.setContentType("text/html"); - webInfoValue.setEditable(false); - webInfoValue.setText( "" - + contact.getDisplayName() - + " web info"); - - webInfoValue.addHyperlinkListener(new HyperlinkListener() - { - public void hyperlinkUpdate(HyperlinkEvent e) - { - if (e.getEventType() - .equals(HyperlinkEvent.EventType.ACTIVATED)) - { - ContactInfoActivator - .getBrowserLauncher().openURL(urlString); - } - } - }); - } - - if (imagePanel.getComponentCount() > 0) - mainExtendedPanel.add(imagePanel, BorderLayout.CENTER); - - mainExtendedPanel.add(extendedPanel, BorderLayout.NORTH); - - return mainExtendedPanel; - } - - /** - * The HTMLTextPane is a pane that handles displaying HTML and - * hyperlinking urls found in the text. - */ - private class HTMLTextPane - extends JTextPane - implements HyperlinkListener - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The regular expression (in the form of compiled Pattern) - * which matches URLs for the purposed of turning them into links. - */ - private final Pattern URL_PATTERN = Pattern.compile("(" - + "(\\bwww\\.[^\\s<>\"]+\\.[^\\s<>\"]+/*[?#]*(\\w+[&=;?]\\w+)*\\b)" // wwwURL - + "|" + "(\\b\\w+://[^\\s<>\"]+/*[?#]*(\\w+[&=;?]\\w+)*\\b)" // protocolURL - + ")"); - - private SIPCommHTMLEditorKit editorKit; - private HTMLDocument document; - - /** - * Creates and instance of HTMLTextPane - */ - public HTMLTextPane() - { - editorKit = new SIPCommHTMLEditorKit(this); - - this.document = (HTMLDocument) editorKit.createDefaultDocument(); - - this.addHyperlinkListener(this); - - this.setContentType("text/html"); - this.setEditorKitForContentType("text/html", editorKit); - this.setEditorKit(editorKit); - this.setDocument(document); - - putClientProperty( - JTextPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); - } - - - /** - * Override of parent setText(String) to search for URLs and - * set as hyperlinks. - * @param string String to display. - */ - @Override - public void setText(String string) - { - - Matcher m = URL_PATTERN.matcher(string); - StringBuffer msgBuffer = new StringBuffer(); - int prevEnd = 0; - - while (m.find()) - { - String fromPrevEndToStart = string.substring(prevEnd, m.start()); - - msgBuffer.append(fromPrevEndToStart); - prevEnd = m.end(); - - String url = m.group().trim(); - - msgBuffer.append(""); - msgBuffer.append(url); - msgBuffer.append(""); - } - - String fromPrevEndToEnd = string.substring(prevEnd); - - msgBuffer.append(fromPrevEndToEnd); - - super.setText(msgBuffer.toString()); - - } - - /** - * Handles activations of hyperlinks - * @param e HyperlinkEvent to handle. - */ - public void hyperlinkUpdate(HyperlinkEvent e) - { - if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) - ContactInfoActivator.getBrowserLauncher() - .openURL(e.getURL().toString()); - } - } -} +package net.java.sip.communicator.plugin.contactinfo; + +import java.awt.*; +import java.awt.event.*; +import java.text.*; +import java.util.*; +import java.util.regex.*; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.html.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.BinaryDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.BirthDateDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.CalendarDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.EmailAddressDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.FirstNameDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenderDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.GenericDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.LastNameDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.LocaleDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.MiddleNameDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.PhoneNumberDetail; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.TimeZoneDetail; + +/** + * The right side panel of ContactInfoDialog. Shows one tab of a summary of + * contact information for the selected subcontact, and has an extended tab + * listing all of the details. + * + * @author Adam Goldstein + * @author Yana Stamcheva + */ +public class ContactInfoDetailsPanel + extends TransparentPanel +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The tabbed pane containing the two different tabs for details. + */ + private final JTabbedPane tabbedPane = new SIPCommTabbedPane(); + + /** + * The operation set giving access to the server stored contact details. + */ + private OperationSetServerStoredContactInfo contactInfoOpSet; + + /** + * The currently selected sub-contact we are displaying information about. + */ + private Contact contact; + + /** + * The default width of hte avater area. + */ + private static final int AVATAR_AREA_WIDTH = 105; + + /** + * The default height of hte avater area. + */ + private static final int AVATAR_AREA_HEIGHT = 130; + + /** + * Construct a tabbed pane that will have one tab with a summary of info for + * the selected subcontact and one tab for all of the extended details. + */ + public ContactInfoDetailsPanel() + { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + this.setPreferredSize(new Dimension(400, 300)); + + this.tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + } + + /** + * Retrieve and display the information for the newly selected contact, c. + * + * @param c the sub-contact we are now focusing on. + */ + public void loadContactDetails(Contact c) + { + this.contact = c; + + ProtocolProviderService pps = contact.getProtocolProvider(); + contactInfoOpSet + = pps.getOperationSet(OperationSetServerStoredContactInfo.class); + + this.removeAll(); + + if (contactInfoOpSet == null || !pps.isRegistered()) + { + JPanel unsupportedPanel = createUnsupportedPanel(); + + this.add(unsupportedPanel); + + this.revalidate(); + this.repaint(); + + return; + } + + this.tabbedPane.removeAll(); + + ImageIcon icon = + new ImageIcon(contact.getProtocolProvider().getProtocolIcon() + .getIcon(ProtocolIcon.ICON_SIZE_16x16)); + + JPanel summaryPanel = createSummaryInfoPanel(); + + JPanel extendedPanel = createExtendedInfoPanel(); + + JScrollPane extendedScrollPane = new JScrollPane(extendedPanel); + + this.tabbedPane.addTab( + Resources.getString("service.gui.SUMMARY"), icon, + summaryPanel, + Resources.getString( + "plugin.contactinfo.CONTACT_SUMMARY_DESCRIPTION") + + contact.getDisplayName()); + + this.tabbedPane.setMnemonicAt(0, KeyEvent.VK_1); + + this.tabbedPane.addTab( + Resources.getString("plugin.accountinfo.EXTENDED"), icon, + extendedScrollPane, + Resources.getString( + "plugin.contactinfo.CONTACT_EXTENDED_DESCRIPTION") + + contact.getDisplayName()); + + this.tabbedPane.setMnemonicAt(1, KeyEvent.VK_2); + + this.add(tabbedPane); + + this.revalidate(); + this.repaint(); + } + + /** + * Creates the panel that indicates to the user that the currently selected + * contact does not support server stored contact info. + * + * @return the panel that is added and shows a message that the selected + * sub-contact does not have the operation set for server stored + * contact info supported. + */ + private JPanel createUnsupportedPanel() + { + JTextArea unsupportedTextArea = new JTextArea( + Resources.getString("service.gui.CONTACT_INFO_NOT_SUPPORTED")); + + unsupportedTextArea.setEditable(false); + unsupportedTextArea.setLineWrap(true); + + JPanel unsupportedPanel = new TransparentPanel(new BorderLayout()); + + unsupportedPanel.add(unsupportedTextArea); + + return unsupportedPanel; + } + + /** + * Creates a panel that can be added as the summary tab that displays the + * following details: - + *

    + * Avatar(Contact image) - FirstNameDetail - MiddleNameDetail - + * LastNameDetail - BirthdateDetail (and calculate age) - GenderDetail - + * EmailAddressDetail - PhoneNumberDetail. All other details will be* added + * to our list of extended details. + * + * @return the panel that will be added as the summary tab. + */ + private JPanel createSummaryInfoPanel() + { + JPanel summaryPanel = new TransparentPanel(); + + summaryPanel.setLayout(new BorderLayout(10, 5)); + summaryPanel.setSize(this.getWidth(), this.getHeight()); + + // Create the avatar panel. + JPanel avatarPanel = new TransparentPanel(); + + avatarPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + byte[] bytes = this.contact.getImage(); + + ImageIcon scaledImage = null; + // If the user has a contact image, let's use it. If not, add the + // default + if (bytes != null) + { + scaledImage = ImageUtils.getScaledRoundedIcon( + bytes, + AVATAR_AREA_WIDTH, + AVATAR_AREA_HEIGHT + ); + } + else + scaledImage = + ImageUtils.getScaledRoundedIcon(Resources + .getImage("service.gui.DEFAULT_USER_PHOTO"), + AVATAR_AREA_WIDTH, AVATAR_AREA_HEIGHT); + + JLabel label = new JLabel(scaledImage); + label.setVerticalAlignment(JLabel.CENTER); + label.setHorizontalAlignment(JLabel.CENTER); + label.setPreferredSize(new Dimension( + AVATAR_AREA_WIDTH, + AVATAR_AREA_HEIGHT) + ); + avatarPanel.add(label); + summaryPanel.add(avatarPanel, BorderLayout.WEST); + + // Create the summary details panel. + JPanel detailsPanel = new TransparentPanel(); + detailsPanel.setLayout(new BorderLayout()); + detailsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + summaryPanel.add(detailsPanel); + + // Labels panel. + JPanel labelsPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5)); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.FIRST_NAME"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.MIDDLE_NAME"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.LAST_NAME"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.GENDER"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.BDAY"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.AGE"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.EMAIL"))); + labelsPanel.add(new JLabel( + Resources.getString("plugin.accountinfo.PHONE"))); + + detailsPanel.add(labelsPanel, BorderLayout.WEST); + + // Values panel. + JPanel valuesPanel = new TransparentPanel(new GridLayout(0, 1, 5, 5)); + + detailsPanel.add(valuesPanel, BorderLayout.CENTER); + + Iterator contactDetails; + GenericDetail genericDetail; + + // First name details. + contactDetails = + contactInfoOpSet.getDetails(contact, FirstNameDetail.class); + + String firstNameDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + + firstNameDetail = + firstNameDetail + " " + genericDetail.getDetailValue(); + } + + if (firstNameDetail.equals("")) + firstNameDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(firstNameDetail)); + + // Middle name details. + contactDetails = + contactInfoOpSet.getDetails(contact, MiddleNameDetail.class); + + String middleNameDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + middleNameDetail = + middleNameDetail + " " + genericDetail.getDetailValue(); + } + + if (middleNameDetail.trim().equals("")) + middleNameDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(middleNameDetail)); + + // Last name details. + contactDetails = + contactInfoOpSet.getDetails(contact, LastNameDetail.class); + + String lastNameDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + + lastNameDetail = + lastNameDetail + " " + genericDetail.getDetailValue(); + } + + if (lastNameDetail.trim().equals("")) + lastNameDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(lastNameDetail)); + + // Gender details. + contactDetails = + contactInfoOpSet.getDetails(contact, GenderDetail.class); + + String genderDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + genderDetail = genderDetail + " " + genericDetail.getDetailValue(); + } + + if (genderDetail.trim().equals("")) + genderDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(genderDetail)); + + // Birthday details. + contactDetails = + contactInfoOpSet.getDetails(contact, BirthDateDetail.class); + + String birthDateDetail = ""; + String ageDetail = ""; + if (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + + Calendar calendarDetail = + (Calendar) genericDetail.getDetailValue(); + + Date birthDate = calendarDetail.getTime(); + DateFormat dateFormat = DateFormat.getDateInstance(); + + birthDateDetail = dateFormat.format(birthDate).trim(); + + Calendar c = Calendar.getInstance(); + int age = c.get(Calendar.YEAR) - calendarDetail.get(Calendar.YEAR); + + if (c.get(Calendar.MONTH) < calendarDetail.get(Calendar.MONTH)) + age--; + + ageDetail = Integer.toString(age).trim(); + } + + if (birthDateDetail.equals("")) + birthDateDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + if (ageDetail.equals("")) + ageDetail = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(birthDateDetail)); + valuesPanel.add(new JLabel(ageDetail)); + + // Email details. + contactDetails = + contactInfoOpSet.getDetails(contact, EmailAddressDetail.class); + + String emailDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + emailDetail = emailDetail + " " + genericDetail.getDetailValue(); + } + + if (emailDetail.trim().equals("")) + emailDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(emailDetail)); + + // Phone number details. + contactDetails = + contactInfoOpSet.getDetails(contact, PhoneNumberDetail.class); + + String phoneNumberDetail = ""; + while (contactDetails.hasNext()) + { + genericDetail = contactDetails.next(); + phoneNumberDetail = + phoneNumberDetail + " " + genericDetail.getDetailValue(); + } + + if (phoneNumberDetail.trim().equals("")) + phoneNumberDetail + = Resources.getString("plugin.contactinfo.NOT_SPECIFIED"); + + valuesPanel.add(new JLabel(phoneNumberDetail)); + + return summaryPanel; + } + + /** + * A panel that displays all of the details retrieved from the opSet. + * + * @return a panel that will be added as the extended tab. + */ + private JPanel createExtendedInfoPanel() + { + JPanel mainExtendedPanel = new TransparentPanel(new BorderLayout()); + + JPanel extendedPanel = new TransparentPanel(); + extendedPanel.setLayout(new BoxLayout(extendedPanel, BoxLayout.Y_AXIS)); + + JPanel imagePanel = new TransparentPanel(); + + // The imagePanel will be used for any BinaryDetails and will be added at + // the bottom so we don't disrupt the standard look of the other details + imagePanel.setLayout(new BoxLayout(imagePanel, BoxLayout.LINE_AXIS)); + imagePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory + .createTitledBorder( + Resources.getString("plugin.contactinfo.USER_PICTURES")), + + BorderFactory.createEmptyBorder(0, 5, 5, 5))); + + // Obtain all the details for a contact. + Iterator iter + = contactInfoOpSet.getAllDetailsForContact(contact); + + GenericDetail detail; + JLabel detailLabel; + JTextArea detailValueArea; + JPanel detailPanel; + + while (iter.hasNext()) + { + detail = iter.next(); + + if (detail.getDetailValue().toString().equals("")) + continue; + + detailLabel = new JLabel(); + detailValueArea = new JTextArea(); + detailPanel = new TransparentPanel(new BorderLayout(10, 10)); + + detailValueArea.setAlignmentX(JTextArea.CENTER_ALIGNMENT); + detailValueArea.setEditable(false); + detailValueArea.setLineWrap(true); + + detailPanel.add(detailLabel, BorderLayout.WEST); + detailPanel.add(detailValueArea, BorderLayout.CENTER); + detailPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + extendedPanel.add(detailPanel); + + if (detail instanceof BinaryDetail) + { + JLabel imageLabel = + new JLabel(new ImageIcon((byte[]) detail + .getDetailValue())); + + imagePanel.add(imageLabel); + } + else if (detail instanceof CalendarDetail) + { + detailLabel.setText(detail.getDetailDisplayName() + ": "); + + Date detailDate = + ((Calendar) detail.getDetailValue()).getTime(); + DateFormat df = DateFormat.getDateInstance(); + + detailValueArea.setText(df.format(detailDate).trim()); + } + else if (detail instanceof LocaleDetail) + { + detailLabel.setText(detail.getDetailDisplayName() + ": "); + + Object value = detail.getDetailValue(); + String valueStr = ""; + + if(value instanceof Locale) + valueStr = ((Locale) value).getDisplayName().trim(); + else if(value instanceof String) + valueStr = (String)value; + + detailValueArea.setText(valueStr); + } + else if (detail instanceof TimeZoneDetail) + { + detailLabel.setText(detail.getDetailDisplayName() + ": "); + + detailValueArea.setText(((TimeZone) detail.getDetailValue()) + .getDisplayName().trim()); + } + else + { + detailLabel.setText(detail.getDetailDisplayName() + ": "); + + detailValueArea.setText( + detail.getDetailValue().toString().trim()); + } + } + + // Add users status message to extended details if it exists + String statusMessage = contact.getStatusMessage(); + if(statusMessage != null && statusMessage.length() > 0) + { + detailLabel = new JLabel(); + HTMLTextPane detailValuePane = new HTMLTextPane(); + detailPanel = new TransparentPanel(new BorderLayout(10, 10)); + + detailValuePane.setEditable(false); + detailValuePane.setOpaque(false); + + detailPanel.add(detailLabel, BorderLayout.WEST); + detailPanel.add(detailValuePane, BorderLayout.CENTER); + detailPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + extendedPanel.add(detailPanel); + + detailLabel.setText(Resources.getString( + "plugin.contactinfo.USER_STATUS_MESSAGE") + ": "); + + detailValuePane.setText(statusMessage); + } + + // If the contact's protocol supports web info, give them a button to + // get it + OperationSetWebContactInfo webContactInfo + = contact + .getProtocolProvider() + .getOperationSet(OperationSetWebContactInfo.class); + + if (webContactInfo != null) + { + final String urlString + = webContactInfo.getWebContactInfo(contact).toString(); + + JLabel webInfoLabel = new JLabel("Click to see web info: "); + JEditorPane webInfoValue = new JEditorPane(); + JPanel webInfoPanel = new TransparentPanel(new BorderLayout()); + + webInfoPanel.add(webInfoLabel, BorderLayout.WEST); + webInfoPanel.add(webInfoValue, BorderLayout.CENTER); + + extendedPanel.add(webInfoPanel); + + webInfoValue.setOpaque(false); + webInfoValue.setContentType("text/html"); + webInfoValue.setEditable(false); + webInfoValue.setText( "" + + contact.getDisplayName() + + " web info"); + + webInfoValue.addHyperlinkListener(new HyperlinkListener() + { + public void hyperlinkUpdate(HyperlinkEvent e) + { + if (e.getEventType() + .equals(HyperlinkEvent.EventType.ACTIVATED)) + { + ContactInfoActivator + .getBrowserLauncher().openURL(urlString); + } + } + }); + } + + if (imagePanel.getComponentCount() > 0) + mainExtendedPanel.add(imagePanel, BorderLayout.CENTER); + + mainExtendedPanel.add(extendedPanel, BorderLayout.NORTH); + + return mainExtendedPanel; + } + + /** + * The HTMLTextPane is a pane that handles displaying HTML and + * hyperlinking urls found in the text. + */ + private class HTMLTextPane + extends JTextPane + implements HyperlinkListener + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The regular expression (in the form of compiled Pattern) + * which matches URLs for the purposed of turning them into links. + */ + private final Pattern URL_PATTERN = Pattern.compile("(" + + "(\\bwww\\.[^\\s<>\"]+\\.[^\\s<>\"]+/*[?#]*(\\w+[&=;?]\\w+)*\\b)" // wwwURL + + "|" + "(\\b\\w+://[^\\s<>\"]+/*[?#]*(\\w+[&=;?]\\w+)*\\b)" // protocolURL + + ")"); + + private SIPCommHTMLEditorKit editorKit; + private HTMLDocument document; + + /** + * Creates and instance of HTMLTextPane + */ + public HTMLTextPane() + { + editorKit = new SIPCommHTMLEditorKit(this); + + this.document = (HTMLDocument) editorKit.createDefaultDocument(); + + this.addHyperlinkListener(this); + + this.setContentType("text/html"); + this.setEditorKitForContentType("text/html", editorKit); + this.setEditorKit(editorKit); + this.setDocument(document); + + putClientProperty( + JTextPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE); + } + + + /** + * Override of parent setText(String) to search for URLs and + * set as hyperlinks. + * @param string String to display. + */ + @Override + public void setText(String string) + { + + Matcher m = URL_PATTERN.matcher(string); + StringBuffer msgBuffer = new StringBuffer(); + int prevEnd = 0; + + while (m.find()) + { + String fromPrevEndToStart = string.substring(prevEnd, m.start()); + + msgBuffer.append(fromPrevEndToStart); + prevEnd = m.end(); + + String url = m.group().trim(); + + msgBuffer.append(""); + msgBuffer.append(url); + msgBuffer.append(""); + } + + String fromPrevEndToEnd = string.substring(prevEnd); + + msgBuffer.append(fromPrevEndToEnd); + + super.setText(msgBuffer.toString()); + + } + + /** + * Handles activations of hyperlinks + * @param e HyperlinkEvent to handle. + */ + public void hyperlinkUpdate(HyperlinkEvent e) + { + if(e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) + ContactInfoActivator.getBrowserLauncher() + .openURL(e.getURL().toString()); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java index 8e7d9db..3176533 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,88 +15,88 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.awt.*; -import java.util.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * A GUI plug-in for SIP Communicator that will allow cross protocol contact - * information viewing and editing. - * - * @author Adam Goldstein - * @author Yana Stamcheva - */ -public class ContactInfoDialog - extends SIPCommFrame -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The right side of this frame that contains protocol specific contact - * details. - */ - protected ContactInfoDetailsPanel detailsPanel - = new ContactInfoDetailsPanel(); - - /** - * The left side of this frame that contains a list of all sub-contacts - * associated with the selected contact. - */ - protected ContactInfoContactPanel contactPanel; - - /** - * The contact that was right clicked on. The sub-contacts of contactItem - * will be the ones selectable in contactPanel. - */ - protected MetaContact metaContact; - - /** - * Accepts a MetaContact and constructs a frame with ContactInfoSearchPanel - * on the left and an information interface, ContactInfoDetailsPanel, - * on the right. - * @param metaContact the sub-contacts of this MetaContact that was right - * clicked on will be the ones selectable in contactPanel. - */ - public ContactInfoDialog(MetaContact metaContact) - { - this.metaContact = metaContact; - - this.setTitle(Resources.getString("plugin.contactinfo.TITLE") - + ": " - + metaContact.getDisplayName()); - - Iterator subContacts = metaContact.getContacts(); - - this.contactPanel - = new ContactInfoContactPanel(subContacts, this); - - Container contentPane = getContentPane(); - contentPane.add(contactPanel, BorderLayout.WEST); - contentPane.add(detailsPanel, BorderLayout.CENTER); - - this.pack(); - } - - /** - * Loads the details of the given contact. - * - * @param contact the Contact, which details we load - */ - public void loadContactDetails(Contact contact) - { - this.detailsPanel.loadContactDetails(contact); - } - - @Override - protected void close(boolean isEscaped) - { - } -} +package net.java.sip.communicator.plugin.contactinfo; + +import java.awt.*; +import java.util.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * A GUI plug-in for SIP Communicator that will allow cross protocol contact + * information viewing and editing. + * + * @author Adam Goldstein + * @author Yana Stamcheva + */ +public class ContactInfoDialog + extends SIPCommFrame +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The right side of this frame that contains protocol specific contact + * details. + */ + protected ContactInfoDetailsPanel detailsPanel + = new ContactInfoDetailsPanel(); + + /** + * The left side of this frame that contains a list of all sub-contacts + * associated with the selected contact. + */ + protected ContactInfoContactPanel contactPanel; + + /** + * The contact that was right clicked on. The sub-contacts of contactItem + * will be the ones selectable in contactPanel. + */ + protected MetaContact metaContact; + + /** + * Accepts a MetaContact and constructs a frame with ContactInfoSearchPanel + * on the left and an information interface, ContactInfoDetailsPanel, + * on the right. + * @param metaContact the sub-contacts of this MetaContact that was right + * clicked on will be the ones selectable in contactPanel. + */ + public ContactInfoDialog(MetaContact metaContact) + { + this.metaContact = metaContact; + + this.setTitle(Resources.getString("plugin.contactinfo.TITLE") + + ": " + + metaContact.getDisplayName()); + + Iterator subContacts = metaContact.getContacts(); + + this.contactPanel + = new ContactInfoContactPanel(subContacts, this); + + Container contentPane = getContentPane(); + contentPane.add(contactPanel, BorderLayout.WEST); + contentPane.add(detailsPanel, BorderLayout.CENTER); + + this.pack(); + } + + /** + * Loads the details of the given contact. + * + * @param contact the Contact, which details we load + */ + public void loadContactDetails(Contact contact) + { + this.detailsPanel.loadContactDetails(contact); + } + + @Override + protected void close(boolean isEscaped) + { + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java index abf4e25..11cea23 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,165 +15,165 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -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.service.resources.*; - -/** - * - * @author Adam Goldstein - */ -public class ContactInfoMenuItem - extends AbstractPluginComponent - implements ActionListener -{ - private AbstractButton menuItem = null; - - private MetaContact metaContact; - - /** - * The button index, for now placed on last position. - */ - private final static int CONTACT_INFO_BUTTON_IX = 50; - - /** - * Creates a ContactInfoMenuItem. - */ - public ContactInfoMenuItem(PluginComponentFactory parentFactory) - { - this(Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU, parentFactory); - } - - /** - * Creates a ContactInfoMenuItem. - */ - public ContactInfoMenuItem(Container container, - PluginComponentFactory parentFactory) - { - super(container, parentFactory); - } - - /** - * Sets the currently selected MetaContact. - * @param metaContact the currently selected meta contact - */ - @Override - public void setCurrentContact(MetaContact metaContact) - { - this.metaContact = metaContact; - } - - /* - * Implements PluginComponent#setCurrentContact(Contact). - * @param contact the currently selected contact - */ - @Override - public void setCurrentContact(Contact contact) - { - if(metaContact == null) - { - // search for the metacontact - MetaContactListService mcs = - ContactInfoActivator.getContactListService(); - - metaContact = - mcs.findMetaContactByContact(contact); - } - } - - /** - * Initializes and shows the contact details dialog. - */ - public void actionPerformed(ActionEvent e) - { - if(metaContact == null) - return; - - ContactInfoDialog cinfoDialog = new ContactInfoDialog(metaContact); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - cinfoDialog.setLocation( - screenSize.width/2 - cinfoDialog.getWidth()/2, - screenSize.height/2 - cinfoDialog.getHeight()/2); - cinfoDialog.setVisible(true); - } - - public Object getComponent() - { - return getMenuItem(); - } - - public String getName() - { - return getMenuItem().getText(); - } - - private AbstractButton getMenuItem() - { - if(menuItem == null) - { - if(getContainer().equals(Container.CONTAINER_CHAT_TOOL_BAR)) - { - menuItem = - new SIPCommButton(null, - (Image)ContactInfoActivator.getImageLoaderService() - .getImage(new ImageID( - "plugin.contactinfo.CONTACT_INFO_TOOLBAR"))) - { - /** - * Returns the button index. - * @return the button index. - */ - public int getIndex() - { - return CONTACT_INFO_BUTTON_IX; - } - }; - - menuItem.setPreferredSize(new Dimension(25, 25)); - menuItem.setToolTipText( - Resources.getString("service.gui.CONTACT_INFO")); - } - else if(getContainer().equals(Container.CONTAINER_CALL_DIALOG)) - { - menuItem = - new SIPCommButton(null, - (Image)ContactInfoActivator.getImageLoaderService() - .getImage(new ImageID( - "plugin.contactinfo.CONTACT_INFO_CALL_WINDOW"))) - { - /** - * Returns the button index. - * @return the button index. - */ - public int getIndex() - { - return CONTACT_INFO_BUTTON_IX; - } - }; - menuItem.setPreferredSize(new Dimension(44, 38)); - menuItem.setToolTipText( - Resources.getString("service.gui.CONTACT_INFO")); - } - else - menuItem = - new JMenuItem( - Resources.getString("service.gui.CONTACT_INFO"), - new ImageIcon(Resources.getImage( - "plugin.contactinfo.CONTACT_INFO_ICON"))); - menuItem.addActionListener(this); - } - - return menuItem; - } -} +package net.java.sip.communicator.plugin.contactinfo; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +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.service.resources.*; + +/** + * + * @author Adam Goldstein + */ +public class ContactInfoMenuItem + extends AbstractPluginComponent + implements ActionListener +{ + private AbstractButton menuItem = null; + + private MetaContact metaContact; + + /** + * The button index, for now placed on last position. + */ + private final static int CONTACT_INFO_BUTTON_IX = 50; + + /** + * Creates a ContactInfoMenuItem. + */ + public ContactInfoMenuItem(PluginComponentFactory parentFactory) + { + this(Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU, parentFactory); + } + + /** + * Creates a ContactInfoMenuItem. + */ + public ContactInfoMenuItem(Container container, + PluginComponentFactory parentFactory) + { + super(container, parentFactory); + } + + /** + * Sets the currently selected MetaContact. + * @param metaContact the currently selected meta contact + */ + @Override + public void setCurrentContact(MetaContact metaContact) + { + this.metaContact = metaContact; + } + + /* + * Implements PluginComponent#setCurrentContact(Contact). + * @param contact the currently selected contact + */ + @Override + public void setCurrentContact(Contact contact) + { + if(metaContact == null) + { + // search for the metacontact + MetaContactListService mcs = + ContactInfoActivator.getContactListService(); + + metaContact = + mcs.findMetaContactByContact(contact); + } + } + + /** + * Initializes and shows the contact details dialog. + */ + public void actionPerformed(ActionEvent e) + { + if(metaContact == null) + return; + + ContactInfoDialog cinfoDialog = new ContactInfoDialog(metaContact); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + cinfoDialog.setLocation( + screenSize.width/2 - cinfoDialog.getWidth()/2, + screenSize.height/2 - cinfoDialog.getHeight()/2); + cinfoDialog.setVisible(true); + } + + public Object getComponent() + { + return getMenuItem(); + } + + public String getName() + { + return getMenuItem().getText(); + } + + private AbstractButton getMenuItem() + { + if(menuItem == null) + { + if(getContainer().equals(Container.CONTAINER_CHAT_TOOL_BAR)) + { + menuItem = + new SIPCommButton(null, + (Image)ContactInfoActivator.getImageLoaderService() + .getImage(new ImageID( + "plugin.contactinfo.CONTACT_INFO_TOOLBAR"))) + { + /** + * Returns the button index. + * @return the button index. + */ + public int getIndex() + { + return CONTACT_INFO_BUTTON_IX; + } + }; + + menuItem.setPreferredSize(new Dimension(25, 25)); + menuItem.setToolTipText( + Resources.getString("service.gui.CONTACT_INFO")); + } + else if(getContainer().equals(Container.CONTAINER_CALL_DIALOG)) + { + menuItem = + new SIPCommButton(null, + (Image)ContactInfoActivator.getImageLoaderService() + .getImage(new ImageID( + "plugin.contactinfo.CONTACT_INFO_CALL_WINDOW"))) + { + /** + * Returns the button index. + * @return the button index. + */ + public int getIndex() + { + return CONTACT_INFO_BUTTON_IX; + } + }; + menuItem.setPreferredSize(new Dimension(44, 38)); + menuItem.setToolTipText( + Resources.getString("service.gui.CONTACT_INFO")); + } + else + menuItem = + new JMenuItem( + Resources.getString("service.gui.CONTACT_INFO"), + new ImageIcon(Resources.getImage( + "plugin.contactinfo.CONTACT_INFO_ICON"))); + menuItem.addActionListener(this); + } + + return menuItem; + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/Resources.java b/src/net/java/sip/communicator/plugin/contactinfo/Resources.java index 0c8f870..f0f31f1 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/Resources.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/Resources.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,79 +15,79 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.awt.*; -import java.awt.image.*; -import java.io.*; - -import javax.imageio.*; - -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author Yana Stamcheva - */ -public class Resources { - - private static Logger log = Logger.getLogger(Resources.class); - - private static ResourceManagementService resourcesService; - - /** - * Returns an internationalized string corresponding to the given key. - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static Image getImage(String imageID) - { - BufferedImage image = null; - - InputStream in = - getResources().getImageInputStream(imageID); - - if(in == null) - return null; - - try - { - image = ImageIO.read(in); - } - catch (IOException e) - { - log.error("Failed to load image:" + imageID, e); - } - - return image; - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(ContactInfoActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.contactinfo; + +import java.awt.*; +import java.awt.image.*; +import java.io.*; + +import javax.imageio.*; + +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; + +/** + * The Resources class manages the access to the internationalization + * properties files and the image resources used in this plugin. + * + * @author Yana Stamcheva + */ +public class Resources { + + private static Logger log = Logger.getLogger(Resources.class); + + private static ResourceManagementService resourcesService; + + /** + * Returns an internationalized string corresponding to the given key. + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + return getResources().getI18NString(key); + } + + /** + * Loads an image from a given image identifier. + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static Image getImage(String imageID) + { + BufferedImage image = null; + + InputStream in = + getResources().getImageInputStream(imageID); + + if(in == null) + return null; + + try + { + image = ImageIO.read(in); + } + catch (IOException e) + { + log.error("Failed to load image:" + imageID, e); + } + + return image; + } + + /** + * Returns the ResourceManagementService. + * + * @return the ResourceManagementService. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(ContactInfoActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/desktoputil/ColoredDefaultText.java b/src/net/java/sip/communicator/plugin/desktoputil/ColoredDefaultText.java index 59dcb5d..e70f57e 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/ColoredDefaultText.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/ColoredDefaultText.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,43 +15,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil; - -import java.awt.*; - -/** - * The purpose of this interface is to allow UI components with a default - * text value to give the default text its own colour, set independently of - * the normal text colour. - * @author Tom Denham - */ -public interface ColoredDefaultText -{ - /** - * Sets the foreground color. - * - * @param c the color to set for the text field foreground - */ - public void setForegroundColor(Color c); - - /** - * Gets the foreground color. - * - * @return the color of the text - */ - public Color getForegroundColor(); - - /** - * Sets the foreground color of the default text shown in this text field. - * - * @param c the color to set - */ - public void setDefaultTextColor(Color c); - - /** - * Gets the foreground color of the default text shown in this text field. - * - * @return the color of the default text - */ - public Color getDefaultTextColor(); +package net.java.sip.communicator.plugin.desktoputil; + +import java.awt.*; + +/** + * The purpose of this interface is to allow UI components with a default + * text value to give the default text its own colour, set independently of + * the normal text colour. + * @author Tom Denham + */ +public interface ColoredDefaultText +{ + /** + * Sets the foreground color. + * + * @param c the color to set for the text field foreground + */ + public void setForegroundColor(Color c); + + /** + * Gets the foreground color. + * + * @return the color of the text + */ + public Color getForegroundColor(); + + /** + * Sets the foreground color of the default text shown in this text field. + * + * @param c the color to set + */ + public void setDefaultTextColor(Color c); + + /** + * Gets the foreground color of the default text shown in this text field. + * + * @return the color of the default text + */ + public Color getDefaultTextColor(); } diff --git a/src/net/java/sip/communicator/plugin/desktoputil/SIPCommCheckBox.java b/src/net/java/sip/communicator/plugin/desktoputil/SIPCommCheckBox.java index e263415..45c2e69 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/SIPCommCheckBox.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/SIPCommCheckBox.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,45 +15,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil; - -import javax.swing.*; - -import org.jitsi.util.*; - -/** - * @author Lubomir Marinov - */ -public class SIPCommCheckBox - extends JCheckBox -{ - private static final long serialVersionUID = 0L; - - private static final boolean setContentAreaFilled = (OSUtils.IS_WINDOWS - || OSUtils.IS_LINUX); - - public SIPCommCheckBox() - { - init(); - } - - public SIPCommCheckBox(String text) - { - super(text); - - init(); - } - - public SIPCommCheckBox(String text, boolean selected) - { - super(text, selected); - - init(); - } - - private void init() - { - if (setContentAreaFilled) - setContentAreaFilled(false); - } -} +package net.java.sip.communicator.plugin.desktoputil; + +import javax.swing.*; + +import org.jitsi.util.*; + +/** + * @author Lubomir Marinov + */ +public class SIPCommCheckBox + extends JCheckBox +{ + private static final long serialVersionUID = 0L; + + private static final boolean setContentAreaFilled = (OSUtils.IS_WINDOWS + || OSUtils.IS_LINUX); + + public SIPCommCheckBox() + { + init(); + } + + public SIPCommCheckBox(String text) + { + super(text); + + init(); + } + + public SIPCommCheckBox(String text, boolean selected) + { + super(text, selected); + + init(); + } + + private void init() + { + if (setContentAreaFilled) + setContentAreaFilled(false); + } +} diff --git a/src/net/java/sip/communicator/plugin/desktoputil/SIPCommRadioButton.java b/src/net/java/sip/communicator/plugin/desktoputil/SIPCommRadioButton.java index 7089c99..1132c72 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/SIPCommRadioButton.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/SIPCommRadioButton.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,45 +15,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil; - -import javax.swing.*; - -import org.jitsi.util.*; - -/** - * @author Ingo Bauersachs - */ -public class SIPCommRadioButton - extends JRadioButton -{ - private static final long serialVersionUID = 0L; - - private static final boolean setContentAreaFilled = (OSUtils.IS_WINDOWS - || OSUtils.IS_LINUX); - - public SIPCommRadioButton() - { - init(); - } - - public SIPCommRadioButton(String text) - { - super(text); - - init(); - } - - public SIPCommRadioButton(String text, boolean selected) - { - super(text, selected); - - init(); - } - - private void init() - { - if (setContentAreaFilled) - setContentAreaFilled(false); - } -} +package net.java.sip.communicator.plugin.desktoputil; + +import javax.swing.*; + +import org.jitsi.util.*; + +/** + * @author Ingo Bauersachs + */ +public class SIPCommRadioButton + extends JRadioButton +{ + private static final long serialVersionUID = 0L; + + private static final boolean setContentAreaFilled = (OSUtils.IS_WINDOWS + || OSUtils.IS_LINUX); + + public SIPCommRadioButton() + { + init(); + } + + public SIPCommRadioButton(String text) + { + super(text); + + init(); + } + + public SIPCommRadioButton(String text, boolean selected) + { + super(text, selected); + + init(); + } + + private void init() + { + if (setContentAreaFilled) + setContentAreaFilled(false); + } +} diff --git a/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomDestroyReasonDialog.java b/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomDestroyReasonDialog.java index 443171b..ad05797 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomDestroyReasonDialog.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomDestroyReasonDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,175 +15,175 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil.chat; - -import java.awt.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; - -/** - * Dialog with fields for reason and alternate address. - * - * @author Hristo Terezov - */ -public class ChatRoomDestroyReasonDialog extends MessageDialog -{ - /** - * The Logger used by the ChatRoomDestroyReasonDialog - * class and its instances for logging output. - */ - private static Logger logger - = Logger.getLogger(ChatRoomDestroyReasonDialog.class); - - /** - * Serial id. - */ - private static final long serialVersionUID = -916498752420264164L; - - /** - * Text field for the alternate address. - */ - private SIPCommTextField alternateAddress - = new SIPCommTextField("chatroom@example.com"); - - /** - * Text field for reason text. - */ - private JTextField reasonField = new JTextField(); - - /** - * Constructs new chat room destroy dialog. - * - * @param title the title of the dialog - * @param message the message shown in this dialog - */ - public ChatRoomDestroyReasonDialog(String title, String message) - { - super(null, title, message, - DesktopUtilActivator.getResources().getI18NString("service.gui.OK"), - false); - this.setIcon((ImageIcon)null); - - alternateAddress.setFont(alternateAddress.getFont().deriveFont(12f)); - - JLabel altAddressLabel - = new JLabel(DesktopUtilActivator.getResources() - .getI18NString("service.gui.ALTERNATE_ADDRESS") + ":"); - - JLabel reasonLabel - = new JLabel(DesktopUtilActivator.getResources() - .getI18NString("service.gui.REASON") + ":"); - - JPanel labelsPanel = new JPanel(new GridLayout(2, 1)); - labelsPanel.add(reasonLabel); - labelsPanel.add(altAddressLabel); - - JPanel valuesPanel = new JPanel(new GridLayout(2, 1)); - valuesPanel.add(reasonField); - valuesPanel.add(alternateAddress); - - JPanel fieldsPanel = new JPanel(new BorderLayout()); - fieldsPanel .add(labelsPanel, BorderLayout.WEST); - - fieldsPanel.add(valuesPanel, BorderLayout.CENTER); - fieldsPanel.add(new JLabel(" "), BorderLayout.EAST); - fieldsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - fieldsPanel.setOpaque(false); - - - - replaceCheckBoxPanel(fieldsPanel); - this.pack(); - } - - /** - * Returns the text entered in the alternate address field. - * - * @return the text from the alternate address field. - */ - public String getAlternateAddress() - { - return alternateAddress.getText(); - } - - /** - * Returns the text entered in the reason field. - * - * @return the text from the reason field. - */ - public String getReason() - { - return reasonField.getText(); - } - - /** - * Opens a dialog with a fields for the reason and alternate address and - * returns them. - * - * @return array with the reason and alternate address values. - */ - public static String[] getDestroyOptions() - { - final ChatRoomDestroyReasonDialog[] res - = new ChatRoomDestroyReasonDialog[1]; - - try - { - SwingUtilities.invokeAndWait(new Runnable() - { - @Override - public void run() - { - ResourceManagementService R - = DesktopUtilActivator.getResources(); - - res[0] = new ChatRoomDestroyReasonDialog( - R.getI18NString("service.gui.DESTROY_CHATROOM"), - R.getI18NString("service.gui.DESTROY_MESSAGE")); - } - }); - } - catch(Throwable t) - { - logger.error("Error creating dialog", t); - return null; - } - - ChatRoomDestroyReasonDialog reasonDialog = res[0]; - - int result = reasonDialog.showDialog(); - - String destroyOptions[] = new String[2]; - - if (result == MessageDialog.OK_RETURN_CODE) - { - destroyOptions[0] = proccessFieldValues(reasonDialog.getReason()); - destroyOptions[1] - = proccessFieldValues(reasonDialog.getAlternateAddress()); - } - else - { - destroyOptions = null; - } - - - return destroyOptions; - } - - private static String proccessFieldValues(String value) - { - if(value != null) - { - value = value.trim(); - if(value.equals("")) - value = null; - } - return value; - } - -} +package net.java.sip.communicator.plugin.desktoputil.chat; + +import java.awt.*; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; + +/** + * Dialog with fields for reason and alternate address. + * + * @author Hristo Terezov + */ +public class ChatRoomDestroyReasonDialog extends MessageDialog +{ + /** + * The Logger used by the ChatRoomDestroyReasonDialog + * class and its instances for logging output. + */ + private static Logger logger + = Logger.getLogger(ChatRoomDestroyReasonDialog.class); + + /** + * Serial id. + */ + private static final long serialVersionUID = -916498752420264164L; + + /** + * Text field for the alternate address. + */ + private SIPCommTextField alternateAddress + = new SIPCommTextField("chatroom@example.com"); + + /** + * Text field for reason text. + */ + private JTextField reasonField = new JTextField(); + + /** + * Constructs new chat room destroy dialog. + * + * @param title the title of the dialog + * @param message the message shown in this dialog + */ + public ChatRoomDestroyReasonDialog(String title, String message) + { + super(null, title, message, + DesktopUtilActivator.getResources().getI18NString("service.gui.OK"), + false); + this.setIcon((ImageIcon)null); + + alternateAddress.setFont(alternateAddress.getFont().deriveFont(12f)); + + JLabel altAddressLabel + = new JLabel(DesktopUtilActivator.getResources() + .getI18NString("service.gui.ALTERNATE_ADDRESS") + ":"); + + JLabel reasonLabel + = new JLabel(DesktopUtilActivator.getResources() + .getI18NString("service.gui.REASON") + ":"); + + JPanel labelsPanel = new JPanel(new GridLayout(2, 1)); + labelsPanel.add(reasonLabel); + labelsPanel.add(altAddressLabel); + + JPanel valuesPanel = new JPanel(new GridLayout(2, 1)); + valuesPanel.add(reasonField); + valuesPanel.add(alternateAddress); + + JPanel fieldsPanel = new JPanel(new BorderLayout()); + fieldsPanel .add(labelsPanel, BorderLayout.WEST); + + fieldsPanel.add(valuesPanel, BorderLayout.CENTER); + fieldsPanel.add(new JLabel(" "), BorderLayout.EAST); + fieldsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + fieldsPanel.setOpaque(false); + + + + replaceCheckBoxPanel(fieldsPanel); + this.pack(); + } + + /** + * Returns the text entered in the alternate address field. + * + * @return the text from the alternate address field. + */ + public String getAlternateAddress() + { + return alternateAddress.getText(); + } + + /** + * Returns the text entered in the reason field. + * + * @return the text from the reason field. + */ + public String getReason() + { + return reasonField.getText(); + } + + /** + * Opens a dialog with a fields for the reason and alternate address and + * returns them. + * + * @return array with the reason and alternate address values. + */ + public static String[] getDestroyOptions() + { + final ChatRoomDestroyReasonDialog[] res + = new ChatRoomDestroyReasonDialog[1]; + + try + { + SwingUtilities.invokeAndWait(new Runnable() + { + @Override + public void run() + { + ResourceManagementService R + = DesktopUtilActivator.getResources(); + + res[0] = new ChatRoomDestroyReasonDialog( + R.getI18NString("service.gui.DESTROY_CHATROOM"), + R.getI18NString("service.gui.DESTROY_MESSAGE")); + } + }); + } + catch(Throwable t) + { + logger.error("Error creating dialog", t); + return null; + } + + ChatRoomDestroyReasonDialog reasonDialog = res[0]; + + int result = reasonDialog.showDialog(); + + String destroyOptions[] = new String[2]; + + if (result == MessageDialog.OK_RETURN_CODE) + { + destroyOptions[0] = proccessFieldValues(reasonDialog.getReason()); + destroyOptions[1] + = proccessFieldValues(reasonDialog.getAlternateAddress()); + } + else + { + destroyOptions = null; + } + + + return destroyOptions; + } + + private static String proccessFieldValues(String value) + { + if(value != null) + { + value = value.trim(); + if(value.equals("")) + value = null; + } + return value; + } + +} diff --git a/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomJoinOptionsDialog.java b/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomJoinOptionsDialog.java index 88a5327..db04c56 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomJoinOptionsDialog.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/chat/ChatRoomJoinOptionsDialog.java @@ -1,4 +1,4 @@ -/** +/** * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,174 +15,174 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil.chat; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; -import javax.swing.border.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Dialog with fields for nickname and subject. - * - * @author Hristo Terezov - */ -public class ChatRoomJoinOptionsDialog extends ChatOperationReasonDialog -{ - /** - * Serial id. - */ - private static final long serialVersionUID = -916498752420264164L; - - /** - * Text field for the subject. - */ - private SIPCommTextField subject = new SIPCommTextField(DesktopUtilActivator - .getResources().getI18NString("service.gui.SUBJECT")); - - /** - * Label that hides and shows the subject fields panel on click. - */ - private JLabel cmdExpandSubjectFields; - - /** - * Panel that holds the subject fields. - */ - private JPanel subjectFieldsPannel = new JPanel(new BorderLayout()); - - /** - * Adds the subject fields to dialog. Sets action listeners. - * - * @param title the title of the dialog - * @param message the message shown in this dialog - * @param disableOKIfReasonIsEmpty if true the OK button will be - * disabled if the reason text is empty. - * @param showReasonLabel specify if we want the "Reason:" label - * @param dontDisplaySubjectFields if true the sibject fields will be - * hidden. - */ - public ChatRoomJoinOptionsDialog(String title, String message, - boolean showReasonLabel, - boolean disableOKIfReasonIsEmpty, - boolean dontDisplaySubjectFields) - { - super(title, - message, - showReasonLabel, - disableOKIfReasonIsEmpty); - - if(dontDisplaySubjectFields) - return; - - JPanel subjectPanel = new JPanel(new BorderLayout()); - subjectPanel.setOpaque(false); - subjectPanel.setBorder( - BorderFactory.createEmptyBorder(10, 0, 0, 0)); - - subjectFieldsPannel.setBorder( - BorderFactory.createEmptyBorder(10, 30, 0, 0)); - subjectFieldsPannel.setOpaque(false); - subjectFieldsPannel.add(subject, BorderLayout.CENTER); - subjectFieldsPannel.setVisible(false); - subject.setFont(getFont().deriveFont(12f)); - - cmdExpandSubjectFields = new JLabel(); - cmdExpandSubjectFields.setBorder(new EmptyBorder(0, 5, 0, 0)); - cmdExpandSubjectFields.setIcon(DesktopUtilActivator.getResources() - .getImage("service.gui.icons.RIGHT_ARROW_ICON")); - cmdExpandSubjectFields.setText(DesktopUtilActivator - .getResources().getI18NString("service.gui.SET_SUBJECT")); - cmdExpandSubjectFields.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - cmdExpandSubjectFields.setIcon( - UtilActivator.getResources().getImage( - subjectFieldsPannel.isVisible() - ? "service.gui.icons.RIGHT_ARROW_ICON" - : "service.gui.icons.DOWN_ARROW_ICON")); - - subjectFieldsPannel.setVisible( - !subjectFieldsPannel.isVisible()); - - pack(); - } - }); - subjectPanel.add(cmdExpandSubjectFields,BorderLayout.NORTH); - subjectPanel.add(subjectFieldsPannel,BorderLayout.CENTER); - addToReasonFieldPannel(subjectPanel); - this.pack(); - } - - /** - * Returns the text entered in the subject field. - * - * @return the text from the subject field. - */ - public String getSubject() - { - return subject.getText(); - } - - /** - * Opens a dialog with a fields for the nickname and the subject of the room - * and returns them. - * - * @param pps the protocol provider associated with the chat room. - * @param chatRoomId the id of the chat room. - * @param defaultNickname the nickname to show if any - * @return array with the nickname and subject values. - */ - public static String[] getJoinOptions(ProtocolProviderService pps, - String chatRoomId, String defaultNickname) - { - return getJoinOptions(false, pps, chatRoomId, defaultNickname); - } - - /** - * Opens a dialog with a fields for the nickname and the subject of the room - * and returns them. - * - * @param dontDisplaySubjectFields if true the subject fields will be hidden - * @param pps the protocol provider associated with the chat room. - * @param chatRoomId the id of the chat room. - * @param defaultNickname the nickname to show if any - * @return array with the nickname and subject values. - */ - public static String[] getJoinOptions(boolean dontDisplaySubjectFields, - ProtocolProviderService pps, String chatRoomId, String defaultNickname) - { - String nickName = null; - ChatRoomJoinOptionsDialog reasonDialog = - new ChatRoomJoinOptionsDialog(DesktopUtilActivator.getResources() - .getI18NString("service.gui.CHANGE_NICKNAME"), - DesktopUtilActivator.getResources().getI18NString( - "service.gui.CHANGE_NICKNAME_LABEL"), false, true, - dontDisplaySubjectFields); - reasonDialog.setIcon(new ImageIcon(DesktopUtilActivator.getImage( - "service.gui.icons.CHANGE_NICKNAME_16x16"))); - - if(defaultNickname != null) - reasonDialog.setReasonFieldText(defaultNickname); - - int result = reasonDialog.showDialog(); - - if (result == MessageDialog.OK_RETURN_CODE) - { - nickName = reasonDialog.getReason().trim(); - ConfigurationUtils.updateChatRoomProperty( - pps, - chatRoomId, "userNickName", nickName); - - } - String[] joinOptions = {nickName, reasonDialog.getSubject()}; - return joinOptions; - } - -} +package net.java.sip.communicator.plugin.desktoputil.chat; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.border.*; + +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * Dialog with fields for nickname and subject. + * + * @author Hristo Terezov + */ +public class ChatRoomJoinOptionsDialog extends ChatOperationReasonDialog +{ + /** + * Serial id. + */ + private static final long serialVersionUID = -916498752420264164L; + + /** + * Text field for the subject. + */ + private SIPCommTextField subject = new SIPCommTextField(DesktopUtilActivator + .getResources().getI18NString("service.gui.SUBJECT")); + + /** + * Label that hides and shows the subject fields panel on click. + */ + private JLabel cmdExpandSubjectFields; + + /** + * Panel that holds the subject fields. + */ + private JPanel subjectFieldsPannel = new JPanel(new BorderLayout()); + + /** + * Adds the subject fields to dialog. Sets action listeners. + * + * @param title the title of the dialog + * @param message the message shown in this dialog + * @param disableOKIfReasonIsEmpty if true the OK button will be + * disabled if the reason text is empty. + * @param showReasonLabel specify if we want the "Reason:" label + * @param dontDisplaySubjectFields if true the sibject fields will be + * hidden. + */ + public ChatRoomJoinOptionsDialog(String title, String message, + boolean showReasonLabel, + boolean disableOKIfReasonIsEmpty, + boolean dontDisplaySubjectFields) + { + super(title, + message, + showReasonLabel, + disableOKIfReasonIsEmpty); + + if(dontDisplaySubjectFields) + return; + + JPanel subjectPanel = new JPanel(new BorderLayout()); + subjectPanel.setOpaque(false); + subjectPanel.setBorder( + BorderFactory.createEmptyBorder(10, 0, 0, 0)); + + subjectFieldsPannel.setBorder( + BorderFactory.createEmptyBorder(10, 30, 0, 0)); + subjectFieldsPannel.setOpaque(false); + subjectFieldsPannel.add(subject, BorderLayout.CENTER); + subjectFieldsPannel.setVisible(false); + subject.setFont(getFont().deriveFont(12f)); + + cmdExpandSubjectFields = new JLabel(); + cmdExpandSubjectFields.setBorder(new EmptyBorder(0, 5, 0, 0)); + cmdExpandSubjectFields.setIcon(DesktopUtilActivator.getResources() + .getImage("service.gui.icons.RIGHT_ARROW_ICON")); + cmdExpandSubjectFields.setText(DesktopUtilActivator + .getResources().getI18NString("service.gui.SET_SUBJECT")); + cmdExpandSubjectFields.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + cmdExpandSubjectFields.setIcon( + UtilActivator.getResources().getImage( + subjectFieldsPannel.isVisible() + ? "service.gui.icons.RIGHT_ARROW_ICON" + : "service.gui.icons.DOWN_ARROW_ICON")); + + subjectFieldsPannel.setVisible( + !subjectFieldsPannel.isVisible()); + + pack(); + } + }); + subjectPanel.add(cmdExpandSubjectFields,BorderLayout.NORTH); + subjectPanel.add(subjectFieldsPannel,BorderLayout.CENTER); + addToReasonFieldPannel(subjectPanel); + this.pack(); + } + + /** + * Returns the text entered in the subject field. + * + * @return the text from the subject field. + */ + public String getSubject() + { + return subject.getText(); + } + + /** + * Opens a dialog with a fields for the nickname and the subject of the room + * and returns them. + * + * @param pps the protocol provider associated with the chat room. + * @param chatRoomId the id of the chat room. + * @param defaultNickname the nickname to show if any + * @return array with the nickname and subject values. + */ + public static String[] getJoinOptions(ProtocolProviderService pps, + String chatRoomId, String defaultNickname) + { + return getJoinOptions(false, pps, chatRoomId, defaultNickname); + } + + /** + * Opens a dialog with a fields for the nickname and the subject of the room + * and returns them. + * + * @param dontDisplaySubjectFields if true the subject fields will be hidden + * @param pps the protocol provider associated with the chat room. + * @param chatRoomId the id of the chat room. + * @param defaultNickname the nickname to show if any + * @return array with the nickname and subject values. + */ + public static String[] getJoinOptions(boolean dontDisplaySubjectFields, + ProtocolProviderService pps, String chatRoomId, String defaultNickname) + { + String nickName = null; + ChatRoomJoinOptionsDialog reasonDialog = + new ChatRoomJoinOptionsDialog(DesktopUtilActivator.getResources() + .getI18NString("service.gui.CHANGE_NICKNAME"), + DesktopUtilActivator.getResources().getI18NString( + "service.gui.CHANGE_NICKNAME_LABEL"), false, true, + dontDisplaySubjectFields); + reasonDialog.setIcon(new ImageIcon(DesktopUtilActivator.getImage( + "service.gui.icons.CHANGE_NICKNAME_16x16"))); + + if(defaultNickname != null) + reasonDialog.setReasonFieldText(defaultNickname); + + int result = reasonDialog.showDialog(); + + if (result == MessageDialog.OK_RETURN_CODE) + { + nickName = reasonDialog.getReason().trim(); + ConfigurationUtils.updateChatRoomProperty( + pps, + chatRoomId, "userNickName", nickName); + + } + String[] joinOptions = {nickName, reasonDialog.getSubject()}; + return joinOptions; + } + +} diff --git a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java index 2400644..3a7b2b9 100644 --- a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java +++ b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,199 +15,199 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.facebookaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the FacebookAccountRegistrationWizard in the UI Service. - * - * @author Dai Zhiwei - */ -public class FacebookAccRegWizzActivator - extends AbstractServiceDependentActivator -{ - /** - * The logger. - */ - private static Logger logger - = Logger.getLogger(FacebookAccRegWizzActivator.class.getName()); - - /** - * A currently valid bundle context. - */ - public static BundleContext bundleContext; - - /** - * The container. - */ - private static WizardContainer wizardContainer; - - /** - * Registration wizard. - */ - private static FacebookAccountRegistrationWizard facebookWizard; - - /** - * The UI service. - */ - private static UIService uiService; - - /** - * The browser launcher service. - */ - private static BrowserLauncherService browserLauncherService; - - private static ResourceManagementService resourcesService; - - /** - * Starts this bundle. - */ - @Override - public void start(Object dependentService) - { - if (logger.isInfoEnabled()) - logger.info("Loading facebook account wizard."); - - uiService = (UIService)dependentService; - - wizardContainer = uiService.getAccountRegWizardContainer(); - - facebookWizard - = new FacebookAccountRegistrationWizard(wizardContainer); - - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.FACEBOOK); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - facebookWizard, - containerFilter); - - if (logger.isInfoEnabled()) - logger.info("Facebook account registration wizard [STARTED]."); - } - - /** - * The dependent class. We are waiting for the ui service. - * @return the ui service class. - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * The bundle context to use. - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param bundleContext The execution context of the bundle being stopped. - */ - public void stop(BundleContext bundleContext) - { - } - - /** - * Returns the ProtocolProviderFactory for the Facebook protocol. - * @return the ProtocolProviderFactory for the Facebook protocol - */ - public static ProtocolProviderFactory getFacebookProtocolProviderFactory() - { - - ServiceReference[] serRefs = null; - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" + ProtocolNames.JABBER + ")"; - - try - { - serRefs = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error("FacebookAccRegWizzActivator : " + ex); - } - - return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); - } - - /** - * Returns the bundleContext that we received when we were started. - * - * @return a currently valid instance of a bundleContext. - */ - public BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Gets the browser launcher service. - * @return the browser launcher service. - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - ServiceReference serviceReference = - bundleContext.getServiceReference(BrowserLauncherService.class - .getName()); - - browserLauncherService = - (BrowserLauncherService) bundleContext - .getService(serviceReference); - } - - return browserLauncherService; - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(FacebookAccRegWizzActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.facebookaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * Registers the FacebookAccountRegistrationWizard in the UI Service. + * + * @author Dai Zhiwei + */ +public class FacebookAccRegWizzActivator + extends AbstractServiceDependentActivator +{ + /** + * The logger. + */ + private static Logger logger + = Logger.getLogger(FacebookAccRegWizzActivator.class.getName()); + + /** + * A currently valid bundle context. + */ + public static BundleContext bundleContext; + + /** + * The container. + */ + private static WizardContainer wizardContainer; + + /** + * Registration wizard. + */ + private static FacebookAccountRegistrationWizard facebookWizard; + + /** + * The UI service. + */ + private static UIService uiService; + + /** + * The browser launcher service. + */ + private static BrowserLauncherService browserLauncherService; + + private static ResourceManagementService resourcesService; + + /** + * Starts this bundle. + */ + @Override + public void start(Object dependentService) + { + if (logger.isInfoEnabled()) + logger.info("Loading facebook account wizard."); + + uiService = (UIService)dependentService; + + wizardContainer = uiService.getAccountRegWizardContainer(); + + facebookWizard + = new FacebookAccountRegistrationWizard(wizardContainer); + + Hashtable containerFilter + = new Hashtable(); + + containerFilter.put( + ProtocolProviderFactory.PROTOCOL, + ProtocolNames.FACEBOOK); + + bundleContext.registerService( + AccountRegistrationWizard.class.getName(), + facebookWizard, + containerFilter); + + if (logger.isInfoEnabled()) + logger.info("Facebook account registration wizard [STARTED]."); + } + + /** + * The dependent class. We are waiting for the ui service. + * @return the ui service class. + */ + @Override + public Class getDependentServiceClass() + { + return UIService.class; + } + + /** + * The bundle context to use. + * @param context the context to set. + */ + @Override + public void setBundleContext(BundleContext context) + { + bundleContext = context; + } + + /** + * Called when this bundle is stopped so the Framework can perform the + * bundle-specific activities necessary to stop the bundle. + * + * @param bundleContext The execution context of the bundle being stopped. + */ + public void stop(BundleContext bundleContext) + { + } + + /** + * Returns the ProtocolProviderFactory for the Facebook protocol. + * @return the ProtocolProviderFactory for the Facebook protocol + */ + public static ProtocolProviderFactory getFacebookProtocolProviderFactory() + { + + ServiceReference[] serRefs = null; + + String osgiFilter = "(" + + ProtocolProviderFactory.PROTOCOL + + "=" + ProtocolNames.JABBER + ")"; + + try + { + serRefs = bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), osgiFilter); + } + catch (InvalidSyntaxException ex) + { + logger.error("FacebookAccRegWizzActivator : " + ex); + } + + return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); + } + + /** + * Returns the bundleContext that we received when we were started. + * + * @return a currently valid instance of a bundleContext. + */ + public BundleContext getBundleContext() + { + return bundleContext; + } + + /** + * Returns the UIService. + * + * @return the UIService + */ + public static UIService getUIService() + { + return uiService; + } + + /** + * Gets the browser launcher service. + * @return the browser launcher service. + */ + public static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncherService == null) + { + ServiceReference serviceReference = + bundleContext.getServiceReference(BrowserLauncherService.class + .getName()); + + browserLauncherService = + (BrowserLauncherService) bundleContext + .getService(serviceReference); + } + + return browserLauncherService; + } + + /** + * Returns the ResourceManagementService. + * + * @return the ResourceManagementService. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(FacebookAccRegWizzActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java index d70282d..896c054 100644 --- a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,286 +15,286 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.facebookaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.jabberaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.jabber.*; - -/** - * The FacebookAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Facebook Chat protocol. It allows - * the user to create and configure a new Facebook account. - * - * @author Dai Zhiwei - * @author Yana Stamcheva - */ -public class FacebookAccountRegistrationWizard - extends JabberAccountRegistrationWizard -{ - /** - * The protocol name. - */ - private static final String PROTOCOL = "Facebook"; - - /** - * A constant pointing to the Facebook protocol logo icon. - */ - private static final String PROTOCOL_ICON - = "service.protocol.facebook.FACEBOOK_16x16"; - - /** - * A constant pointing to the Facebook protocol wizard page image. - */ - private static final String PAGE_IMAGE - = "service.protocol.facebook.FACEBOOK_48x48"; - - private static final String SERVER_ADDRESS = "chat.facebook.com"; - - /** - * Creates an instance of FacebookAccountRegistrationWizard. - * @param wizardContainer the wizard container, where this wizard - * is added - */ - public FacebookAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all facebook specific properties. - * - * @param reg the registration object - */ - private void setPredefinedProperties(JabberAccountRegistration reg) - { - reg.setServerAddress(SERVER_ADDRESS); - reg.setSendKeepAlive(true); - - reg.setServerOverridden(true); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return FacebookAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return FacebookAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: username"; - } - - /** - * Returns the display label used for the sip id field. - * @return the sip id display label string. - */ - @Override - protected String getUsernameLabel() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.USERNAME"); - } - - /** - * Return the string for add existing account button. - * @return the string for add existing account button. - */ - @Override - protected String getCreateAccountButtonLabel() - { - return null; - } - - /** - * Return the string for create new account button. - * @return the string for create new account button. - */ - @Override - protected String getCreateAccountLabel() - { - return FacebookAccRegWizzActivator.getResources().getI18NString( - "plugin.facebookaccregwizz.DESCRIPTION"); - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/facebook"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/facebook/logo32x32.png"; - } - - /** - * Opens a browser on the sign up page. - */ - @Override - public void webSignup() {} - - /** - * Returns true if the web sign up is supported by the current - * implementation, false - otherwise. - * @return true if the web sign up is supported by the current - * implementation, false - otherwise - */ - @Override - public boolean isWebSignupSupported() - { - return false; - } - - /** - * Creates an account for the given user and password. - * - * @param providerFactory the ProtocolProviderFactory which will create - * the account - * @param userName the user identifier - * @param passwd the password - * @return the ProtocolProviderService for the new account. - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - protected ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, - String userName, - String passwd) - throws OperationFailedException - { - // add server part to username - if(userName.indexOf("@") == -1) - userName += "@" + SERVER_ADDRESS; - - return super.installAccount(providerFactory, userName, passwd); - } - - /** - * Returns an instance of CreateAccountService through which the - * user could create an account. This method is meant to be implemented by - * specific protocol provider wizards. - * @return an instance of CreateAccountService - */ - @Override - protected JabberAccountCreationFormService getCreateAccountService() - { - return null; - } - - /** - * Whether the advanced configuration is enabled. Gives an option - * to disable/hide advanced config button. - * @return whether the advanced configuration is enabled. - */ - public boolean isAdvancedConfigurationEnabled() - { - return false; - } -} +package net.java.sip.communicator.plugin.facebookaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.plugin.jabberaccregwizz.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.jabber.*; + +/** + * The FacebookAccountRegistrationWizard is an implementation of the + * AccountRegistrationWizard for the Facebook Chat protocol. It allows + * the user to create and configure a new Facebook account. + * + * @author Dai Zhiwei + * @author Yana Stamcheva + */ +public class FacebookAccountRegistrationWizard + extends JabberAccountRegistrationWizard +{ + /** + * The protocol name. + */ + private static final String PROTOCOL = "Facebook"; + + /** + * A constant pointing to the Facebook protocol logo icon. + */ + private static final String PROTOCOL_ICON + = "service.protocol.facebook.FACEBOOK_16x16"; + + /** + * A constant pointing to the Facebook protocol wizard page image. + */ + private static final String PAGE_IMAGE + = "service.protocol.facebook.FACEBOOK_48x48"; + + private static final String SERVER_ADDRESS = "chat.facebook.com"; + + /** + * Creates an instance of FacebookAccountRegistrationWizard. + * @param wizardContainer the wizard container, where this wizard + * is added + */ + public FacebookAccountRegistrationWizard(WizardContainer wizardContainer) + { + super(wizardContainer); + } + + /** + * Returns the set of pages contained in this wizard. + * @return Iterator + */ + @Override + public Iterator getPages() + { + JabberAccountRegistration reg = new JabberAccountRegistration(); + + setPredefinedProperties(reg); + + return getPages(reg); + } + + /** + * Returns a simple account registration form that would be the first form + * shown to the user. Only if the user needs more settings she'll choose + * to open the advanced wizard, consisted by all pages. + * + * @param isCreateAccount indicates if the simple form should be opened as + * a create account form or as a login form + * @return a simple account registration form + */ + @Override + public Object getSimpleForm(boolean isCreateAccount) + { + JabberAccountRegistration reg = new JabberAccountRegistration(); + + setPredefinedProperties(reg); + + return getSimpleForm(reg, isCreateAccount); + } + + /** + * Sets all facebook specific properties. + * + * @param reg the registration object + */ + private void setPredefinedProperties(JabberAccountRegistration reg) + { + reg.setServerAddress(SERVER_ADDRESS); + reg.setSendKeepAlive(true); + + reg.setServerOverridden(true); + } + + /** + * Implements the AccountRegistrationWizard.getIcon method. + * Returns the icon to be used for this wizard. + * @return byte[] + */ + @Override + public byte[] getIcon() + { + return FacebookAccRegWizzActivator.getResources() + .getImageInBytes(PROTOCOL_ICON); + } + + /** + * Implements the AccountRegistrationWizard.getPageImage method. + * Returns the image used to decorate the wizard page + * + * @return byte[] the image used to decorate the wizard page + */ + @Override + public byte[] getPageImage() + { + return FacebookAccRegWizzActivator.getResources() + .getImageInBytes(PAGE_IMAGE); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolName + * method. Returns the protocol name for this wizard. + * @return String + */ + @Override + public String getProtocolName() + { + return FacebookAccRegWizzActivator.getResources() + .getI18NString("plugin.facebookaccregwizz.PROTOCOL_NAME"); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolDescription + * method. Returns the description of the protocol for this wizard. + * @return String + */ + @Override + public String getProtocolDescription() + { + return FacebookAccRegWizzActivator.getResources() + .getI18NString("plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION"); + } + + /** + * Returns an example string, which should indicate to the user how the + * user name should look like. + * @return an example string, which should indicate to the user how the + * user name should look like. + */ + @Override + public String getUserNameExample() + { + return "Ex: username"; + } + + /** + * Returns the display label used for the sip id field. + * @return the sip id display label string. + */ + @Override + protected String getUsernameLabel() + { + return FacebookAccRegWizzActivator.getResources() + .getI18NString("plugin.facebookaccregwizz.USERNAME"); + } + + /** + * Return the string for add existing account button. + * @return the string for add existing account button. + */ + @Override + protected String getCreateAccountButtonLabel() + { + return null; + } + + /** + * Return the string for create new account button. + * @return the string for create new account button. + */ + @Override + protected String getCreateAccountLabel() + { + return FacebookAccRegWizzActivator.getResources().getI18NString( + "plugin.facebookaccregwizz.DESCRIPTION"); + } + + /** + * Returns the protocol name as listed in "ProtocolNames" or just the name + * of the service. + * @return the protocol name + */ + @Override + public String getProtocol() + { + return PROTOCOL; + } + + /** + * Returns the protocol icon path. + * @return the protocol icon path + */ + @Override + public String getProtocolIconPath() + { + return "resources/images/protocol/facebook"; + } + + /** + * Returns the account icon path. + * @return the account icon path + */ + @Override + public String getAccountIconPath() + { + return "resources/images/protocol/facebook/logo32x32.png"; + } + + /** + * Opens a browser on the sign up page. + */ + @Override + public void webSignup() {} + + /** + * Returns true if the web sign up is supported by the current + * implementation, false - otherwise. + * @return true if the web sign up is supported by the current + * implementation, false - otherwise + */ + @Override + public boolean isWebSignupSupported() + { + return false; + } + + /** + * Creates an account for the given user and password. + * + * @param providerFactory the ProtocolProviderFactory which will create + * the account + * @param userName the user identifier + * @param passwd the password + * @return the ProtocolProviderService for the new account. + * @throws OperationFailedException if the operation didn't succeed + */ + @Override + protected ProtocolProviderService installAccount( + ProtocolProviderFactory providerFactory, + String userName, + String passwd) + throws OperationFailedException + { + // add server part to username + if(userName.indexOf("@") == -1) + userName += "@" + SERVER_ADDRESS; + + return super.installAccount(providerFactory, userName, passwd); + } + + /** + * Returns an instance of CreateAccountService through which the + * user could create an account. This method is meant to be implemented by + * specific protocol provider wizards. + * @return an instance of CreateAccountService + */ + @Override + protected JabberAccountCreationFormService getCreateAccountService() + { + return null; + } + + /** + * Whether the advanced configuration is enabled. Gives an option + * to disable/hide advanced config button. + * @return whether the advanced configuration is enabled. + */ + public boolean isAdvancedConfigurationEnabled() + { + return false; + } +} diff --git a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java index 38a51c6..37bc48f 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/AutoAwayWatcher.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,462 +15,462 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.generalconfig.autoaway; - -import java.beans.*; -import java.util.*; - -import net.java.sip.communicator.plugin.generalconfig.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.sysactivity.*; -import net.java.sip.communicator.service.sysactivity.event.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Listens for idle events from SystemActivityNotifications Service. - * - * @author Damian Minkov - */ -public class AutoAwayWatcher - implements ServiceListener, - RegistrationStateChangeListener -{ - /** - * The logger. - */ - private static final Logger logger - = Logger.getLogger(AutoAwayWatcher.class); - - /** - * The states of providers before going to away. - */ - private final Map lastStates - = new HashMap(); - - /** - * Listens for idle events. - */ - private IdleListener idleListener = null; - - /** - * Creates AutoAway handler. - */ - public AutoAwayWatcher() - { - if (Preferences.isEnabled()) - { - start(); - } - - Preferences.addEnableChangeListener( - new PropertyChangeListener() - { - public void propertyChange(PropertyChangeEvent evt) - { - if(Boolean.parseBoolean((String) evt.getNewValue())) - start(); - else - stopInner(); - } - } - ); - - // listens for changes in configured value. - Preferences.addTimerChangeListener( - new PropertyChangeListener() - { - public void propertyChange(PropertyChangeEvent evt) - { - stopInner(); - start(); - } - } - ); - } - - /** - * Starts and add needed listeners. - */ - private void start() - { - if(idleListener == null) - { - - idleListener = new IdleListener(); - - SystemActivityNotificationsService - systemActivityNotificationsService - = getSystemActivityNotificationsService(); - - systemActivityNotificationsService.addIdleSystemChangeListener( - Preferences.getTimer() * 60 * 1000, - idleListener); - systemActivityNotificationsService - .addSystemActivityChangeListener(idleListener); - - startListeningForNewProviders(); - } - } - - /** - * Start listening for new providers and their registration states. - */ - private void startListeningForNewProviders() - { - // listen for new providers - GeneralConfigPluginActivator.bundleContext.addServiceListener(this); - - // lets check current providers - ServiceReference[] protocolProviderRefs = null; - try - { - protocolProviderRefs = GeneralConfigPluginActivator.bundleContext - .getServiceReferences(ProtocolProviderService.class.getName(), - null); - } - catch (InvalidSyntaxException ex) - { - // this shouldn't happen since we're providing no parameter string - // but let's log just in case. - logger.error( - "Error while retrieving service refs", ex); - return; - } - - // in case we found any - if (protocolProviderRefs != null) - { - for (int i = 0; i < protocolProviderRefs.length; i++) - { - ProtocolProviderService provider = (ProtocolProviderService) - GeneralConfigPluginActivator.bundleContext - .getService(protocolProviderRefs[i]); - - this.handleProviderAdded(provider); - } - } - } - - /** - * Stop listening for new providers and their registration states. - */ - private void stopListeningForNewProviders() - { - // stop listen for new providers - GeneralConfigPluginActivator.bundleContext.removeServiceListener(this); - - // lets check current providers and remove registration state listener - ServiceReference[] protocolProviderRefs = null; - try - { - protocolProviderRefs = GeneralConfigPluginActivator.bundleContext - .getServiceReferences(ProtocolProviderService.class.getName(), - null); - } - catch (InvalidSyntaxException ex) - { - // this shouldn't happen since we're providing no parameter string - // but let's log just in case. - logger.error( - "Error while retrieving service refs", ex); - return; - } - - // in case we found any - if (protocolProviderRefs != null) - { - for (int i = 0; i < protocolProviderRefs.length; i++) - { - ProtocolProviderService provider = (ProtocolProviderService) - GeneralConfigPluginActivator.bundleContext - .getService(protocolProviderRefs[i]); - - this.handleProviderRemoved(provider); - } - } - } - - /** - * Stops and removes the listeners. - */ - public void stop() - { - GeneralConfigPluginActivator.bundleContext.removeServiceListener(this); - stopInner(); - } - - /** - * Stops and removes the listeners. - */ - private void stopInner() - { - if(idleListener != null) - { - SystemActivityNotificationsService - systemActivityNotificationsService - = getSystemActivityNotificationsService(); - - systemActivityNotificationsService.removeIdleSystemChangeListener( - idleListener); - systemActivityNotificationsService - .removeSystemActivityChangeListener(idleListener); - - stopListeningForNewProviders(); - - idleListener = null; - } - } - - /** - * Change protocol to away saving status so it can be set again when - * out of idle state. - */ - private void changeProtocolsToAway() - { - for (ProtocolProviderService protocolProvider - : GeneralConfigPluginActivator.getProtocolProviders()) - { - OperationSetPresence presence - = protocolProvider.getOperationSet( - OperationSetPresence.class); - - if(presence == null) - continue; - - PresenceStatus status = presence.getPresenceStatus(); - - if (status.getStatus() < PresenceStatus.AVAILABLE_THRESHOLD) - { - // already (manually) set to away or lower - continue; - } - - PresenceStatus newStatus - = StatusUpdateThread.findAwayStatus(presence); - - try - { - if (newStatus != null && !status.equals(newStatus)) - { - addProviderToLastStates(protocolProvider, status); - - presence.publishPresenceStatus( - newStatus, - newStatus.getStatusName()); - } - } - catch (IllegalArgumentException e) - { - } - catch (IllegalStateException e) - { - } - catch (OperationFailedException e) - { - } - } - } - - /** - * Back to status which was already saved before going to idle. - */ - private void changeProtocolsToPreviousState() - { - for (ProtocolProviderService protocolProvider - : GeneralConfigPluginActivator.getProtocolProviders()) - { - PresenceStatus lastState = lastStates.get(protocolProvider); - - if (lastState != null) - { - OperationSetPresence presence - = protocolProvider.getOperationSet( - OperationSetPresence.class); - try - { - presence.publishPresenceStatus(lastState, ""); - } - catch (IllegalArgumentException e) - { - } - catch (IllegalStateException e) - { - } - catch (OperationFailedException e) - { - } - removeProviderFromLastStates(protocolProvider); - } - } - } - - /** - * The SystemActivityNotifications Service. - * @return the SystemActivityNotifications Service. - */ - private SystemActivityNotificationsService - getSystemActivityNotificationsService() - { - return - ServiceUtils.getService( - GeneralConfigPluginActivator.bundleContext, - SystemActivityNotificationsService.class); - } - - /** - * When new protocol provider is registered we add our - * registration change listener. - * If unregistered remove reference to the provider and the - * registration change listener. - * - * @param serviceEvent ServiceEvent - */ - public void serviceChanged(ServiceEvent serviceEvent) - { - Object service - = GeneralConfigPluginActivator.bundleContext.getService( - serviceEvent.getServiceReference()); - - // we don't care if the source service is not a protocol provider - if (service instanceof ProtocolProviderService) - { - int serviceEventType = serviceEvent.getType(); - - if (serviceEventType == ServiceEvent.REGISTERED) - handleProviderAdded((ProtocolProviderService) service); - else if (serviceEventType == ServiceEvent.UNREGISTERING) - handleProviderRemoved((ProtocolProviderService) service); - } - } - - /** - * Used to set registration state change listener. - * - * @param provider ProtocolProviderService - */ - private synchronized void handleProviderAdded( - ProtocolProviderService provider) - { - provider.addRegistrationStateChangeListener(this); - } - - /** - * Removes the registration change listener. - * - * @param provider the ProtocolProviderService that has been unregistered. - */ - private void handleProviderRemoved(ProtocolProviderService provider) - { - provider.removeRegistrationStateChangeListener(this); - } - - /** - * Remove provider from list with last statuses. - * If this is the last provider stop listening for idle events. - * @param provider - */ - private synchronized void removeProviderFromLastStates( - ProtocolProviderService provider) - { - lastStates.remove(provider); - } - - /** - * Remember provider's last status, normally before setting it to away. - * If needed start listening for idle events. - * @param provider the provider. - * @param status the status to save. - */ - private synchronized void addProviderToLastStates( - ProtocolProviderService provider, - PresenceStatus status) - { - if(lastStates.size() == 0) - start(); - - lastStates.put(provider, status); - } - - /** - * Listens for provider states. - * @param evt - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if(evt.getSource() instanceof ProtocolProviderService) - { - if(evt.getNewState().equals(RegistrationState.UNREGISTERED) - || evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) - { - removeProviderFromLastStates(evt.getProvider()); - } - else if(evt.getNewState().equals( - RegistrationState.REGISTERED)) - { - // we have at least one provider, so lets start listening - if(lastStates.size() == 0) - { - start(); - } - else - { - // or check are we away - if(getSystemActivityNotificationsService() - .getTimeSinceLastInput() - > Preferences.getTimer()*60*1000) - { - // we are away, so update the newly registered provider - // do it in new thread to give the provider - // time dispatch his status - new Thread(new Runnable() - { - public void run() - { - try{ - Thread.sleep(1000); - } - catch(Throwable t){} - - changeProtocolsToAway(); - } - }).start(); - } - } - } - } - } - - /** - * Listener waiting for idle state change. - */ - private class IdleListener - implements SystemActivityChangeListener - { - /** - * Listens for activities and set corresponding statuses. - * - * @param event the NotificationActionTypeEvent, which is - */ - public void activityChanged(SystemActivityEvent event) - { - switch(event.getEventID()) - { - case SystemActivityEvent.EVENT_DISPLAY_SLEEP: - case SystemActivityEvent.EVENT_SCREEN_LOCKED: - case SystemActivityEvent.EVENT_SCREENSAVER_START: - case SystemActivityEvent.EVENT_SYSTEM_IDLE: - changeProtocolsToAway(); - break; - case SystemActivityEvent.EVENT_DISPLAY_WAKE: - case SystemActivityEvent.EVENT_SCREEN_UNLOCKED: - case SystemActivityEvent.EVENT_SCREENSAVER_STOP: - case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: - changeProtocolsToPreviousState(); - break; - } - } - } -} +package net.java.sip.communicator.plugin.generalconfig.autoaway; + +import java.beans.*; +import java.util.*; + +import net.java.sip.communicator.plugin.generalconfig.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.sysactivity.*; +import net.java.sip.communicator.service.sysactivity.event.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * Listens for idle events from SystemActivityNotifications Service. + * + * @author Damian Minkov + */ +public class AutoAwayWatcher + implements ServiceListener, + RegistrationStateChangeListener +{ + /** + * The logger. + */ + private static final Logger logger + = Logger.getLogger(AutoAwayWatcher.class); + + /** + * The states of providers before going to away. + */ + private final Map lastStates + = new HashMap(); + + /** + * Listens for idle events. + */ + private IdleListener idleListener = null; + + /** + * Creates AutoAway handler. + */ + public AutoAwayWatcher() + { + if (Preferences.isEnabled()) + { + start(); + } + + Preferences.addEnableChangeListener( + new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + if(Boolean.parseBoolean((String) evt.getNewValue())) + start(); + else + stopInner(); + } + } + ); + + // listens for changes in configured value. + Preferences.addTimerChangeListener( + new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + stopInner(); + start(); + } + } + ); + } + + /** + * Starts and add needed listeners. + */ + private void start() + { + if(idleListener == null) + { + + idleListener = new IdleListener(); + + SystemActivityNotificationsService + systemActivityNotificationsService + = getSystemActivityNotificationsService(); + + systemActivityNotificationsService.addIdleSystemChangeListener( + Preferences.getTimer() * 60 * 1000, + idleListener); + systemActivityNotificationsService + .addSystemActivityChangeListener(idleListener); + + startListeningForNewProviders(); + } + } + + /** + * Start listening for new providers and their registration states. + */ + private void startListeningForNewProviders() + { + // listen for new providers + GeneralConfigPluginActivator.bundleContext.addServiceListener(this); + + // lets check current providers + ServiceReference[] protocolProviderRefs = null; + try + { + protocolProviderRefs = GeneralConfigPluginActivator.bundleContext + .getServiceReferences(ProtocolProviderService.class.getName(), + null); + } + catch (InvalidSyntaxException ex) + { + // this shouldn't happen since we're providing no parameter string + // but let's log just in case. + logger.error( + "Error while retrieving service refs", ex); + return; + } + + // in case we found any + if (protocolProviderRefs != null) + { + for (int i = 0; i < protocolProviderRefs.length; i++) + { + ProtocolProviderService provider = (ProtocolProviderService) + GeneralConfigPluginActivator.bundleContext + .getService(protocolProviderRefs[i]); + + this.handleProviderAdded(provider); + } + } + } + + /** + * Stop listening for new providers and their registration states. + */ + private void stopListeningForNewProviders() + { + // stop listen for new providers + GeneralConfigPluginActivator.bundleContext.removeServiceListener(this); + + // lets check current providers and remove registration state listener + ServiceReference[] protocolProviderRefs = null; + try + { + protocolProviderRefs = GeneralConfigPluginActivator.bundleContext + .getServiceReferences(ProtocolProviderService.class.getName(), + null); + } + catch (InvalidSyntaxException ex) + { + // this shouldn't happen since we're providing no parameter string + // but let's log just in case. + logger.error( + "Error while retrieving service refs", ex); + return; + } + + // in case we found any + if (protocolProviderRefs != null) + { + for (int i = 0; i < protocolProviderRefs.length; i++) + { + ProtocolProviderService provider = (ProtocolProviderService) + GeneralConfigPluginActivator.bundleContext + .getService(protocolProviderRefs[i]); + + this.handleProviderRemoved(provider); + } + } + } + + /** + * Stops and removes the listeners. + */ + public void stop() + { + GeneralConfigPluginActivator.bundleContext.removeServiceListener(this); + stopInner(); + } + + /** + * Stops and removes the listeners. + */ + private void stopInner() + { + if(idleListener != null) + { + SystemActivityNotificationsService + systemActivityNotificationsService + = getSystemActivityNotificationsService(); + + systemActivityNotificationsService.removeIdleSystemChangeListener( + idleListener); + systemActivityNotificationsService + .removeSystemActivityChangeListener(idleListener); + + stopListeningForNewProviders(); + + idleListener = null; + } + } + + /** + * Change protocol to away saving status so it can be set again when + * out of idle state. + */ + private void changeProtocolsToAway() + { + for (ProtocolProviderService protocolProvider + : GeneralConfigPluginActivator.getProtocolProviders()) + { + OperationSetPresence presence + = protocolProvider.getOperationSet( + OperationSetPresence.class); + + if(presence == null) + continue; + + PresenceStatus status = presence.getPresenceStatus(); + + if (status.getStatus() < PresenceStatus.AVAILABLE_THRESHOLD) + { + // already (manually) set to away or lower + continue; + } + + PresenceStatus newStatus + = StatusUpdateThread.findAwayStatus(presence); + + try + { + if (newStatus != null && !status.equals(newStatus)) + { + addProviderToLastStates(protocolProvider, status); + + presence.publishPresenceStatus( + newStatus, + newStatus.getStatusName()); + } + } + catch (IllegalArgumentException e) + { + } + catch (IllegalStateException e) + { + } + catch (OperationFailedException e) + { + } + } + } + + /** + * Back to status which was already saved before going to idle. + */ + private void changeProtocolsToPreviousState() + { + for (ProtocolProviderService protocolProvider + : GeneralConfigPluginActivator.getProtocolProviders()) + { + PresenceStatus lastState = lastStates.get(protocolProvider); + + if (lastState != null) + { + OperationSetPresence presence + = protocolProvider.getOperationSet( + OperationSetPresence.class); + try + { + presence.publishPresenceStatus(lastState, ""); + } + catch (IllegalArgumentException e) + { + } + catch (IllegalStateException e) + { + } + catch (OperationFailedException e) + { + } + removeProviderFromLastStates(protocolProvider); + } + } + } + + /** + * The SystemActivityNotifications Service. + * @return the SystemActivityNotifications Service. + */ + private SystemActivityNotificationsService + getSystemActivityNotificationsService() + { + return + ServiceUtils.getService( + GeneralConfigPluginActivator.bundleContext, + SystemActivityNotificationsService.class); + } + + /** + * When new protocol provider is registered we add our + * registration change listener. + * If unregistered remove reference to the provider and the + * registration change listener. + * + * @param serviceEvent ServiceEvent + */ + public void serviceChanged(ServiceEvent serviceEvent) + { + Object service + = GeneralConfigPluginActivator.bundleContext.getService( + serviceEvent.getServiceReference()); + + // we don't care if the source service is not a protocol provider + if (service instanceof ProtocolProviderService) + { + int serviceEventType = serviceEvent.getType(); + + if (serviceEventType == ServiceEvent.REGISTERED) + handleProviderAdded((ProtocolProviderService) service); + else if (serviceEventType == ServiceEvent.UNREGISTERING) + handleProviderRemoved((ProtocolProviderService) service); + } + } + + /** + * Used to set registration state change listener. + * + * @param provider ProtocolProviderService + */ + private synchronized void handleProviderAdded( + ProtocolProviderService provider) + { + provider.addRegistrationStateChangeListener(this); + } + + /** + * Removes the registration change listener. + * + * @param provider the ProtocolProviderService that has been unregistered. + */ + private void handleProviderRemoved(ProtocolProviderService provider) + { + provider.removeRegistrationStateChangeListener(this); + } + + /** + * Remove provider from list with last statuses. + * If this is the last provider stop listening for idle events. + * @param provider + */ + private synchronized void removeProviderFromLastStates( + ProtocolProviderService provider) + { + lastStates.remove(provider); + } + + /** + * Remember provider's last status, normally before setting it to away. + * If needed start listening for idle events. + * @param provider the provider. + * @param status the status to save. + */ + private synchronized void addProviderToLastStates( + ProtocolProviderService provider, + PresenceStatus status) + { + if(lastStates.size() == 0) + start(); + + lastStates.put(provider, status); + } + + /** + * Listens for provider states. + * @param evt + */ + public void registrationStateChanged(RegistrationStateChangeEvent evt) + { + if(evt.getSource() instanceof ProtocolProviderService) + { + if(evt.getNewState().equals(RegistrationState.UNREGISTERED) + || evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) + { + removeProviderFromLastStates(evt.getProvider()); + } + else if(evt.getNewState().equals( + RegistrationState.REGISTERED)) + { + // we have at least one provider, so lets start listening + if(lastStates.size() == 0) + { + start(); + } + else + { + // or check are we away + if(getSystemActivityNotificationsService() + .getTimeSinceLastInput() + > Preferences.getTimer()*60*1000) + { + // we are away, so update the newly registered provider + // do it in new thread to give the provider + // time dispatch his status + new Thread(new Runnable() + { + public void run() + { + try{ + Thread.sleep(1000); + } + catch(Throwable t){} + + changeProtocolsToAway(); + } + }).start(); + } + } + } + } + } + + /** + * Listener waiting for idle state change. + */ + private class IdleListener + implements SystemActivityChangeListener + { + /** + * Listens for activities and set corresponding statuses. + * + * @param event the NotificationActionTypeEvent, which is + */ + public void activityChanged(SystemActivityEvent event) + { + switch(event.getEventID()) + { + case SystemActivityEvent.EVENT_DISPLAY_SLEEP: + case SystemActivityEvent.EVENT_SCREEN_LOCKED: + case SystemActivityEvent.EVENT_SCREENSAVER_START: + case SystemActivityEvent.EVENT_SYSTEM_IDLE: + changeProtocolsToAway(); + break; + case SystemActivityEvent.EVENT_DISPLAY_WAKE: + case SystemActivityEvent.EVENT_SCREEN_UNLOCKED: + case SystemActivityEvent.EVENT_SCREENSAVER_STOP: + case SystemActivityEvent.EVENT_SYSTEM_IDLE_END: + changeProtocolsToPreviousState(); + break; + } + } + } +} diff --git a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/Preferences.java b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/Preferences.java index 148da25..bee52df 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/autoaway/Preferences.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/autoaway/Preferences.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,133 +15,133 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.generalconfig.autoaway; - -import net.java.sip.communicator.plugin.generalconfig.*; -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; - -import java.beans.*; - -/** - * Preferences for the Status Update - * - * @author Thomas Hofer - * - */ -public final class Preferences -{ - /** - * Property indicating whether status change on away is enabled. - */ - private static final String ENABLE - = "net.java.sip.communicator.plugin.statusupdate.enable"; - - /** - * Property indicating the time in minutes to consider a pc in idle state. - */ - private static final String TIMER - = "net.java.sip.communicator.plugin.statusupdate.timer"; - - /** - * The default value to be displayed and to be considered - * for {@link Preferences#TIMER}. - */ - public static final int DEFAULT_TIMER = 15; - - /** - * Whether change status on away is enabled. - * @return whether change status on away is enabled. - */ - static boolean isEnabled() - { - // if enabled start - String enabledDefault - = GeneralConfigPluginActivator.getResources().getSettingsString( - Preferences.ENABLE); - - return - GeneralConfigPluginActivator - .getConfigurationService() - .getBoolean( - Preferences.ENABLE, - Boolean.parseBoolean(enabledDefault)); - } - - /** - * Returns the time in minutes to consider a pc in idle state. - * @return the time in minutes to consider a pc in idle state. - */ - static int getTimer() - { - ConfigurationService cfg - = GeneralConfigPluginActivator.getConfigurationService(); - ResourceManagementService resources - = GeneralConfigPluginActivator.getResources(); - - String enabledDefault = resources.getSettingsString(Preferences.ENABLE); - - String timerDefaultStr = resources.getSettingsString(Preferences.TIMER); - int timerDefault = DEFAULT_TIMER; - - if (timerDefaultStr != null) - { - try - { - timerDefault = Integer.parseInt(timerDefaultStr); - } - catch (NumberFormatException nfe) - { - } - } - - return - cfg.getBoolean( - Preferences.ENABLE, - Boolean.parseBoolean(enabledDefault)) - ? cfg.getInt(Preferences.TIMER, timerDefault) - : 0; - } - - /** - * Save data in the configuration file - * @param enabled is enabled - * @param timer the time value to save - */ - static void saveData(boolean enabled, String timer) - { - ConfigurationService cfg - = GeneralConfigPluginActivator.getConfigurationService(); - - cfg.setProperty(Preferences.ENABLE, Boolean.toString(enabled)); - cfg.setProperty(Preferences.TIMER, timer); - } - - /** - * Adds listener to detect property changes. - * @param listener the listener to notify. - */ - static void addEnableChangeListener(PropertyChangeListener listener) - { - // listens for changes in configuration enable/disable - GeneralConfigPluginActivator - .getConfigurationService() - .addPropertyChangeListener( - ENABLE, - listener); - } - - /** - * Adds listener to detect timer property changes. - * @param listener the listener to notify. - */ - static void addTimerChangeListener(PropertyChangeListener listener) - { - // listens for changes in configuration enable/disable - GeneralConfigPluginActivator - .getConfigurationService() - .addPropertyChangeListener( - TIMER, - listener); - } -} +package net.java.sip.communicator.plugin.generalconfig.autoaway; + +import net.java.sip.communicator.plugin.generalconfig.*; +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; + +import java.beans.*; + +/** + * Preferences for the Status Update + * + * @author Thomas Hofer + * + */ +public final class Preferences +{ + /** + * Property indicating whether status change on away is enabled. + */ + private static final String ENABLE + = "net.java.sip.communicator.plugin.statusupdate.enable"; + + /** + * Property indicating the time in minutes to consider a pc in idle state. + */ + private static final String TIMER + = "net.java.sip.communicator.plugin.statusupdate.timer"; + + /** + * The default value to be displayed and to be considered + * for {@link Preferences#TIMER}. + */ + public static final int DEFAULT_TIMER = 15; + + /** + * Whether change status on away is enabled. + * @return whether change status on away is enabled. + */ + static boolean isEnabled() + { + // if enabled start + String enabledDefault + = GeneralConfigPluginActivator.getResources().getSettingsString( + Preferences.ENABLE); + + return + GeneralConfigPluginActivator + .getConfigurationService() + .getBoolean( + Preferences.ENABLE, + Boolean.parseBoolean(enabledDefault)); + } + + /** + * Returns the time in minutes to consider a pc in idle state. + * @return the time in minutes to consider a pc in idle state. + */ + static int getTimer() + { + ConfigurationService cfg + = GeneralConfigPluginActivator.getConfigurationService(); + ResourceManagementService resources + = GeneralConfigPluginActivator.getResources(); + + String enabledDefault = resources.getSettingsString(Preferences.ENABLE); + + String timerDefaultStr = resources.getSettingsString(Preferences.TIMER); + int timerDefault = DEFAULT_TIMER; + + if (timerDefaultStr != null) + { + try + { + timerDefault = Integer.parseInt(timerDefaultStr); + } + catch (NumberFormatException nfe) + { + } + } + + return + cfg.getBoolean( + Preferences.ENABLE, + Boolean.parseBoolean(enabledDefault)) + ? cfg.getInt(Preferences.TIMER, timerDefault) + : 0; + } + + /** + * Save data in the configuration file + * @param enabled is enabled + * @param timer the time value to save + */ + static void saveData(boolean enabled, String timer) + { + ConfigurationService cfg + = GeneralConfigPluginActivator.getConfigurationService(); + + cfg.setProperty(Preferences.ENABLE, Boolean.toString(enabled)); + cfg.setProperty(Preferences.TIMER, timer); + } + + /** + * Adds listener to detect property changes. + * @param listener the listener to notify. + */ + static void addEnableChangeListener(PropertyChangeListener listener) + { + // listens for changes in configuration enable/disable + GeneralConfigPluginActivator + .getConfigurationService() + .addPropertyChangeListener( + ENABLE, + listener); + } + + /** + * Adds listener to detect timer property changes. + * @param listener the listener to notify. + */ + static void addTimerChangeListener(PropertyChangeListener listener) + { + // listens for changes in configuration enable/disable + GeneralConfigPluginActivator + .getConfigurationService() + .addPropertyChangeListener( + TIMER, + listener); + } +} diff --git a/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccRegWizzActivator.java index e457fdd..02b84e9 100644 --- a/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccRegWizzActivator.java +++ b/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccRegWizzActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,163 +15,163 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.googletalkaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. - * - * @author Lubomir Marinov - */ -public class GoogleTalkAccRegWizzActivator - extends AbstractServiceDependentActivator -{ - /** - * OSGi bundle context. - */ - public static BundleContext bundleContext; - - private static ResourceManagementService resourcesService; - - /** - * The Logger used by the GoogleTalkAccRegWizzActivator - * and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(GoogleTalkAccRegWizzActivator.class); - - private static BrowserLauncherService browserLauncherService; - - private static UIService uiService; - - /** - * Starts this bundle. - */ - @Override - public void start(Object dependentService) - { - uiService = (UIService)dependentService; - - GoogleTalkAccountRegistrationWizard wizard = - new GoogleTalkAccountRegistrationWizard(uiService - .getAccountRegWizardContainer()); - - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - GoogleTalkAccountRegistrationWizard.PROTOCOL); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - wizard, - containerFilter); - } - - /** - * The dependent class. We are waiting for the ui service. - * @return - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * The bundle context to use. - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - public void stop(BundleContext bundleContext) - throws Exception - { - } - - /** - * Returns the ProtocolProviderFactory for the Google Talk - * protocol. - * - * @return the ProtocolProviderFactory for the Google Talk - * protocol - */ - public static ProtocolProviderFactory getGoogleTalkProtocolProviderFactory() - { - ServiceReference[] serRefs = null; - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" + ProtocolNames.JABBER + ")"; - - try - { - serRefs = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error("GoogleTalkAccRegWizzActivator : " + ex); - } - - return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - browserLauncherService = - (BrowserLauncherService) bundleContext - .getService(bundleContext - .getServiceReference(BrowserLauncherService.class - .getName())); - } - - return browserLauncherService; - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(GoogleTalkAccRegWizzActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.googletalkaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. + * + * @author Lubomir Marinov + */ +public class GoogleTalkAccRegWizzActivator + extends AbstractServiceDependentActivator +{ + /** + * OSGi bundle context. + */ + public static BundleContext bundleContext; + + private static ResourceManagementService resourcesService; + + /** + * The Logger used by the GoogleTalkAccRegWizzActivator + * and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(GoogleTalkAccRegWizzActivator.class); + + private static BrowserLauncherService browserLauncherService; + + private static UIService uiService; + + /** + * Starts this bundle. + */ + @Override + public void start(Object dependentService) + { + uiService = (UIService)dependentService; + + GoogleTalkAccountRegistrationWizard wizard = + new GoogleTalkAccountRegistrationWizard(uiService + .getAccountRegWizardContainer()); + + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + ProtocolProviderFactory.PROTOCOL, + GoogleTalkAccountRegistrationWizard.PROTOCOL); + + bundleContext.registerService( + AccountRegistrationWizard.class.getName(), + wizard, + containerFilter); + } + + /** + * The dependent class. We are waiting for the ui service. + * @return + */ + @Override + public Class getDependentServiceClass() + { + return UIService.class; + } + + /** + * The bundle context to use. + * @param context the context to set. + */ + @Override + public void setBundleContext(BundleContext context) + { + bundleContext = context; + } + + public void stop(BundleContext bundleContext) + throws Exception + { + } + + /** + * Returns the ProtocolProviderFactory for the Google Talk + * protocol. + * + * @return the ProtocolProviderFactory for the Google Talk + * protocol + */ + public static ProtocolProviderFactory getGoogleTalkProtocolProviderFactory() + { + ServiceReference[] serRefs = null; + + String osgiFilter = "(" + + ProtocolProviderFactory.PROTOCOL + + "=" + ProtocolNames.JABBER + ")"; + + try + { + serRefs = bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), osgiFilter); + } + catch (InvalidSyntaxException ex) + { + logger.error("GoogleTalkAccRegWizzActivator : " + ex); + } + + return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); + } + + /** + * Returns the UIService. + * + * @return the UIService + */ + public static UIService getUIService() + { + return uiService; + } + + /** + * Returns the BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService obtained from the bundle + * context + */ + public static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncherService == null) + { + browserLauncherService = + (BrowserLauncherService) bundleContext + .getService(bundleContext + .getServiceReference(BrowserLauncherService.class + .getName())); + } + + return browserLauncherService; + } + + /** + * Returns the ResourceManagementService. + * + * @return the ResourceManagementService. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(GoogleTalkAccRegWizzActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccountRegistrationWizard.java index c296762..25b3b21 100644 --- a/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/googletalkaccregwizz/GoogleTalkAccountRegistrationWizard.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,254 +15,254 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.googletalkaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.jabberaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.jabber.*; - -/** - * The GoogleTalkAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Google Talk protocol. It should - * allow the user to create and configure a new Google Talk account. - * - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class GoogleTalkAccountRegistrationWizard - extends JabberAccountRegistrationWizard -{ - /** - * The Google Talk protocol name. - */ - public static final String PROTOCOL = "Google Talk"; - - /** - * A constant pointing to the Google Talk protocol logo image. - */ - public static final String PROTOCOL_ICON - = "service.protocol.googletalk.GTALK_16x16"; - - /** - * A constant pointing to the Aim protocol wizard page image. - */ - public static final String PAGE_IMAGE - = "service.protocol.googletalk.GTALK_64x64"; - - /** - * Creates an instance of GoogleTalkAccountRegistrationWizard. - * @param wizardContainer the wizard container, where this wizard - * is added - */ - public GoogleTalkAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all google talk specific properties. - * - * @param reg the registration object - */ - private void setPredefinedProperties(JabberAccountRegistration reg) - { - reg.setDefaultUserSufix("gmail.com"); - reg.setServerAddress("talk.google.com"); - - reg.setServerOverridden(true); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return GoogleTalkAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return GoogleTalkAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return GoogleTalkAccRegWizzActivator.getResources() - .getI18NString("plugin.googletalkaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return GoogleTalkAccRegWizzActivator.getResources() - .getI18NString("plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: johnsmith@gmail.com or johnsmith"; - } - - /** - * Returns the display label used for the sip id field. - * @return the sip id display label string. - */ - @Override - protected String getUsernameLabel() - { - return GoogleTalkAccRegWizzActivator.getResources() - .getI18NString("plugin.googletalkaccregwizz.USERNAME"); - } - - /** - * Return the string for add existing account button. - * @return the string for add existing account button. - */ - @Override - protected String getCreateAccountButtonLabel() - { - return GoogleTalkAccRegWizzActivator.getResources().getI18NString( - "plugin.googletalkaccregwizz.NEW_ACCOUNT_TITLE"); - } - - /** - * Return the string for create new account button. - * @return the string for create new account button. - */ - @Override - protected String getCreateAccountLabel() - { - return GoogleTalkAccRegWizzActivator.getResources().getI18NString( - "plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT"); - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/googletalk"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/googletalk/logo32x32.png"; - } - - /** - * Opens a browser on the sign up page. - */ - @Override - public void webSignup() - { - GoogleTalkAccRegWizzActivator.getBrowserLauncher() - .openURL("https://www.google.com/accounts/NewAccount"); - } - - /** - * Returns true if the web sign up is supported by the current - * implementation, false - otherwise. - * @return true if the web sign up is supported by the current - * implementation, false - otherwise - */ - @Override - public boolean isWebSignupSupported() - { - return true; - } - - /** - * Returns an instance of CreateAccountService through which the - * user could create an account. This method is meant to be implemented by - * specific protocol provider wizards. - * @return an instance of CreateAccountService - */ - @Override - protected JabberAccountCreationFormService getCreateAccountService() - { - return null; - } -} +package net.java.sip.communicator.plugin.googletalkaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.plugin.jabberaccregwizz.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.jabber.*; + +/** + * The GoogleTalkAccountRegistrationWizard is an implementation of the + * AccountRegistrationWizard for the Google Talk protocol. It should + * allow the user to create and configure a new Google Talk account. + * + * @author Lubomir Marinov + * @author Yana Stamcheva + */ +public class GoogleTalkAccountRegistrationWizard + extends JabberAccountRegistrationWizard +{ + /** + * The Google Talk protocol name. + */ + public static final String PROTOCOL = "Google Talk"; + + /** + * A constant pointing to the Google Talk protocol logo image. + */ + public static final String PROTOCOL_ICON + = "service.protocol.googletalk.GTALK_16x16"; + + /** + * A constant pointing to the Aim protocol wizard page image. + */ + public static final String PAGE_IMAGE + = "service.protocol.googletalk.GTALK_64x64"; + + /** + * Creates an instance of GoogleTalkAccountRegistrationWizard. + * @param wizardContainer the wizard container, where this wizard + * is added + */ + public GoogleTalkAccountRegistrationWizard(WizardContainer wizardContainer) + { + super(wizardContainer); + } + + /** + * Returns the set of pages contained in this wizard. + * @return Iterator + */ + @Override + public Iterator getPages() + { + JabberAccountRegistration reg = new JabberAccountRegistration(); + + setPredefinedProperties(reg); + + return getPages(reg); + } + + /** + * Returns a simple account registration form that would be the first form + * shown to the user. Only if the user needs more settings she'll choose + * to open the advanced wizard, consisted by all pages. + * + * @param isCreateAccount indicates if the simple form should be opened as + * a create account form or as a login form + * @return a simple account registration form + */ + @Override + public Object getSimpleForm(boolean isCreateAccount) + { + JabberAccountRegistration reg = new JabberAccountRegistration(); + + setPredefinedProperties(reg); + + return getSimpleForm(reg, isCreateAccount); + } + + /** + * Sets all google talk specific properties. + * + * @param reg the registration object + */ + private void setPredefinedProperties(JabberAccountRegistration reg) + { + reg.setDefaultUserSufix("gmail.com"); + reg.setServerAddress("talk.google.com"); + + reg.setServerOverridden(true); + } + + /** + * Implements the AccountRegistrationWizard.getIcon method. + * Returns the icon to be used for this wizard. + * @return byte[] + */ + @Override + public byte[] getIcon() + { + return GoogleTalkAccRegWizzActivator.getResources() + .getImageInBytes(PROTOCOL_ICON); + } + + /** + * Implements the AccountRegistrationWizard.getPageImage method. + * Returns the image used to decorate the wizard page + * + * @return byte[] the image used to decorate the wizard page + */ + @Override + public byte[] getPageImage() + { + return GoogleTalkAccRegWizzActivator.getResources() + .getImageInBytes(PAGE_IMAGE); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolName + * method. Returns the protocol name for this wizard. + * @return String + */ + @Override + public String getProtocolName() + { + return GoogleTalkAccRegWizzActivator.getResources() + .getI18NString("plugin.googletalkaccregwizz.PROTOCOL_NAME"); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolDescription + * method. Returns the description of the protocol for this wizard. + * @return String + */ + @Override + public String getProtocolDescription() + { + return GoogleTalkAccRegWizzActivator.getResources() + .getI18NString("plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION"); + } + + /** + * Returns an example string, which should indicate to the user how the + * user name should look like. + * @return an example string, which should indicate to the user how the + * user name should look like. + */ + @Override + public String getUserNameExample() + { + return "Ex: johnsmith@gmail.com or johnsmith"; + } + + /** + * Returns the display label used for the sip id field. + * @return the sip id display label string. + */ + @Override + protected String getUsernameLabel() + { + return GoogleTalkAccRegWizzActivator.getResources() + .getI18NString("plugin.googletalkaccregwizz.USERNAME"); + } + + /** + * Return the string for add existing account button. + * @return the string for add existing account button. + */ + @Override + protected String getCreateAccountButtonLabel() + { + return GoogleTalkAccRegWizzActivator.getResources().getI18NString( + "plugin.googletalkaccregwizz.NEW_ACCOUNT_TITLE"); + } + + /** + * Return the string for create new account button. + * @return the string for create new account button. + */ + @Override + protected String getCreateAccountLabel() + { + return GoogleTalkAccRegWizzActivator.getResources().getI18NString( + "plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT"); + } + + /** + * Returns the protocol name as listed in "ProtocolNames" or just the name + * of the service. + * @return the protocol name + */ + @Override + public String getProtocol() + { + return PROTOCOL; + } + + /** + * Returns the protocol icon path. + * @return the protocol icon path + */ + @Override + public String getProtocolIconPath() + { + return "resources/images/protocol/googletalk"; + } + + /** + * Returns the account icon path. + * @return the account icon path + */ + @Override + public String getAccountIconPath() + { + return "resources/images/protocol/googletalk/logo32x32.png"; + } + + /** + * Opens a browser on the sign up page. + */ + @Override + public void webSignup() + { + GoogleTalkAccRegWizzActivator.getBrowserLauncher() + .openURL("https://www.google.com/accounts/NewAccount"); + } + + /** + * Returns true if the web sign up is supported by the current + * implementation, false - otherwise. + * @return true if the web sign up is supported by the current + * implementation, false - otherwise + */ + @Override + public boolean isWebSignupSupported() + { + return true; + } + + /** + * Returns an instance of CreateAccountService through which the + * user could create an account. This method is meant to be implemented by + * specific protocol provider wizards. + * @return an instance of CreateAccountService + */ + @Override + protected JabberAccountCreationFormService getCreateAccountService() + { + return null; + } +} diff --git a/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccRegWizzActivator.java index c50178c..7340901 100644 --- a/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccRegWizzActivator.java +++ b/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccRegWizzActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,154 +15,154 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.iptelaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. - * - * @author Lubomir Marinov - */ -public class IptelAccRegWizzActivator - extends AbstractServiceDependentActivator -{ - /** - * OSGi bundle context. - */ - public static BundleContext bundleContext; - - /** - * The Logger used by the IptelAccRegWizzActivator class - * and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(IptelAccRegWizzActivator.class); - - private static BrowserLauncherService browserLauncherService; - - private static ResourceManagementService resourcesService; - - private static UIService uiService; - - /** - * Starts this bundle. - */ - @Override - public void start(Object dependentService) - { - uiService = (UIService)dependentService; - - IptelAccountRegistrationWizard wizard - = new IptelAccountRegistrationWizard(uiService - .getAccountRegWizardContainer()); - - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - IptelAccountRegistrationWizard.PROTOCOL); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - wizard, - containerFilter); - } - - /** - * The dependent class. We are waiting for the ui service. - * @return the ui service class. - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * The bundle context to use. - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - public void stop(BundleContext bundleContext) throws Exception {} - - /** - * Returns the ProtocolProviderFactory for the IP Tel protocol. - * - * @return the ProtocolProviderFactory for the IP Tel protocol - */ - public static ProtocolProviderFactory getIptelProtocolProviderFactory() - { - ServiceReference[] serRefs = null; - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" + ProtocolNames.SIP + ")"; - - try - { - serRefs = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error("IptelAccRegWizzActivator : " + ex); - } - - return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - browserLauncherService - = (BrowserLauncherService) bundleContext.getService( - bundleContext.getServiceReference( - BrowserLauncherService.class.getName())); - } - return browserLauncherService; - } - - /** - * Returns the service giving access to resources. - * @return the service giving access to resources - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = ResourceManagementServiceUtils - .getService(IptelAccRegWizzActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.iptelaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. + * + * @author Lubomir Marinov + */ +public class IptelAccRegWizzActivator + extends AbstractServiceDependentActivator +{ + /** + * OSGi bundle context. + */ + public static BundleContext bundleContext; + + /** + * The Logger used by the IptelAccRegWizzActivator class + * and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(IptelAccRegWizzActivator.class); + + private static BrowserLauncherService browserLauncherService; + + private static ResourceManagementService resourcesService; + + private static UIService uiService; + + /** + * Starts this bundle. + */ + @Override + public void start(Object dependentService) + { + uiService = (UIService)dependentService; + + IptelAccountRegistrationWizard wizard + = new IptelAccountRegistrationWizard(uiService + .getAccountRegWizardContainer()); + + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + ProtocolProviderFactory.PROTOCOL, + IptelAccountRegistrationWizard.PROTOCOL); + + bundleContext.registerService( + AccountRegistrationWizard.class.getName(), + wizard, + containerFilter); + } + + /** + * The dependent class. We are waiting for the ui service. + * @return the ui service class. + */ + @Override + public Class getDependentServiceClass() + { + return UIService.class; + } + + /** + * The bundle context to use. + * @param context the context to set. + */ + @Override + public void setBundleContext(BundleContext context) + { + bundleContext = context; + } + + public void stop(BundleContext bundleContext) throws Exception {} + + /** + * Returns the ProtocolProviderFactory for the IP Tel protocol. + * + * @return the ProtocolProviderFactory for the IP Tel protocol + */ + public static ProtocolProviderFactory getIptelProtocolProviderFactory() + { + ServiceReference[] serRefs = null; + + String osgiFilter = "(" + + ProtocolProviderFactory.PROTOCOL + + "=" + ProtocolNames.SIP + ")"; + + try + { + serRefs = bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), osgiFilter); + } + catch (InvalidSyntaxException ex) + { + logger.error("IptelAccRegWizzActivator : " + ex); + } + + return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); + } + + /** + * Returns the UIService. + * + * @return the UIService + */ + public static UIService getUIService() + { + return uiService; + } + + /** + * Returns the BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService obtained from the bundle + * context + */ + public static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncherService == null) + { + browserLauncherService + = (BrowserLauncherService) bundleContext.getService( + bundleContext.getServiceReference( + BrowserLauncherService.class.getName())); + } + return browserLauncherService; + } + + /** + * Returns the service giving access to resources. + * @return the service giving access to resources + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = ResourceManagementServiceUtils + .getService(IptelAccRegWizzActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccountRegistrationWizard.java index 699496c..38b7a0a 100644 --- a/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/iptelaccregwizz/IptelAccountRegistrationWizard.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,205 +15,205 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.iptelaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.sipaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.sip.*; - -/** - * The IptelAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the SIP protocol. It should allow - * the user to create and configure a new SIP account. - * - * @author Yana Stamcheva - */ -public class IptelAccountRegistrationWizard - extends SIPAccountRegistrationWizard -{ - /** - * A constant pointing to the IP Tel protocol logo image. - */ - private static final String PROTOCOL_ICON - = "service.protocol.iptel.IPTEL_16x16"; - - /** - * A constant pointing to the IP Tel protocol wizard page image. - */ - private static final String PAGE_IMAGE - = "service.protocol.iptel.IPTEL_64x64"; - - /** - * The protocol name. - */ - public static final String PROTOCOL = "iptel.org"; - - /** - * Creates an instance of IptelAccountRegistrationWizard. - * @param wizardContainer the wizard container - */ - public IptelAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all iptel specific properties. - * - * @param reg the registration object - */ - private void setPredefinedProperties(SIPAccountRegistration reg) - { - reg.setDefaultDomain("iptel.org"); - reg.setPreferredTransport("TCP"); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return IptelAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return IptelAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString( - "plugin.iptelaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources.getString( - "plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: myusername or myusername@iptel.org"; - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/iptel"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/iptel/sip32x32.png"; - } - - /** - * Opens the browser on the page sign up - */ - @Override - public void webSignup() - { - IptelAccRegWizzActivator.getBrowserLauncher() - .openURL("https://serweb.iptel.org/user/reg/index.php"); - } - - /** - * Returns the name of the web sign up link. - * @return the name of the web sign up link - */ - @Override - public String getWebSignupLinkName() - { - return IptelAccRegWizzActivator.getResources().getI18NString( - "plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE"); - } -} +package net.java.sip.communicator.plugin.iptelaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.plugin.sipaccregwizz.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.sip.*; + +/** + * The IptelAccountRegistrationWizard is an implementation of the + * AccountRegistrationWizard for the SIP protocol. It should allow + * the user to create and configure a new SIP account. + * + * @author Yana Stamcheva + */ +public class IptelAccountRegistrationWizard + extends SIPAccountRegistrationWizard +{ + /** + * A constant pointing to the IP Tel protocol logo image. + */ + private static final String PROTOCOL_ICON + = "service.protocol.iptel.IPTEL_16x16"; + + /** + * A constant pointing to the IP Tel protocol wizard page image. + */ + private static final String PAGE_IMAGE + = "service.protocol.iptel.IPTEL_64x64"; + + /** + * The protocol name. + */ + public static final String PROTOCOL = "iptel.org"; + + /** + * Creates an instance of IptelAccountRegistrationWizard. + * @param wizardContainer the wizard container + */ + public IptelAccountRegistrationWizard(WizardContainer wizardContainer) + { + super(wizardContainer); + } + + /** + * Returns the set of pages contained in this wizard. + * @return Iterator + */ + @Override + public Iterator getPages() + { + SIPAccountRegistration reg = new SIPAccountRegistration(); + + setPredefinedProperties(reg); + + return getPages(reg); + } + + /** + * Returns a simple account registration form that would be the first form + * shown to the user. Only if the user needs more settings she'll choose + * to open the advanced wizard, consisted by all pages. + * + * @param isCreateAccount indicates if the simple form should be opened as + * a create account form or as a login form + * @return a simple account registration form + */ + @Override + public Object getSimpleForm(boolean isCreateAccount) + { + SIPAccountRegistration reg = new SIPAccountRegistration(); + + setPredefinedProperties(reg); + + return getSimpleForm(reg, isCreateAccount); + } + + /** + * Sets all iptel specific properties. + * + * @param reg the registration object + */ + private void setPredefinedProperties(SIPAccountRegistration reg) + { + reg.setDefaultDomain("iptel.org"); + reg.setPreferredTransport("TCP"); + } + + /** + * Implements the AccountRegistrationWizard.getIcon method. + * Returns the icon to be used for this wizard. + * @return byte[] + */ + @Override + public byte[] getIcon() + { + return IptelAccRegWizzActivator.getResources() + .getImageInBytes(PROTOCOL_ICON); + } + + /** + * Implements the AccountRegistrationWizard.getPageImage method. + * Returns the image used to decorate the wizard page + * + * @return byte[] the image used to decorate the wizard page + */ + @Override + public byte[] getPageImage() + { + return IptelAccRegWizzActivator.getResources() + .getImageInBytes(PAGE_IMAGE); + } + + + /** + * Implements the AccountRegistrationWizard.getProtocolName + * method. Returns the protocol name for this wizard. + * @return String + */ + @Override + public String getProtocolName() + { + return Resources.getString( + "plugin.iptelaccregwizz.PROTOCOL_NAME"); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolDescription + * method. Returns the description of the protocol for this wizard. + * @return String + */ + @Override + public String getProtocolDescription() + { + return Resources.getString( + "plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION"); + } + + /** + * Returns an example string, which should indicate to the user how the + * user name should look like. + * @return an example string, which should indicate to the user how the + * user name should look like. + */ + @Override + public String getUserNameExample() + { + return "Ex: myusername or myusername@iptel.org"; + } + + /** + * Returns the protocol name as listed in "ProtocolNames" or just the name + * of the service. + * @return the protocol name + */ + @Override + public String getProtocol() + { + return PROTOCOL; + } + + /** + * Returns the protocol icon path. + * @return the protocol icon path + */ + @Override + public String getProtocolIconPath() + { + return "resources/images/protocol/iptel"; + } + + /** + * Returns the account icon path. + * @return the account icon path + */ + @Override + public String getAccountIconPath() + { + return "resources/images/protocol/iptel/sip32x32.png"; + } + + /** + * Opens the browser on the page sign up + */ + @Override + public void webSignup() + { + IptelAccRegWizzActivator.getBrowserLauncher() + .openURL("https://serweb.iptel.org/user/reg/index.php"); + } + + /** + * Returns the name of the web sign up link. + * @return the name of the web sign up link + */ + @Override + public String getWebSignupLinkName() + { + return IptelAccRegWizzActivator.getResources().getI18NString( + "plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE"); + } +} diff --git a/src/net/java/sip/communicator/plugin/keybindingchooser/globalchooser/GlobalShortcutDialog.java b/src/net/java/sip/communicator/plugin/keybindingchooser/globalchooser/GlobalShortcutDialog.java index aab01c5..1e9f83f 100644 --- a/src/net/java/sip/communicator/plugin/keybindingchooser/globalchooser/GlobalShortcutDialog.java +++ b/src/net/java/sip/communicator/plugin/keybindingchooser/globalchooser/GlobalShortcutDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,489 +15,489 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.keybindingchooser.globalchooser; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import java.util.List; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.keybindingchooser.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.plugin.desktoputil.plaf.*; -import net.java.sip.communicator.service.globalshortcut.*; -import net.java.sip.communicator.util.skin.*; - -import org.jitsi.util.*; -// disambiguation - -/** - * Dialog to choose the shortcut. - * - * @author Sebastien Vincent - */ -public class GlobalShortcutDialog - extends SIPCommDialog - implements ActionListener, - GlobalShortcutListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Text displayed when no shortcut is configured. - */ - private static final String PRESS_TO_SETUP_SHORTCUT = - Resources.getString("plugin.keybindings.globalchooser.PRESS_BTN"); - - /** - * The global shortcut entry. - */ - private final GlobalShortcutEntry entry; - - /** - * OK button. - */ - private final JButton btnOK = new JButton( - Resources.getString("service.gui.OK")); - - /** - * Cancel button. - */ - private final JButton btnCancel = new JButton( - Resources.getString("service.gui.CANCEL")); - - /** - * Enable or not special key for shortcut. - */ - private final JCheckBox specialBox = new SIPCommCheckBox( - Resources.getString("plugin.keybindings.globalchooser.ENABLE_SPECIAL")); - - /** - * First shortcut field. - */ - private final ShortcutField fldShortcut = new ShortcutField( - PRESS_TO_SETUP_SHORTCUT); - - /** - * Secondary shortcut field. - */ - private final ShortcutField fldShortcut2 = new ShortcutField( - PRESS_TO_SETUP_SHORTCUT); - - /** - * Return code. - */ - private int retCode = 0; - - /** - * Constructor. - * - * @param dialog root dialog - * @param entry the global shortcut entry - */ - public GlobalShortcutDialog(Dialog dialog, GlobalShortcutEntry entry) - { - super(dialog); - - setModal(true); - setTitle("Global shortcut: " + entry.getAction()); - this.entry = entry; - init(); - } - - /** - * Initialize components. - */ - private void init() - { - TransparentPanel mainPanel = new TransparentPanel(new BorderLayout()); - JPanel btnPanel = new TransparentPanel( - new FlowLayout(FlowLayout.RIGHT)); - JPanel shortcutPanel = new TransparentPanel( - new GridLayout(0, 2, 0, 10)); - - btnOK.addActionListener(this); - btnCancel.addActionListener(this); - - KeyAdapter keyAdapter = new KeyAdapter() - { - private KeyEvent buffer = null; - - @Override - public void keyPressed(KeyEvent event) - { - if(event.getKeyCode() == KeyEvent.VK_ESCAPE) - { - SIPCommTextField field = - (SIPCommTextField)event.getSource(); - - AWTKeyStroke ks = null; - - if(field == fldShortcut) - { - ks = entry.getShortcut(); - } - else if(field == fldShortcut2) - { - ks = entry.getShortcut2(); - } - - if(ks == null) - field.setText(PRESS_TO_SETUP_SHORTCUT); - else - { - - if(ks.getModifiers() == - GlobalShortcutService.SPECIAL_KEY_MODIFIERS) - { - field.setText("Special"); - } - else - { - field.setText(GlobalShortcutEntry.getShortcutText( - entry.getShortcut())); - } - } - btnOK.requestFocusInWindow(); - return; - } - - if(event.getKeyCode() == 0) - return; - - // Reports KEY_PRESSED events on release to support modifiers - this.buffer = event; - } - - @Override - public void keyReleased(KeyEvent event) - { - if (buffer != null) - { - SIPCommTextField field = - (SIPCommTextField)event.getSource(); - AWTKeyStroke input = KeyStroke.getKeyStrokeForEvent(buffer); - buffer = null; - - GlobalShortcutEntry en = entry; - List kss = new ArrayList(); - - if(field == fldShortcut) - { - kss.add(input); - kss.add(en.getShortcut2()); - } - else if(field == fldShortcut2) - { - kss.add(en.getShortcut()); - kss.add(input); - } - - en.setShortcuts(kss); - en.setEditShortcut1(false); - en.setEditShortcut2(false); - field.setText(GlobalShortcutEntry.getShortcutText( - input)); - btnOK.requestFocus(); - } - } - }; - - AWTKeyStroke ks = entry.getShortcut(); - AWTKeyStroke ks2 = entry.getShortcut2(); - - if(ks != null) - { - if(ks.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) - { - fldShortcut.setText(GlobalShortcutEntry.getShortcutText(ks)); - } - else - { - fldShortcut.setText("Special"); - } - } - - if(ks2 != null) - { - - if(ks2.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) - { - fldShortcut2.setText(GlobalShortcutEntry.getShortcutText(ks2)); - } - else - { - fldShortcut2.setText("Special"); - } - } - - fldShortcut.addKeyListener(keyAdapter); - fldShortcut2.addKeyListener(keyAdapter); - - specialBox.addItemListener(new ItemListener() - { - public void itemStateChanged(ItemEvent evt) - { - KeybindingChooserActivator.getGlobalShortcutService(). - setSpecialKeyDetection( - (evt.getStateChange() == ItemEvent.SELECTED), - GlobalShortcutDialog.this); - } - }); - - shortcutPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, - 10)); - shortcutPanel.add(new JLabel("Primary shortcut")); - shortcutPanel.add(fldShortcut); - shortcutPanel.add(new JLabel("Secondary shortcut")); - shortcutPanel.add(fldShortcut2); - - if(OSUtils.IS_WINDOWS) - { - shortcutPanel.add(new TransparentPanel()); - shortcutPanel.add(specialBox); - } - - mainPanel.add(shortcutPanel, BorderLayout.CENTER); - - btnPanel.add(btnOK); - btnPanel.add(btnCancel); - mainPanel.add(btnPanel, BorderLayout.SOUTH); - - btnOK.requestFocus(); - - getContentPane().add(mainPanel); - pack(); - } - - /** - * {@inheritDoc} - */ - @Override - protected void close(boolean isEscaped) - { - super.close(isEscaped); - KeybindingChooserActivator.getGlobalShortcutService(). - setSpecialKeyDetection(false, this); - } - - /** - * Show the dialog and returns if the user has modified something (create - * or modify entry). - * - * @return true if the user has modified something (create - * or modify entry), false otherwise. - */ - public int showDialog() - { - setVisible(true); - - // as the dialog is modal, wait for OK/Cancel button retCode - setVisible(false); - return retCode; - } - - /** - * {@inheritDoc} - */ - public void actionPerformed(ActionEvent evt) - { - Object obj = evt.getSource(); - - if(obj == btnOK) - { - retCode = 1; - dispose(); - } - else if(obj == btnCancel) - { - retCode = 0; - dispose(); - } - } - - /** - * {@inheritDoc} - */ - public void shortcutReceived(GlobalShortcutEvent evt) - { - AWTKeyStroke ksr = evt.getKeyStroke(); - - if(ksr.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) - { - return; - } - - if(!fldShortcut.isFocusOwner() && !fldShortcut2.isFocusOwner()) - return; - - List kss = new ArrayList(); - - if(fldShortcut.isFocusOwner()) - { - kss.add(ksr); - kss.add(entry.getShortcut2()); - fldShortcut.setText("Special"); - } - else if(fldShortcut2.isFocusOwner()) - { - kss.add(entry.getShortcut()); - kss.add(ksr); - fldShortcut2.setText("Special"); - } - entry.setShortcuts(kss); - KeybindingChooserActivator.getGlobalShortcutService(). - setSpecialKeyDetection(false, this); - } - - /** - * Clear the text field. - * - * @param ui TextFieldUI to clear - */ - public void clearTextField(SIPCommTextFieldUI ui) - { - List kss = new ArrayList(); - - if(ui == fldShortcut.getUI()) - { - kss.add(null); - kss.add(entry.getShortcut2()); - entry.setShortcuts(kss); - btnOK.requestFocusInWindow(); - } - else if(ui == fldShortcut2.getUI()) - { - kss.add(entry.getShortcut()); - kss.add(null); - entry.setShortcuts(kss); - btnOK.requestFocusInWindow(); - } - } - - /** - * A custom call field. - */ - private class ShortcutField - extends SIPCommTextField - implements Skinnable - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The text field ui. - */ - private ShortcutFieldUI textFieldUI; - - /** - * Creates an instance of the CallField. - * - * @param text - */ - public ShortcutField(String text) - { - super(text); - - textFieldUI = new ShortcutFieldUI(); - textFieldUI.setDeleteButtonEnabled(true); - - this.setPreferredSize(new Dimension(200, 23)); - this.setUI(textFieldUI); - this.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); - this.setOpaque(false); - - this.setDragEnabled(true); - - loadSkin(); - } - - /** - * Reloads text field UI defs. - */ - public void loadSkin() - { - textFieldUI.loadSkin(); - } - } - - /** - * A custom text field UI. - */ - public class ShortcutFieldUI - extends SIPCommTextFieldUI - implements Skinnable - { - /** - * Creates a SIPCommTextFieldUI. - */ - public ShortcutFieldUI() - { - loadSkin(); - } - - /** - * Adds the custom mouse listeners defined in this class to the installed - * listeners. - */ - @Override - protected void installListeners() - { - super.installListeners(); - } - - /** - * {@inheritDoc} - */ - @Override - protected void updateDeleteIcon(MouseEvent evt) - { - super.updateDeleteIcon(evt); - - Rectangle deleteRect = getDeleteButtonRect(); - if(deleteRect.contains(evt.getX(), evt.getY()) && - evt.getID() == MouseEvent.MOUSE_CLICKED) - { - clearTextField(this); - } - } - - /** - * Implements parent paintSafely method and enables antialiasing. - * @param g the Graphics object that notified us - */ - @Override - protected void paintSafely(Graphics g) - { - customPaintBackground(g); - super.paintSafely(g); - } - - /** - * Paints the background of the associated component. - * @param g the Graphics object used for painting - */ - @Override - protected void customPaintBackground(Graphics g) - { - Graphics2D g2 = (Graphics2D) g.create(); - - try - { - AntialiasingManager.activateAntialiasing(g2); - super.customPaintBackground(g2); - } - finally - { - g2.dispose(); - } - } - } -} +package net.java.sip.communicator.plugin.keybindingchooser.globalchooser; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +import javax.swing.*; + +import net.java.sip.communicator.plugin.keybindingchooser.*; +import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.desktoputil.plaf.*; +import net.java.sip.communicator.service.globalshortcut.*; +import net.java.sip.communicator.util.skin.*; + +import org.jitsi.util.*; +// disambiguation + +/** + * Dialog to choose the shortcut. + * + * @author Sebastien Vincent + */ +public class GlobalShortcutDialog + extends SIPCommDialog + implements ActionListener, + GlobalShortcutListener +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Text displayed when no shortcut is configured. + */ + private static final String PRESS_TO_SETUP_SHORTCUT = + Resources.getString("plugin.keybindings.globalchooser.PRESS_BTN"); + + /** + * The global shortcut entry. + */ + private final GlobalShortcutEntry entry; + + /** + * OK button. + */ + private final JButton btnOK = new JButton( + Resources.getString("service.gui.OK")); + + /** + * Cancel button. + */ + private final JButton btnCancel = new JButton( + Resources.getString("service.gui.CANCEL")); + + /** + * Enable or not special key for shortcut. + */ + private final JCheckBox specialBox = new SIPCommCheckBox( + Resources.getString("plugin.keybindings.globalchooser.ENABLE_SPECIAL")); + + /** + * First shortcut field. + */ + private final ShortcutField fldShortcut = new ShortcutField( + PRESS_TO_SETUP_SHORTCUT); + + /** + * Secondary shortcut field. + */ + private final ShortcutField fldShortcut2 = new ShortcutField( + PRESS_TO_SETUP_SHORTCUT); + + /** + * Return code. + */ + private int retCode = 0; + + /** + * Constructor. + * + * @param dialog root dialog + * @param entry the global shortcut entry + */ + public GlobalShortcutDialog(Dialog dialog, GlobalShortcutEntry entry) + { + super(dialog); + + setModal(true); + setTitle("Global shortcut: " + entry.getAction()); + this.entry = entry; + init(); + } + + /** + * Initialize components. + */ + private void init() + { + TransparentPanel mainPanel = new TransparentPanel(new BorderLayout()); + JPanel btnPanel = new TransparentPanel( + new FlowLayout(FlowLayout.RIGHT)); + JPanel shortcutPanel = new TransparentPanel( + new GridLayout(0, 2, 0, 10)); + + btnOK.addActionListener(this); + btnCancel.addActionListener(this); + + KeyAdapter keyAdapter = new KeyAdapter() + { + private KeyEvent buffer = null; + + @Override + public void keyPressed(KeyEvent event) + { + if(event.getKeyCode() == KeyEvent.VK_ESCAPE) + { + SIPCommTextField field = + (SIPCommTextField)event.getSource(); + + AWTKeyStroke ks = null; + + if(field == fldShortcut) + { + ks = entry.getShortcut(); + } + else if(field == fldShortcut2) + { + ks = entry.getShortcut2(); + } + + if(ks == null) + field.setText(PRESS_TO_SETUP_SHORTCUT); + else + { + + if(ks.getModifiers() == + GlobalShortcutService.SPECIAL_KEY_MODIFIERS) + { + field.setText("Special"); + } + else + { + field.setText(GlobalShortcutEntry.getShortcutText( + entry.getShortcut())); + } + } + btnOK.requestFocusInWindow(); + return; + } + + if(event.getKeyCode() == 0) + return; + + // Reports KEY_PRESSED events on release to support modifiers + this.buffer = event; + } + + @Override + public void keyReleased(KeyEvent event) + { + if (buffer != null) + { + SIPCommTextField field = + (SIPCommTextField)event.getSource(); + AWTKeyStroke input = KeyStroke.getKeyStrokeForEvent(buffer); + buffer = null; + + GlobalShortcutEntry en = entry; + List kss = new ArrayList(); + + if(field == fldShortcut) + { + kss.add(input); + kss.add(en.getShortcut2()); + } + else if(field == fldShortcut2) + { + kss.add(en.getShortcut()); + kss.add(input); + } + + en.setShortcuts(kss); + en.setEditShortcut1(false); + en.setEditShortcut2(false); + field.setText(GlobalShortcutEntry.getShortcutText( + input)); + btnOK.requestFocus(); + } + } + }; + + AWTKeyStroke ks = entry.getShortcut(); + AWTKeyStroke ks2 = entry.getShortcut2(); + + if(ks != null) + { + if(ks.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) + { + fldShortcut.setText(GlobalShortcutEntry.getShortcutText(ks)); + } + else + { + fldShortcut.setText("Special"); + } + } + + if(ks2 != null) + { + + if(ks2.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) + { + fldShortcut2.setText(GlobalShortcutEntry.getShortcutText(ks2)); + } + else + { + fldShortcut2.setText("Special"); + } + } + + fldShortcut.addKeyListener(keyAdapter); + fldShortcut2.addKeyListener(keyAdapter); + + specialBox.addItemListener(new ItemListener() + { + public void itemStateChanged(ItemEvent evt) + { + KeybindingChooserActivator.getGlobalShortcutService(). + setSpecialKeyDetection( + (evt.getStateChange() == ItemEvent.SELECTED), + GlobalShortcutDialog.this); + } + }); + + shortcutPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, + 10)); + shortcutPanel.add(new JLabel("Primary shortcut")); + shortcutPanel.add(fldShortcut); + shortcutPanel.add(new JLabel("Secondary shortcut")); + shortcutPanel.add(fldShortcut2); + + if(OSUtils.IS_WINDOWS) + { + shortcutPanel.add(new TransparentPanel()); + shortcutPanel.add(specialBox); + } + + mainPanel.add(shortcutPanel, BorderLayout.CENTER); + + btnPanel.add(btnOK); + btnPanel.add(btnCancel); + mainPanel.add(btnPanel, BorderLayout.SOUTH); + + btnOK.requestFocus(); + + getContentPane().add(mainPanel); + pack(); + } + + /** + * {@inheritDoc} + */ + @Override + protected void close(boolean isEscaped) + { + super.close(isEscaped); + KeybindingChooserActivator.getGlobalShortcutService(). + setSpecialKeyDetection(false, this); + } + + /** + * Show the dialog and returns if the user has modified something (create + * or modify entry). + * + * @return true if the user has modified something (create + * or modify entry), false otherwise. + */ + public int showDialog() + { + setVisible(true); + + // as the dialog is modal, wait for OK/Cancel button retCode + setVisible(false); + return retCode; + } + + /** + * {@inheritDoc} + */ + public void actionPerformed(ActionEvent evt) + { + Object obj = evt.getSource(); + + if(obj == btnOK) + { + retCode = 1; + dispose(); + } + else if(obj == btnCancel) + { + retCode = 0; + dispose(); + } + } + + /** + * {@inheritDoc} + */ + public void shortcutReceived(GlobalShortcutEvent evt) + { + AWTKeyStroke ksr = evt.getKeyStroke(); + + if(ksr.getModifiers() != GlobalShortcutService.SPECIAL_KEY_MODIFIERS) + { + return; + } + + if(!fldShortcut.isFocusOwner() && !fldShortcut2.isFocusOwner()) + return; + + List kss = new ArrayList(); + + if(fldShortcut.isFocusOwner()) + { + kss.add(ksr); + kss.add(entry.getShortcut2()); + fldShortcut.setText("Special"); + } + else if(fldShortcut2.isFocusOwner()) + { + kss.add(entry.getShortcut()); + kss.add(ksr); + fldShortcut2.setText("Special"); + } + entry.setShortcuts(kss); + KeybindingChooserActivator.getGlobalShortcutService(). + setSpecialKeyDetection(false, this); + } + + /** + * Clear the text field. + * + * @param ui TextFieldUI to clear + */ + public void clearTextField(SIPCommTextFieldUI ui) + { + List kss = new ArrayList(); + + if(ui == fldShortcut.getUI()) + { + kss.add(null); + kss.add(entry.getShortcut2()); + entry.setShortcuts(kss); + btnOK.requestFocusInWindow(); + } + else if(ui == fldShortcut2.getUI()) + { + kss.add(entry.getShortcut()); + kss.add(null); + entry.setShortcuts(kss); + btnOK.requestFocusInWindow(); + } + } + + /** + * A custom call field. + */ + private class ShortcutField + extends SIPCommTextField + implements Skinnable + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The text field ui. + */ + private ShortcutFieldUI textFieldUI; + + /** + * Creates an instance of the CallField. + * + * @param text + */ + public ShortcutField(String text) + { + super(text); + + textFieldUI = new ShortcutFieldUI(); + textFieldUI.setDeleteButtonEnabled(true); + + this.setPreferredSize(new Dimension(200, 23)); + this.setUI(textFieldUI); + this.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + this.setOpaque(false); + + this.setDragEnabled(true); + + loadSkin(); + } + + /** + * Reloads text field UI defs. + */ + public void loadSkin() + { + textFieldUI.loadSkin(); + } + } + + /** + * A custom text field UI. + */ + public class ShortcutFieldUI + extends SIPCommTextFieldUI + implements Skinnable + { + /** + * Creates a SIPCommTextFieldUI. + */ + public ShortcutFieldUI() + { + loadSkin(); + } + + /** + * Adds the custom mouse listeners defined in this class to the installed + * listeners. + */ + @Override + protected void installListeners() + { + super.installListeners(); + } + + /** + * {@inheritDoc} + */ + @Override + protected void updateDeleteIcon(MouseEvent evt) + { + super.updateDeleteIcon(evt); + + Rectangle deleteRect = getDeleteButtonRect(); + if(deleteRect.contains(evt.getX(), evt.getY()) && + evt.getID() == MouseEvent.MOUSE_CLICKED) + { + clearTextField(this); + } + } + + /** + * Implements parent paintSafely method and enables antialiasing. + * @param g the Graphics object that notified us + */ + @Override + protected void paintSafely(Graphics g) + { + customPaintBackground(g); + super.paintSafely(g); + } + + /** + * Paints the background of the associated component. + * @param g the Graphics object used for painting + */ + @Override + protected void customPaintBackground(Graphics g) + { + Graphics2D g2 = (Graphics2D) g.create(); + + try + { + AntialiasingManager.activateAntialiasing(g2); + super.customPaintBackground(g2); + } + finally + { + g2.dispose(); + } + } + } +} diff --git a/src/net/java/sip/communicator/plugin/otr/OtrConfigurator.java b/src/net/java/sip/communicator/plugin/otr/OtrConfigurator.java index 42efc97..dd3940b 100644 --- a/src/net/java/sip/communicator/plugin/otr/OtrConfigurator.java +++ b/src/net/java/sip/communicator/plugin/otr/OtrConfigurator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,171 +15,171 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import java.util.*; - -import org.bouncycastle.util.encoders.Base64; // disambiguation -import org.jitsi.service.configuration.*; - -/** - * A class that gets/sets the OTR configuration values. Introduced to assure our - * configuration is properly written when XMLConfigurationStore is - * used. Can be seen as a proxy between the {@link ConfigurationService} and the - * OTR Plugin. - * - * @author George Politis - */ -public class OtrConfigurator -{ - /** - * Gets an XML tag friendly {@link String} from a {@link String}. - * - * @param s a {@link String} - * @return an XML friendly {@link String} - */ - private String getXmlFriendlyString(String s) - { - if (s == null || s.length() < 1) - return s; - - // XML Tags are not allowed to start with digits, - // insert a dummy "p" char. - if (Character.isDigit(s.charAt(0))) - s = "p" + s; - - char[] cId = new char[s.length()]; - - for (int i = 0; i < cId.length; i++) - { - char c = s.charAt(i); - - cId[i] = Character.isLetterOrDigit(c) ? c : '_'; - } - - return new String(cId); - } - - /** - * Puts a given property ID under the OTR namespace and makes sure it is XML - * tag friendly. - * - * @param id the property ID. - * @return the namespaced ID. - */ - private String getID(String id) - { - return - "net.java.sip.communicator.plugin.otr." + getXmlFriendlyString(id); - } - - /** - * Returns the value of the property with the specified name or null if no - * such property exists ({@link ConfigurationService#getProperty(String)} - * proxy). - * - * @param id of the property that is being queried. - * @return the byte[] value of the property with the specified - * name. - */ - public byte[] getPropertyBytes(String id) - { - String value = OtrActivator.configService.getString(getID(id)); - - return (value == null) ? null : Base64.decode(value.getBytes()); - } - - /** - * Gets the value of a specific property as a boolean ( - * {@link ConfigurationService#getBoolean(String, boolean)} proxy). - * - * @param id of the property that is being queried. - * @param defaultValue the value to be returned if the specified property - * name is not associated with a value. - * @return the Boolean value of the property with the specified - * name. - */ - public boolean getPropertyBoolean(String id, boolean defaultValue) - { - return - OtrActivator.configService.getBoolean(getID(id), defaultValue); - } - - /** - * Sets the property with the specified name to the specified value ( - * {@link ConfigurationService#setProperty(String, Object)} proxy). The - * value is Base64 encoded. - * - * @param id the name of the property to change. - * @param value the new value of the specified property. - */ - public void setProperty(String id, byte[] value) - { - String valueToStore = new String(Base64.encode(value)); - - OtrActivator.configService.setProperty(getID(id), valueToStore); - } - - /** - * Sets the property with the specified name to the specified value ( - * {@link ConfigurationService#setProperty(String, Object)} proxy). - * - * @param id the name of the property to change. - * @param value the new value of the specified property. - */ - public void setProperty(String id, Object value) - { - OtrActivator.configService.setProperty(getID(id), value); - } - - /** - * Removes the property with the specified name ( - * {@link ConfigurationService#removeProperty(String)} proxy). - * - * @param id the name of the property to change. - */ - public void removeProperty(String id) - { - OtrActivator.configService.removeProperty(getID(id)); - } - - /** - * Gets the value of a specific property as a signed decimal integer. - * - * @param id the name of the property to change. - * @param defaultValue the value to be returned if the specified property - * name is not associated with a value. - * @return the int value of the property - */ - public int getPropertyInt(String id, int defaultValue) - { - return OtrActivator.configService.getInt(getID(id), defaultValue); - } - - /** - * Appends value to the old value of the property with the - * specified name. The two values will be comma separated. - * - * @param id the name of the property to append to - * @param value the value to append - */ - public void appendProperty(String id, Object value) - { - Object oldValue = OtrActivator.configService.getProperty(getID(id)); - - String newValue = - oldValue == null ? value.toString() : oldValue + "," + value; - - setProperty(id, newValue); - } - - public List getAppendedProperties(String id) - { - String listProperties = - (String) OtrActivator.configService.getProperty(getID(id)); - - if (listProperties == null) return new ArrayList(); - - return Arrays.asList(listProperties.split(",")); - } -} +package net.java.sip.communicator.plugin.otr; + +import java.util.*; + +import org.bouncycastle.util.encoders.Base64; // disambiguation +import org.jitsi.service.configuration.*; + +/** + * A class that gets/sets the OTR configuration values. Introduced to assure our + * configuration is properly written when XMLConfigurationStore is + * used. Can be seen as a proxy between the {@link ConfigurationService} and the + * OTR Plugin. + * + * @author George Politis + */ +public class OtrConfigurator +{ + /** + * Gets an XML tag friendly {@link String} from a {@link String}. + * + * @param s a {@link String} + * @return an XML friendly {@link String} + */ + private String getXmlFriendlyString(String s) + { + if (s == null || s.length() < 1) + return s; + + // XML Tags are not allowed to start with digits, + // insert a dummy "p" char. + if (Character.isDigit(s.charAt(0))) + s = "p" + s; + + char[] cId = new char[s.length()]; + + for (int i = 0; i < cId.length; i++) + { + char c = s.charAt(i); + + cId[i] = Character.isLetterOrDigit(c) ? c : '_'; + } + + return new String(cId); + } + + /** + * Puts a given property ID under the OTR namespace and makes sure it is XML + * tag friendly. + * + * @param id the property ID. + * @return the namespaced ID. + */ + private String getID(String id) + { + return + "net.java.sip.communicator.plugin.otr." + getXmlFriendlyString(id); + } + + /** + * Returns the value of the property with the specified name or null if no + * such property exists ({@link ConfigurationService#getProperty(String)} + * proxy). + * + * @param id of the property that is being queried. + * @return the byte[] value of the property with the specified + * name. + */ + public byte[] getPropertyBytes(String id) + { + String value = OtrActivator.configService.getString(getID(id)); + + return (value == null) ? null : Base64.decode(value.getBytes()); + } + + /** + * Gets the value of a specific property as a boolean ( + * {@link ConfigurationService#getBoolean(String, boolean)} proxy). + * + * @param id of the property that is being queried. + * @param defaultValue the value to be returned if the specified property + * name is not associated with a value. + * @return the Boolean value of the property with the specified + * name. + */ + public boolean getPropertyBoolean(String id, boolean defaultValue) + { + return + OtrActivator.configService.getBoolean(getID(id), defaultValue); + } + + /** + * Sets the property with the specified name to the specified value ( + * {@link ConfigurationService#setProperty(String, Object)} proxy). The + * value is Base64 encoded. + * + * @param id the name of the property to change. + * @param value the new value of the specified property. + */ + public void setProperty(String id, byte[] value) + { + String valueToStore = new String(Base64.encode(value)); + + OtrActivator.configService.setProperty(getID(id), valueToStore); + } + + /** + * Sets the property with the specified name to the specified value ( + * {@link ConfigurationService#setProperty(String, Object)} proxy). + * + * @param id the name of the property to change. + * @param value the new value of the specified property. + */ + public void setProperty(String id, Object value) + { + OtrActivator.configService.setProperty(getID(id), value); + } + + /** + * Removes the property with the specified name ( + * {@link ConfigurationService#removeProperty(String)} proxy). + * + * @param id the name of the property to change. + */ + public void removeProperty(String id) + { + OtrActivator.configService.removeProperty(getID(id)); + } + + /** + * Gets the value of a specific property as a signed decimal integer. + * + * @param id the name of the property to change. + * @param defaultValue the value to be returned if the specified property + * name is not associated with a value. + * @return the int value of the property + */ + public int getPropertyInt(String id, int defaultValue) + { + return OtrActivator.configService.getInt(getID(id), defaultValue); + } + + /** + * Appends value to the old value of the property with the + * specified name. The two values will be comma separated. + * + * @param id the name of the property to append to + * @param value the value to append + */ + public void appendProperty(String id, Object value) + { + Object oldValue = OtrActivator.configService.getProperty(getID(id)); + + String newValue = + oldValue == null ? value.toString() : oldValue + "," + value; + + setProperty(id, newValue); + } + + public List getAppendedProperties(String id) + { + String listProperties = + (String) OtrActivator.configService.getProperty(getID(id)); + + if (listProperties == null) return new ArrayList(); + + return Arrays.asList(listProperties.split(",")); + } +} diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java index 183eed7..ae50390 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,44 +15,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import java.security.*; -import java.util.*; - -import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; -import net.java.sip.communicator.service.protocol.*; - -/** - * - * @author George Politis - * - */ -public interface ScOtrKeyManager -{ - - public abstract void addListener(ScOtrKeyManagerListener l); - - public abstract void removeListener(ScOtrKeyManagerListener l); - - public abstract void verify(OtrContact contact, String fingerprint); - - public abstract void unverify(OtrContact contact, String fingerprint); - - public abstract boolean isVerified(Contact contact, String fingerprint); - - public abstract String getFingerprintFromPublicKey(PublicKey pubKey); - - public abstract List getAllRemoteFingerprints(Contact contact); - - public abstract String getLocalFingerprint(AccountID account); - - public abstract byte[] getLocalFingerprintRaw(AccountID account); - - public abstract void saveFingerprint(Contact contact, String fingerprint); - - public abstract KeyPair loadKeyPair(AccountID accountID); - - public abstract void generateKeyPair(AccountID accountID); - +package net.java.sip.communicator.plugin.otr; + +import java.security.*; +import java.util.*; + +import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; +import net.java.sip.communicator.service.protocol.*; + +/** + * + * @author George Politis + * + */ +public interface ScOtrKeyManager +{ + + public abstract void addListener(ScOtrKeyManagerListener l); + + public abstract void removeListener(ScOtrKeyManagerListener l); + + public abstract void verify(OtrContact contact, String fingerprint); + + public abstract void unverify(OtrContact contact, String fingerprint); + + public abstract boolean isVerified(Contact contact, String fingerprint); + + public abstract String getFingerprintFromPublicKey(PublicKey pubKey); + + public abstract List getAllRemoteFingerprints(Contact contact); + + public abstract String getLocalFingerprint(AccountID account); + + public abstract byte[] getLocalFingerprintRaw(AccountID account); + + public abstract void saveFingerprint(Contact contact, String fingerprint); + + public abstract KeyPair loadKeyPair(AccountID accountID); + + public abstract void generateKeyPair(AccountID accountID); + } diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java index 890211e..cb57ba4 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,311 +15,311 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import java.security.*; -import java.security.spec.*; -import java.util.*; - -import net.java.otr4j.crypto.*; -import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; -import net.java.sip.communicator.service.protocol.*; - -/** - * - * @author George Politis - * @author Lyubomir Marinov - */ -public class ScOtrKeyManagerImpl - implements ScOtrKeyManager -{ - private final OtrConfigurator configurator = new OtrConfigurator(); - - private final List listeners = - new Vector(); - - public void addListener(ScOtrKeyManagerListener l) - { - synchronized (listeners) - { - if (!listeners.contains(l)) - listeners.add(l); - } - } - - /** - * Gets a copy of the list of ScOtrKeyManagerListeners registered - * with this instance which may safely be iterated without the risk of a - * ConcurrentModificationException. - * - * @return a copy of the list of ScOtrKeyManagerListeners registered - * with this instance which may safely be iterated without the risk of a - * ConcurrentModificationException - */ - private ScOtrKeyManagerListener[] getListeners() - { - synchronized (listeners) - { - return - listeners.toArray( - new ScOtrKeyManagerListener[listeners.size()]); - } - } - - public void removeListener(ScOtrKeyManagerListener l) - { - synchronized (listeners) - { - listeners.remove(l); - } - } - - public void verify(OtrContact otrContact, String fingerprint) - { - if ((fingerprint == null) || otrContact == null) - return; - - this.configurator.setProperty(otrContact.contact.getAddress() + fingerprint - + ".fingerprint.verified", true); - - for (ScOtrKeyManagerListener l : getListeners()) - l.contactVerificationStatusChanged(otrContact); - } - - public void unverify(OtrContact otrContact, String fingerprint) - { - if ((fingerprint == null) || otrContact == null) - return; - - this.configurator.setProperty(otrContact.contact.getAddress() + fingerprint - + ".fingerprint.verified", false); - - for (ScOtrKeyManagerListener l : getListeners()) - l.contactVerificationStatusChanged(otrContact); - } - - public boolean isVerified(Contact contact, String fingerprint) - { - if (fingerprint == null || contact == null) - return false; - - return this.configurator.getPropertyBoolean( - contact.getAddress() + fingerprint - + ".fingerprint.verified", false); - } - - public List getAllRemoteFingerprints(Contact contact) - { - if (contact == null) - return null; - - /* - * The following lines are needed for backward compatibility with old - * versions of the otr plugin. Instead of lists of fingerprints the otr - * plugin used to store one public key for every contact in the form of - * "userID.publicKey=..." and one boolean property in the form of - * "userID.publicKey.verified=...". In order not to loose these old - * properties we have to convert them to match the new format. - */ - String userID = contact.getAddress(); - - byte[] b64PubKey = - this.configurator.getPropertyBytes(userID + ".publicKey"); - if (b64PubKey != null) - { - // We delete the old format property because we are going to convert - // it in the new format - this.configurator.removeProperty(userID + ".publicKey"); - - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); - - KeyFactory keyFactory; - try - { - keyFactory = KeyFactory.getInstance("DSA"); - PublicKey pubKey = keyFactory.generatePublic(publicKeySpec); - - boolean isVerified = - this.configurator.getPropertyBoolean(userID - + ".publicKey.verified", false); - - // We also make sure to delete this old format property if it - // exists. - this.configurator.removeProperty(userID + ".publicKey.verified"); - - String fingerprint = getFingerprintFromPublicKey(pubKey); - - // Now we can store the old properties in the new format. - if (isVerified) - verify(OtrContactManager.getOtrContact(contact, null), fingerprint); - else - unverify(OtrContactManager.getOtrContact(contact, null), fingerprint); - - // Finally we append the new fingerprint to out stored list of - // fingerprints. - this.configurator.appendProperty( - userID + ".fingerprints", fingerprint); - } - catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - } - catch (InvalidKeySpecException e) - { - e.printStackTrace(); - } - } - - // Now we can safely return our list of fingerprints for this contact - // without worrying that we missed an old format property. - return this.configurator.getAppendedProperties( - contact.getAddress() + ".fingerprints"); - } - - public String getFingerprintFromPublicKey(PublicKey pubKey) - { - try - { - return new OtrCryptoEngineImpl().getFingerprint(pubKey); - } - catch (OtrCryptoException e) - { - e.printStackTrace(); - return null; - } - } - - public String getLocalFingerprint(AccountID account) - { - KeyPair keyPair = loadKeyPair(account); - - if (keyPair == null) - return null; - - PublicKey pubKey = keyPair.getPublic(); - - try - { - return new OtrCryptoEngineImpl().getFingerprint(pubKey); - } - catch (OtrCryptoException e) - { - e.printStackTrace(); - return null; - } - } - - public byte[] getLocalFingerprintRaw(AccountID account) - { - KeyPair keyPair = loadKeyPair(account); - - if (keyPair == null) - return null; - - PublicKey pubKey = keyPair.getPublic(); - - try - { - return new OtrCryptoEngineImpl().getFingerprintRaw(pubKey); - } - catch (OtrCryptoException e) - { - e.printStackTrace(); - return null; - } - } - - public void saveFingerprint(Contact contact, String fingerprint) - { - if (contact == null) - return; - - this.configurator.appendProperty(contact.getAddress() + ".fingerprints", - fingerprint); - - this.configurator.setProperty(contact.getAddress() + fingerprint - + ".fingerprint.verified", false); - } - - public KeyPair loadKeyPair(AccountID account) - { - if (account == null) - return null; - - String accountID = account.getAccountUniqueID(); - // Load Private Key. - byte[] b64PrivKey = - this.configurator.getPropertyBytes(accountID + ".privateKey"); - if (b64PrivKey == null) - return null; - - PKCS8EncodedKeySpec privateKeySpec = - new PKCS8EncodedKeySpec(b64PrivKey); - - // Load Public Key. - byte[] b64PubKey = - this.configurator.getPropertyBytes(accountID + ".publicKey"); - if (b64PubKey == null) - return null; - - X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); - - PublicKey publicKey; - PrivateKey privateKey; - - // Generate KeyPair. - KeyFactory keyFactory; - try - { - keyFactory = KeyFactory.getInstance("DSA"); - publicKey = keyFactory.generatePublic(publicKeySpec); - privateKey = keyFactory.generatePrivate(privateKeySpec); - } - catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - return null; - } - catch (InvalidKeySpecException e) - { - e.printStackTrace(); - return null; - } - - return new KeyPair(publicKey, privateKey); - } - - public void generateKeyPair(AccountID account) - { - if (account == null) - return; - - String accountID = account.getAccountUniqueID(); - KeyPair keyPair; - try - { - keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair(); - } - catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); - return; - } - - // Store Public Key. - PublicKey pubKey = keyPair.getPublic(); - X509EncodedKeySpec x509EncodedKeySpec = - new X509EncodedKeySpec(pubKey.getEncoded()); - - this.configurator.setProperty(accountID + ".publicKey", - x509EncodedKeySpec.getEncoded()); - - // Store Private Key. - PrivateKey privKey = keyPair.getPrivate(); - PKCS8EncodedKeySpec pkcs8EncodedKeySpec = - new PKCS8EncodedKeySpec(privKey.getEncoded()); - - this.configurator.setProperty(accountID + ".privateKey", - pkcs8EncodedKeySpec.getEncoded()); - } -} +package net.java.sip.communicator.plugin.otr; + +import java.security.*; +import java.security.spec.*; +import java.util.*; + +import net.java.otr4j.crypto.*; +import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; +import net.java.sip.communicator.service.protocol.*; + +/** + * + * @author George Politis + * @author Lyubomir Marinov + */ +public class ScOtrKeyManagerImpl + implements ScOtrKeyManager +{ + private final OtrConfigurator configurator = new OtrConfigurator(); + + private final List listeners = + new Vector(); + + public void addListener(ScOtrKeyManagerListener l) + { + synchronized (listeners) + { + if (!listeners.contains(l)) + listeners.add(l); + } + } + + /** + * Gets a copy of the list of ScOtrKeyManagerListeners registered + * with this instance which may safely be iterated without the risk of a + * ConcurrentModificationException. + * + * @return a copy of the list of ScOtrKeyManagerListeners registered + * with this instance which may safely be iterated without the risk of a + * ConcurrentModificationException + */ + private ScOtrKeyManagerListener[] getListeners() + { + synchronized (listeners) + { + return + listeners.toArray( + new ScOtrKeyManagerListener[listeners.size()]); + } + } + + public void removeListener(ScOtrKeyManagerListener l) + { + synchronized (listeners) + { + listeners.remove(l); + } + } + + public void verify(OtrContact otrContact, String fingerprint) + { + if ((fingerprint == null) || otrContact == null) + return; + + this.configurator.setProperty(otrContact.contact.getAddress() + fingerprint + + ".fingerprint.verified", true); + + for (ScOtrKeyManagerListener l : getListeners()) + l.contactVerificationStatusChanged(otrContact); + } + + public void unverify(OtrContact otrContact, String fingerprint) + { + if ((fingerprint == null) || otrContact == null) + return; + + this.configurator.setProperty(otrContact.contact.getAddress() + fingerprint + + ".fingerprint.verified", false); + + for (ScOtrKeyManagerListener l : getListeners()) + l.contactVerificationStatusChanged(otrContact); + } + + public boolean isVerified(Contact contact, String fingerprint) + { + if (fingerprint == null || contact == null) + return false; + + return this.configurator.getPropertyBoolean( + contact.getAddress() + fingerprint + + ".fingerprint.verified", false); + } + + public List getAllRemoteFingerprints(Contact contact) + { + if (contact == null) + return null; + + /* + * The following lines are needed for backward compatibility with old + * versions of the otr plugin. Instead of lists of fingerprints the otr + * plugin used to store one public key for every contact in the form of + * "userID.publicKey=..." and one boolean property in the form of + * "userID.publicKey.verified=...". In order not to loose these old + * properties we have to convert them to match the new format. + */ + String userID = contact.getAddress(); + + byte[] b64PubKey = + this.configurator.getPropertyBytes(userID + ".publicKey"); + if (b64PubKey != null) + { + // We delete the old format property because we are going to convert + // it in the new format + this.configurator.removeProperty(userID + ".publicKey"); + + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); + + KeyFactory keyFactory; + try + { + keyFactory = KeyFactory.getInstance("DSA"); + PublicKey pubKey = keyFactory.generatePublic(publicKeySpec); + + boolean isVerified = + this.configurator.getPropertyBoolean(userID + + ".publicKey.verified", false); + + // We also make sure to delete this old format property if it + // exists. + this.configurator.removeProperty(userID + ".publicKey.verified"); + + String fingerprint = getFingerprintFromPublicKey(pubKey); + + // Now we can store the old properties in the new format. + if (isVerified) + verify(OtrContactManager.getOtrContact(contact, null), fingerprint); + else + unverify(OtrContactManager.getOtrContact(contact, null), fingerprint); + + // Finally we append the new fingerprint to out stored list of + // fingerprints. + this.configurator.appendProperty( + userID + ".fingerprints", fingerprint); + } + catch (NoSuchAlgorithmException e) + { + e.printStackTrace(); + } + catch (InvalidKeySpecException e) + { + e.printStackTrace(); + } + } + + // Now we can safely return our list of fingerprints for this contact + // without worrying that we missed an old format property. + return this.configurator.getAppendedProperties( + contact.getAddress() + ".fingerprints"); + } + + public String getFingerprintFromPublicKey(PublicKey pubKey) + { + try + { + return new OtrCryptoEngineImpl().getFingerprint(pubKey); + } + catch (OtrCryptoException e) + { + e.printStackTrace(); + return null; + } + } + + public String getLocalFingerprint(AccountID account) + { + KeyPair keyPair = loadKeyPair(account); + + if (keyPair == null) + return null; + + PublicKey pubKey = keyPair.getPublic(); + + try + { + return new OtrCryptoEngineImpl().getFingerprint(pubKey); + } + catch (OtrCryptoException e) + { + e.printStackTrace(); + return null; + } + } + + public byte[] getLocalFingerprintRaw(AccountID account) + { + KeyPair keyPair = loadKeyPair(account); + + if (keyPair == null) + return null; + + PublicKey pubKey = keyPair.getPublic(); + + try + { + return new OtrCryptoEngineImpl().getFingerprintRaw(pubKey); + } + catch (OtrCryptoException e) + { + e.printStackTrace(); + return null; + } + } + + public void saveFingerprint(Contact contact, String fingerprint) + { + if (contact == null) + return; + + this.configurator.appendProperty(contact.getAddress() + ".fingerprints", + fingerprint); + + this.configurator.setProperty(contact.getAddress() + fingerprint + + ".fingerprint.verified", false); + } + + public KeyPair loadKeyPair(AccountID account) + { + if (account == null) + return null; + + String accountID = account.getAccountUniqueID(); + // Load Private Key. + byte[] b64PrivKey = + this.configurator.getPropertyBytes(accountID + ".privateKey"); + if (b64PrivKey == null) + return null; + + PKCS8EncodedKeySpec privateKeySpec = + new PKCS8EncodedKeySpec(b64PrivKey); + + // Load Public Key. + byte[] b64PubKey = + this.configurator.getPropertyBytes(accountID + ".publicKey"); + if (b64PubKey == null) + return null; + + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(b64PubKey); + + PublicKey publicKey; + PrivateKey privateKey; + + // Generate KeyPair. + KeyFactory keyFactory; + try + { + keyFactory = KeyFactory.getInstance("DSA"); + publicKey = keyFactory.generatePublic(publicKeySpec); + privateKey = keyFactory.generatePrivate(privateKeySpec); + } + catch (NoSuchAlgorithmException e) + { + e.printStackTrace(); + return null; + } + catch (InvalidKeySpecException e) + { + e.printStackTrace(); + return null; + } + + return new KeyPair(publicKey, privateKey); + } + + public void generateKeyPair(AccountID account) + { + if (account == null) + return; + + String accountID = account.getAccountUniqueID(); + KeyPair keyPair; + try + { + keyPair = KeyPairGenerator.getInstance("DSA").genKeyPair(); + } + catch (NoSuchAlgorithmException e) + { + e.printStackTrace(); + return; + } + + // Store Public Key. + PublicKey pubKey = keyPair.getPublic(); + X509EncodedKeySpec x509EncodedKeySpec = + new X509EncodedKeySpec(pubKey.getEncoded()); + + this.configurator.setProperty(accountID + ".publicKey", + x509EncodedKeySpec.getEncoded()); + + // Store Private Key. + PrivateKey privKey = keyPair.getPrivate(); + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = + new PKCS8EncodedKeySpec(privKey.getEncoded()); + + this.configurator.setProperty(accountID + ".privateKey", + pkcs8EncodedKeySpec.getEncoded()); + } +} diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerListener.java b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerListener.java index aeabf75..95403d3 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerListener.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrKeyManagerListener.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,15 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; - -/** - * - * @author George Politis - */ -public interface ScOtrKeyManagerListener -{ - public void contactVerificationStatusChanged(OtrContact contact); -} +package net.java.sip.communicator.plugin.otr; + +import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; + +/** + * + * @author George Politis + */ +public interface ScOtrKeyManagerListener +{ + public void contactVerificationStatusChanged(OtrContact contact); +} diff --git a/src/net/java/sip/communicator/plugin/otr/ScSessionID.java b/src/net/java/sip/communicator/plugin/otr/ScSessionID.java index 4392045..1a55fcd 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScSessionID.java +++ b/src/net/java/sip/communicator/plugin/otr/ScSessionID.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,83 +15,83 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import java.util.*; - -import net.java.otr4j.session.*; - -/** - * Class used to associate a random UUID to an OTR4J SessionID. - * - * @author Daniel Perren - */ -public class ScSessionID -{ - private final UUID guid = UUID.randomUUID(); - - private final SessionID sessionID; - - /** - * Creates a new instance of this class. - * - * @param sessionID the OTR4J SessionID that is being wrapped. - */ - public ScSessionID(SessionID sessionID) - { - this.sessionID = sessionID; - } - - /** - * Overrides equals() for the ability to get the hashcode from sessionID. - * - * @param obj the object to compare - * @return true if the objects are considered equal. - */ - @Override - public boolean equals(Object obj) - { - return (obj != null) && sessionID.toString().equals(obj.toString()); - } - - /** - * Get the current GUID. - * - * @return The GUID generated for this SessionID. - */ - public UUID getGUID() - { - return guid; - } - - /** - * Gets the wrapped session ID - * - * @return sessionID - */ - public SessionID getSessionID() - { - return sessionID; - } - - /** - * Returns {@link SessionID#hashCode()} of the wrapped SessionID. - * - * @return HashCode of the wrapped SessionID. - */ - @Override - public int hashCode() - { - return sessionID.hashCode(); - } - - /** - * Returns {@link SessionID#toString()} of the wrapped SessionID. - * @return String representation of the wrapped SessionID. - */ - @Override - public String toString() - { - return sessionID.toString(); - } -} +package net.java.sip.communicator.plugin.otr; + +import java.util.*; + +import net.java.otr4j.session.*; + +/** + * Class used to associate a random UUID to an OTR4J SessionID. + * + * @author Daniel Perren + */ +public class ScSessionID +{ + private final UUID guid = UUID.randomUUID(); + + private final SessionID sessionID; + + /** + * Creates a new instance of this class. + * + * @param sessionID the OTR4J SessionID that is being wrapped. + */ + public ScSessionID(SessionID sessionID) + { + this.sessionID = sessionID; + } + + /** + * Overrides equals() for the ability to get the hashcode from sessionID. + * + * @param obj the object to compare + * @return true if the objects are considered equal. + */ + @Override + public boolean equals(Object obj) + { + return (obj != null) && sessionID.toString().equals(obj.toString()); + } + + /** + * Get the current GUID. + * + * @return The GUID generated for this SessionID. + */ + public UUID getGUID() + { + return guid; + } + + /** + * Gets the wrapped session ID + * + * @return sessionID + */ + public SessionID getSessionID() + { + return sessionID; + } + + /** + * Returns {@link SessionID#hashCode()} of the wrapped SessionID. + * + * @return HashCode of the wrapped SessionID. + */ + @Override + public int hashCode() + { + return sessionID.hashCode(); + } + + /** + * Returns {@link SessionID#toString()} of the wrapped SessionID. + * @return String representation of the wrapped SessionID. + */ + @Override + public String toString() + { + return sessionID.toString(); + } +} diff --git a/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberContactSource.java b/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberContactSource.java index 3f916a7..954f5d5 100644 --- a/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberContactSource.java +++ b/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberContactSource.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,79 +15,79 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.phonenumbercontactsource; - -import net.java.sip.communicator.service.contactsource.*; - -/** - * The PhoneNumberContactSource is a source of phone numbers coming - * from the server stored contact info of all contacts for all protocol - * providers. - * - * @author Yana Stamcheva - */ -public class PhoneNumberContactSource - implements ContactSourceService -{ - /** - * Returns DEFAULT_TYPE to indicate that this contact source is a default - * source. - * - * @return the type of this contact source - */ - public int getType() - { - return DEFAULT_TYPE; - } - - /** - * Returns a user-friendly string that identifies this contact source. - * - * @return the display name of this contact source - */ - public String getDisplayName() - { - return PNContactSourceActivator.getResources().getI18NString( - "plugin.phonenumbercontactsource.DISPLAY_NAME"); - } - - /** - * Creates query for the given queryString. - * - * @param queryString the string to search for - * @return the created query - */ - public ContactQuery createContactQuery(String queryString) - { - return createContactQuery(queryString, -1); - } - - /** - * Creates query for the given queryString. - * - * @param queryString the string to search for - * @param contactCount the maximum count of result contacts - * @return the created query - */ - public ContactQuery createContactQuery( String queryString, - int contactCount) - { - if (queryString == null) - queryString = ""; - - PhoneNumberContactQuery contactQuery - = new PhoneNumberContactQuery(this, queryString, contactCount); - - return contactQuery; - } - - /** - * Returns the index of the contact source in the result list. - * - * @return the index of the contact source in the result list - */ - public int getIndex() - { - return -1; - } -} +package net.java.sip.communicator.plugin.phonenumbercontactsource; + +import net.java.sip.communicator.service.contactsource.*; + +/** + * The PhoneNumberContactSource is a source of phone numbers coming + * from the server stored contact info of all contacts for all protocol + * providers. + * + * @author Yana Stamcheva + */ +public class PhoneNumberContactSource + implements ContactSourceService +{ + /** + * Returns DEFAULT_TYPE to indicate that this contact source is a default + * source. + * + * @return the type of this contact source + */ + public int getType() + { + return DEFAULT_TYPE; + } + + /** + * Returns a user-friendly string that identifies this contact source. + * + * @return the display name of this contact source + */ + public String getDisplayName() + { + return PNContactSourceActivator.getResources().getI18NString( + "plugin.phonenumbercontactsource.DISPLAY_NAME"); + } + + /** + * Creates query for the given queryString. + * + * @param queryString the string to search for + * @return the created query + */ + public ContactQuery createContactQuery(String queryString) + { + return createContactQuery(queryString, -1); + } + + /** + * Creates query for the given queryString. + * + * @param queryString the string to search for + * @param contactCount the maximum count of result contacts + * @return the created query + */ + public ContactQuery createContactQuery( String queryString, + int contactCount) + { + if (queryString == null) + queryString = ""; + + PhoneNumberContactQuery contactQuery + = new PhoneNumberContactQuery(this, queryString, contactCount); + + return contactQuery; + } + + /** + * Returns the index of the contact source in the result list. + * + * @return the index of the contact source in the result list + */ + public int getIndex() + { + return -1; + } +} diff --git a/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java b/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java index f8ab3a6..1e59786 100644 --- a/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java +++ b/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,58 +15,58 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.profiler4j; - -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.gui.*; -import net.sf.profiler4j.console.*; - -/** - * Menu entry for the profiler plug-in - * - * @author Vladimir Skarupelov - */ -public class SettingsWindowMenuEntry - extends AbstractPluginComponent -{ - private static final String PROFILER_NAME = "plugin.profiler.PLUGIN_NAME"; - private JMenuItem settingsMenuEntry; - - public SettingsWindowMenuEntry(Container container, - PluginComponentFactory parentFactory) - { - super(container, parentFactory); - - settingsMenuEntry = new JMenuItem(Resources.getString( PROFILER_NAME )); - settingsMenuEntry.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - Prefs prefs = new Prefs(); - - System.setProperty("swing.aatext", - String.valueOf(prefs.isAntialiasing())); - - final Console app = new Console(prefs); - app.connect(); - MainFrame f = new MainFrame(app); - app.setMainFrame(f); - f.pack(); - f.setVisible(true); - } - }); - } - - public Object getComponent() - { - return settingsMenuEntry; - } - - public String getName() - { - return Resources.getString( PROFILER_NAME ); - } -} +package net.java.sip.communicator.plugin.profiler4j; + +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.gui.*; +import net.sf.profiler4j.console.*; + +/** + * Menu entry for the profiler plug-in + * + * @author Vladimir Skarupelov + */ +public class SettingsWindowMenuEntry + extends AbstractPluginComponent +{ + private static final String PROFILER_NAME = "plugin.profiler.PLUGIN_NAME"; + private JMenuItem settingsMenuEntry; + + public SettingsWindowMenuEntry(Container container, + PluginComponentFactory parentFactory) + { + super(container, parentFactory); + + settingsMenuEntry = new JMenuItem(Resources.getString( PROFILER_NAME )); + settingsMenuEntry.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + Prefs prefs = new Prefs(); + + System.setProperty("swing.aatext", + String.valueOf(prefs.isAntialiasing())); + + final Console app = new Console(prefs); + app.connect(); + MainFrame f = new MainFrame(app); + app.setMainFrame(f); + f.pack(); + f.setVisible(true); + } + }); + } + + public Object getComponent() + { + return settingsMenuEntry; + } + + public String getName() + { + return Resources.getString( PROFILER_NAME ); + } +} diff --git a/src/net/java/sip/communicator/plugin/simpleaccreg/InitialAccountRegistrationFrame.java b/src/net/java/sip/communicator/plugin/simpleaccreg/InitialAccountRegistrationFrame.java index b8d6a2a..e1213ce 100644 --- a/src/net/java/sip/communicator/plugin/simpleaccreg/InitialAccountRegistrationFrame.java +++ b/src/net/java/sip/communicator/plugin/simpleaccreg/InitialAccountRegistrationFrame.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,736 +15,736 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.simpleaccreg; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.util.*; -import java.util.List; - -import javax.imageio.*; -import javax.swing.*; -import javax.swing.text.*; - -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * The NoAccountFoundPage is the page shown in the account - * registration wizard shown in the beginning of the program, when no registered - * accounts are found. - * - * @author Yana Stamcheva - * @author Lubomir Marinov - */ -public class InitialAccountRegistrationFrame - extends SIPCommFrame -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private ConfigurationService configurationService; - - /** - * The Logger used by this InitialAccountRegistrationFrame - * for logging output. - */ - private final Logger logger - = Logger.getLogger(InitialAccountRegistrationFrame.class); - - private final TransparentPanel mainAccountsPanel - = new TransparentPanel(new BorderLayout(10, 10)); - - private final TransparentPanel accountsPanel - = new TransparentPanel(new GridLayout(0, 2, 10, 10)); - - private final TransparentPanel southPanel - = new TransparentPanel(new BorderLayout()); - - private final JButton signinButton - = new JButton(Resources.getString("service.gui.SIGN_IN")); - - private final Collection registrationForms = - new Vector(); - - /** - * Creates an instance of NoAccountFoundPage. - */ - public InitialAccountRegistrationFrame() - { - super(false); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - - TransparentPanel mainPanel - = new TransparentPanel(new BorderLayout()); - mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - southPanel.add(buttonPanel, BorderLayout.EAST); - JButton cancelButton - = new JButton(Resources.getString("service.gui.CANCEL")); - - this.setTitle(Resources.getString("service.gui.SIGN_IN")); - - this.setIconImage( - Resources.getImage("service.gui.SIP_COMMUNICATOR_LOGO").getImage()); - - // In order to have the same icon when using option panes - JOptionPane.getRootFrame().setIconImage( - Resources.getImage("service.gui.SIP_COMMUNICATOR_LOGO").getImage()); - - mainAccountsPanel.setBorder( - BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.getContentPane().add(mainPanel); - - mainPanel.add(createTitleComponent(), BorderLayout.NORTH); - JScrollPane scroller = new JScrollPane(mainAccountsPanel); - scroller.setOpaque(false); - scroller.getViewport().setOpaque(false); - mainPanel.add(scroller, BorderLayout.CENTER); - mainPanel.add(southPanel, BorderLayout.SOUTH); - - mainAccountsPanel.add(accountsPanel, BorderLayout.CENTER); - - initProvisioningPanel(); - - mainAccountsPanel.setOpaque(false); - accountsPanel.setOpaque(false); - buttonPanel.setOpaque(false); - - SigninActionListener actionListener = new SigninActionListener(); - - signinButton.addActionListener(actionListener); - cancelButton.addActionListener(actionListener); - - buttonPanel.add(signinButton); - buttonPanel.add(cancelButton); - - this.getRootPane().setDefaultButton(signinButton); - - this.initAccountWizards(); - - // Create the default group - String groupName - = Resources.getApplicationProperty("impl.gui.DEFAULT_GROUP_NAME"); - - if(groupName != null && groupName.length() > 0) - { - MetaContactListService contactList = - SimpleAccountRegistrationActivator.getContactList(); - Iterator iter - = contactList.getRoot().getSubgroups(); - while (iter.hasNext()) - { - MetaContactGroup gr = iter.next(); - if (groupName.equals(gr.getGroupName())) - return; - } - - contactList - .createMetaContactGroup(contactList.getRoot(), groupName); - - getConfigurationService() - .setProperty( - "net.java.sip.communicator.impl.gui.addcontact.lastContactParent", - groupName); - } - - this.getRootPane().validate(); - this.pack(); - - // if the screen height is sufficiently large, expand the window size - // so that no scrolling is needed - if (scroller.getViewport().getHeight() - < Toolkit.getDefaultToolkit().getScreenSize().getHeight() - 230) - { - this.setSize(scroller.getViewport().getWidth() + 100, - scroller.getViewport().getHeight() + 150); - } - else - { - // otherwise add some width so that no horizontal scrolling is - // needed - this.setSize(this.getSize().width + 20, - this.getSize().height - 10); - } - } - - /** - * Initializes the provisioning panel. - */ - private void initProvisioningPanel() - { - String isInitialProv = SimpleAccountRegistrationActivator.getResources() - .getSettingsString( - "plugin.provisioning.IS_INITIAL_PROVISIONING_LINK"); - - if (isInitialProv != null && isInitialProv.length() > 0 - && !Boolean.parseBoolean(isInitialProv)) - return; - - String useProvisioningString = SimpleAccountRegistrationActivator - .getResources().getI18NString("service.gui.USE_PROVISIONING"); - - final JLabel provisioningLabel = - new JLabel("" - + useProvisioningString - + ""); - - provisioningLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - provisioningLabel.setToolTipText(useProvisioningString); - - provisioningLabel.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent e) - { - ConfigurationContainer configContainer - = SimpleAccountRegistrationActivator.getUIService() - .getConfigurationContainer(); - - ConfigurationForm advancedConfigForm - = SimpleAccountRegistrationActivator.getAdvancedConfigForm(); - - if (advancedConfigForm != null) - { - configContainer.setSelected(advancedConfigForm); - - if (advancedConfigForm instanceof ConfigurationContainer) - { - ConfigurationForm provisioningForm - = SimpleAccountRegistrationActivator - .getProvisioningConfigForm(); - - if (provisioningForm != null) - { - ((ConfigurationContainer) advancedConfigForm) - .setSelected(provisioningForm); - } - } - } - - configContainer.setVisible(true); - } - }); - - southPanel.add(provisioningLabel, BorderLayout.WEST); - } - - private void initAccountWizards() - { - String simpleWizards - = SimpleAccountRegistrationActivator.getConfigService() - .getString("plugin.simpleaccreg.PROTOCOL_ORDER"); - - StringTokenizer tokenizer = new StringTokenizer(simpleWizards, "|"); - - ServiceReference[] serviceRefs = null; - while (tokenizer.hasMoreTokens()) - { - String protocolToken = tokenizer.nextToken(); - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "="+protocolToken+")"; - - try - { - serviceRefs = SimpleAccountRegistrationActivator.bundleContext - .getServiceReferences( - AccountRegistrationWizard.class.getName(), osgiFilter); - - if (serviceRefs != null && serviceRefs.length > 0) - { - AccountRegistrationWizard wizard - = (AccountRegistrationWizard) - - SimpleAccountRegistrationActivator - .bundleContext.getService(serviceRefs[0]); - - this.addAccountRegistrationForm(wizard); - } - } - catch (InvalidSyntaxException ex) - { - logger.error("GuiActivator : ", ex); - } - } - } - - /** - * The account registration panel. - */ - private class AccountRegistrationPanel - extends JPanel - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private JLabel usernameLabel - = new JLabel(Resources.getString( - "plugin.simpleaccregwizz.LOGIN_USERNAME")); - - private JLabel passwordLabel - = new JLabel(Resources.getString("service.gui.PASSWORD")); - - private JTextField usernameField = new JTextField(); - - private JLabel usernameExampleLabel = new JLabel(); - - private JPasswordField passwordField = new JPasswordField(); - - private JPanel labelsPanel = new JPanel(new GridLayout(0, 1, 5, 0)); - - private JPanel fieldsPanel = new JPanel(new GridLayout(0, 1, 5, 0)); - - private JPanel emptyPanel = new JPanel(); - - private JPanel inputPanel = new JPanel(new BorderLayout(5, 5)); - - private JPanel iconDescriptionPanel = new JPanel(new BorderLayout()); - - private JTextArea descriptionArea = new JTextArea(); - - private final AccountRegistrationWizard wizard; - - public AccountRegistrationPanel( - AccountRegistrationWizard accountWizard, - boolean isPreferredWizard) - { - super(new BorderLayout(5, 5)); - - this.wizard = accountWizard; - - // Obtain the simple form in order to initialize all predefined - // values. - // TODO: Use the simple form instead of creating new fields and - // panels here. - wizard.getSimpleForm(false); - - JLabel protocolLabel = new JLabel(); - JPanel inputRegisterPanel = new JPanel(new BorderLayout()); - - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.setOpaque(false); - - this.inputPanel.setOpaque(false); - this.labelsPanel.setOpaque(false); - this.fieldsPanel.setOpaque(false); - this.emptyPanel.setOpaque(false); - inputRegisterPanel.setOpaque(false); - this.iconDescriptionPanel.setOpaque(false); - - this.add(inputRegisterPanel, BorderLayout.CENTER); - - inputRegisterPanel.add(inputPanel, BorderLayout.NORTH); - - if (((wizard instanceof ExtendedAccountRegistrationWizard) - && ((ExtendedAccountRegistrationWizard) wizard) - .isSignupSupported()) || wizard.isWebSignupSupported()) - { - String textKey = - isPreferredWizard ? "plugin.simpleaccregwizz.SPECIAL_SIGNUP" - : "plugin.simpleaccregwizz.SIGNUP"; - JLabel signupLabel = - new JLabel("" - + Resources.getString(textKey) + "", - JLabel.RIGHT); - - signupLabel.setFont(signupLabel.getFont().deriveFont(10f)); - signupLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - signupLabel.setToolTipText( - Resources.getString( - "plugin.simpleaccregwizz.SPECIAL_SIGNUP")); - signupLabel.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent e) - { - try - { - if ((wizard - instanceof ExtendedAccountRegistrationWizard) - && ((ExtendedAccountRegistrationWizard) wizard) - .isSignupSupported()) - { - showCreateAccountWindow(wizard); - dispose(); - } - else if (wizard.isWebSignupSupported()) - { - wizard.webSignup(); - } - } - catch (UnsupportedOperationException ex) - { - // This should not happen, because we check if the - // operation is supported, before adding the sign - // up. - logger.error("The web sign up is not supported.", - ex); - } - } - }); - - inputRegisterPanel.add(signupLabel, BorderLayout.SOUTH); - } - - this.inputPanel.add(labelsPanel, BorderLayout.WEST); - - this.inputPanel.add(fieldsPanel, BorderLayout.CENTER); - - this.iconDescriptionPanel.add( - protocolLabel, BorderLayout.NORTH); - - protocolLabel.setFont( - protocolLabel.getFont().deriveFont(Font.BOLD, 14f)); - this.usernameExampleLabel.setForeground(Color.DARK_GRAY); - this.usernameExampleLabel.setFont( - usernameExampleLabel.getFont().deriveFont(8f)); - this.emptyPanel.setMaximumSize(new Dimension(40, 25)); - - this.labelsPanel.add(usernameLabel); - this.labelsPanel.add(emptyPanel); - this.labelsPanel.add(passwordLabel); - - this.fieldsPanel.add(usernameField); - this.fieldsPanel.add(usernameExampleLabel); - this.fieldsPanel.add(passwordField); - - this.usernameExampleLabel.setText(wizard.getUserNameExample()); - - protocolLabel.setText(wizard.getProtocolName()); - - Image image = null; - try - { - image = ImageIO.read( - new ByteArrayInputStream(wizard.getPageImage())); - } - catch (IOException e) - { - logger.error("Unable to load image.", e); - } - - if (image != null) - { - image = image.getScaledInstance(28, 28, Image.SCALE_SMOOTH); - - protocolLabel.setIcon(new ImageIcon(image)); - } - - if (isPreferredWizard) - { - descriptionArea.setBorder(BorderFactory - .createEmptyBorder(10, 0, 0, 0)); - - descriptionArea.setFont( - descriptionArea.getFont().deriveFont(10f)); - descriptionArea.setPreferredSize(new Dimension(220, 50)); - descriptionArea.setLineWrap(true); - descriptionArea.setWrapStyleWord(true); - descriptionArea.setText(wizard.getProtocolDescription()); - descriptionArea.setEditable(false); - descriptionArea.setOpaque(false); - - this.iconDescriptionPanel.add( - descriptionArea, BorderLayout.CENTER); - - this.add(iconDescriptionPanel, BorderLayout.WEST); - } - else - { - this.add(iconDescriptionPanel, BorderLayout.NORTH); - } - } - - @Override - public void paintComponent(Graphics g) - { - // do the superclass behavior first - super.paintComponent(g); - - g = g.create(); - try - { - AntialiasingManager.activateAntialiasing(g); - - Graphics2D g2d = (Graphics2D) g; - - // paint the background with the chosen color - g2d.setColor(Color.GRAY); - g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15); - } - finally - { - g.dispose(); - } - } - - public boolean isFilled() - { - String username = usernameField.getText(); - return (username != null) && (username.length() > 0); - } - - public void signin() throws OperationFailedException - { - ProtocolProviderService protocolProvider = - wizard.signin(usernameField.getText(), new String(passwordField - .getPassword())); - - saveAccountWizard(protocolProvider, wizard); - } - } - - /** - * Adds a simple account registration form corresponding to the given - * AccountRegistrationWizard. - * - * @param wizard the AccountRegistrationWizard, which gives us - * information to fill our simple form. - */ - private void addAccountRegistrationForm(AccountRegistrationWizard wizard) - { - // We don't need to add wizards that are not interested in a - // simple sign in form. - if (!wizard.isSimpleFormEnabled()) - return; - - String preferredWizardName - = Resources.getLoginProperty("impl.gui.PREFERRED_ACCOUNT_WIZARD"); - - AccountRegistrationPanel accountPanel; - - if (preferredWizardName != null - && preferredWizardName.equals(wizard.getClass().getName())) - { - accountPanel = new AccountRegistrationPanel(wizard, true); - - mainAccountsPanel.add( - accountPanel, - BorderLayout.NORTH); - - mainAccountsPanel.validate(); - } - else - { - accountPanel = new AccountRegistrationPanel(wizard, false); - - accountsPanel.add(accountPanel); - - accountsPanel.validate(); - } - - this.registrationForms.add(accountPanel); - } - - /** - * Handles the event triggered by the "service.gui.SIGN_IN" button. - */ - private class SigninActionListener implements ActionListener - { - public void actionPerformed(ActionEvent evt) - { - JButton button = (JButton) evt.getSource(); - - if (button.equals(signinButton)) - { - Iterator regIterator = - registrationForms.iterator(); - - if (regIterator.hasNext()) - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - while(regIterator.hasNext()) - { - AccountRegistrationPanel regForm = regIterator.next(); - - try - { - if (regForm.isFilled()) - regForm.signin(); - } - catch (OperationFailedException e) - { - if (logger.isDebugEnabled()) - logger.debug("The sign in operation has failed."); - - PopupDialog popupDialog - = SimpleAccountRegistrationActivator.getUIService() - .getPopupDialog(); - - if (e.getErrorCode() - == OperationFailedException.ILLEGAL_ARGUMENT) - { - popupDialog.showMessagePopupDialog( - Resources.getString( - "service.gui.USERNAME_NULL"), - Resources.getString( - "service.gui.ERROR"), - PopupDialog.ERROR_MESSAGE); - } - else if (e.getErrorCode() - == OperationFailedException - .IDENTIFICATION_CONFLICT) - { - popupDialog.showMessagePopupDialog( - Resources.getString( - "service.gui.USER_EXISTS_ERROR"), - Resources.getString( - "service.gui.ERROR"), - PopupDialog.ERROR_MESSAGE); - } - else if (e.getErrorCode() - == OperationFailedException - .SERVER_NOT_SPECIFIED) - { - popupDialog.showMessagePopupDialog( - Resources.getString( - "service.gui.SPECIFY_SERVER"), - Resources.getString( - "service.gui.ERROR"), - PopupDialog.ERROR_MESSAGE); - } - } - } - } - - InitialAccountRegistrationFrame initialAccountRegistrationFrame = - InitialAccountRegistrationFrame.this; - initialAccountRegistrationFrame.setVisible(false); - initialAccountRegistrationFrame.dispose(); - } - } - - /** - * Saves the (protocol provider, wizard) pair in through the - * ConfigurationService. - * - * @param protocolProvider the protocol provider to save - * @param wizard the wizard to save - */ - private void saveAccountWizard(ProtocolProviderService protocolProvider, - AccountRegistrationWizard wizard) - { - String prefix = "net.java.sip.communicator.impl.gui.accounts"; - - ConfigurationService configService = getConfigurationService(); - - List accounts = configService.getPropertyNamesByPrefix(prefix, true); - boolean savedAccount = false; - - for (String accountRootPropName : accounts) - { - String accountUID = configService.getString(accountRootPropName); - - if (accountUID.equals(protocolProvider.getAccountID() - .getAccountUniqueID())) - { - - configService.setProperty(accountRootPropName + ".wizard", - wizard.getClass().getName().replace('.', '_')); - - savedAccount = true; - } - } - - if (!savedAccount) - { - String accNodeName = - "acc" + Long.toString(System.currentTimeMillis()); - - String accountPackage = - "net.java.sip.communicator.impl.gui.accounts." + accNodeName; - - configService.setProperty(accountPackage, protocolProvider - .getAccountID().getAccountUniqueID()); - - configService.setProperty(accountPackage + ".wizard", wizard); - } - } - - /** - * Returns the ConfigurationService. - * - * @return the ConfigurationService - */ - public ConfigurationService getConfigurationService() - { - if (configurationService == null) - { - BundleContext bundleContext = - SimpleAccountRegistrationActivator.bundleContext; - ServiceReference configReference = - bundleContext.getServiceReference(ConfigurationService.class - .getName()); - - configurationService = - (ConfigurationService) bundleContext - .getService(configReference); - } - return configurationService; - } - - /** - * Creates the title component. - * @return the newly created title component - */ - private JComponent createTitleComponent() - { - JTextPane titlePane = new JTextPane(); - SimpleAttributeSet aSet = new SimpleAttributeSet(); - StyleConstants.setAlignment(aSet, StyleConstants.ALIGN_CENTER); - StyleConstants.setBold(aSet, true); - StyleConstants.setFontFamily(aSet, titlePane.getFont().getFamily()); - - titlePane.setParagraphAttributes(aSet, true); - titlePane.setEditable(false); - titlePane.setText(Resources.getString( - "plugin.simpleaccregwizz.INITIAL_ACCOUNT_REGISTRATION")); - titlePane.setOpaque(false); - - return titlePane; - } - - /** - * Show the create account window for the given wizard. - * - * @param wizard the AccountRegistrationWizard, for which we're - * opening the window - */ - private void showCreateAccountWindow(AccountRegistrationWizard wizard) - { - CreateAccountWindow createAccountWindow - = SimpleAccountRegistrationActivator - .getUIService().getCreateAccountWindow(); - - createAccountWindow.setSelectedWizard(wizard, true); - - if (wizard instanceof ExtendedAccountRegistrationWizard) - { - ((ExtendedAccountRegistrationWizard) wizard).setCreateAccountView(); - } - - createAccountWindow.setVisible(true); - } - - @Override - protected void close(boolean isEscaped) - { - } -} +package net.java.sip.communicator.plugin.simpleaccreg; + +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.util.*; +import java.util.List; + +import javax.imageio.*; +import javax.swing.*; +import javax.swing.text.*; + +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * The NoAccountFoundPage is the page shown in the account + * registration wizard shown in the beginning of the program, when no registered + * accounts are found. + * + * @author Yana Stamcheva + * @author Lubomir Marinov + */ +public class InitialAccountRegistrationFrame + extends SIPCommFrame +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private ConfigurationService configurationService; + + /** + * The Logger used by this InitialAccountRegistrationFrame + * for logging output. + */ + private final Logger logger + = Logger.getLogger(InitialAccountRegistrationFrame.class); + + private final TransparentPanel mainAccountsPanel + = new TransparentPanel(new BorderLayout(10, 10)); + + private final TransparentPanel accountsPanel + = new TransparentPanel(new GridLayout(0, 2, 10, 10)); + + private final TransparentPanel southPanel + = new TransparentPanel(new BorderLayout()); + + private final JButton signinButton + = new JButton(Resources.getString("service.gui.SIGN_IN")); + + private final Collection registrationForms = + new Vector(); + + /** + * Creates an instance of NoAccountFoundPage. + */ + public InitialAccountRegistrationFrame() + { + super(false); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + + TransparentPanel mainPanel + = new TransparentPanel(new BorderLayout()); + mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + southPanel.add(buttonPanel, BorderLayout.EAST); + JButton cancelButton + = new JButton(Resources.getString("service.gui.CANCEL")); + + this.setTitle(Resources.getString("service.gui.SIGN_IN")); + + this.setIconImage( + Resources.getImage("service.gui.SIP_COMMUNICATOR_LOGO").getImage()); + + // In order to have the same icon when using option panes + JOptionPane.getRootFrame().setIconImage( + Resources.getImage("service.gui.SIP_COMMUNICATOR_LOGO").getImage()); + + mainAccountsPanel.setBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + this.getContentPane().add(mainPanel); + + mainPanel.add(createTitleComponent(), BorderLayout.NORTH); + JScrollPane scroller = new JScrollPane(mainAccountsPanel); + scroller.setOpaque(false); + scroller.getViewport().setOpaque(false); + mainPanel.add(scroller, BorderLayout.CENTER); + mainPanel.add(southPanel, BorderLayout.SOUTH); + + mainAccountsPanel.add(accountsPanel, BorderLayout.CENTER); + + initProvisioningPanel(); + + mainAccountsPanel.setOpaque(false); + accountsPanel.setOpaque(false); + buttonPanel.setOpaque(false); + + SigninActionListener actionListener = new SigninActionListener(); + + signinButton.addActionListener(actionListener); + cancelButton.addActionListener(actionListener); + + buttonPanel.add(signinButton); + buttonPanel.add(cancelButton); + + this.getRootPane().setDefaultButton(signinButton); + + this.initAccountWizards(); + + // Create the default group + String groupName + = Resources.getApplicationProperty("impl.gui.DEFAULT_GROUP_NAME"); + + if(groupName != null && groupName.length() > 0) + { + MetaContactListService contactList = + SimpleAccountRegistrationActivator.getContactList(); + Iterator iter + = contactList.getRoot().getSubgroups(); + while (iter.hasNext()) + { + MetaContactGroup gr = iter.next(); + if (groupName.equals(gr.getGroupName())) + return; + } + + contactList + .createMetaContactGroup(contactList.getRoot(), groupName); + + getConfigurationService() + .setProperty( + "net.java.sip.communicator.impl.gui.addcontact.lastContactParent", + groupName); + } + + this.getRootPane().validate(); + this.pack(); + + // if the screen height is sufficiently large, expand the window size + // so that no scrolling is needed + if (scroller.getViewport().getHeight() + < Toolkit.getDefaultToolkit().getScreenSize().getHeight() - 230) + { + this.setSize(scroller.getViewport().getWidth() + 100, + scroller.getViewport().getHeight() + 150); + } + else + { + // otherwise add some width so that no horizontal scrolling is + // needed + this.setSize(this.getSize().width + 20, + this.getSize().height - 10); + } + } + + /** + * Initializes the provisioning panel. + */ + private void initProvisioningPanel() + { + String isInitialProv = SimpleAccountRegistrationActivator.getResources() + .getSettingsString( + "plugin.provisioning.IS_INITIAL_PROVISIONING_LINK"); + + if (isInitialProv != null && isInitialProv.length() > 0 + && !Boolean.parseBoolean(isInitialProv)) + return; + + String useProvisioningString = SimpleAccountRegistrationActivator + .getResources().getI18NString("service.gui.USE_PROVISIONING"); + + final JLabel provisioningLabel = + new JLabel("" + + useProvisioningString + + ""); + + provisioningLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + provisioningLabel.setToolTipText(useProvisioningString); + + provisioningLabel.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent e) + { + ConfigurationContainer configContainer + = SimpleAccountRegistrationActivator.getUIService() + .getConfigurationContainer(); + + ConfigurationForm advancedConfigForm + = SimpleAccountRegistrationActivator.getAdvancedConfigForm(); + + if (advancedConfigForm != null) + { + configContainer.setSelected(advancedConfigForm); + + if (advancedConfigForm instanceof ConfigurationContainer) + { + ConfigurationForm provisioningForm + = SimpleAccountRegistrationActivator + .getProvisioningConfigForm(); + + if (provisioningForm != null) + { + ((ConfigurationContainer) advancedConfigForm) + .setSelected(provisioningForm); + } + } + } + + configContainer.setVisible(true); + } + }); + + southPanel.add(provisioningLabel, BorderLayout.WEST); + } + + private void initAccountWizards() + { + String simpleWizards + = SimpleAccountRegistrationActivator.getConfigService() + .getString("plugin.simpleaccreg.PROTOCOL_ORDER"); + + StringTokenizer tokenizer = new StringTokenizer(simpleWizards, "|"); + + ServiceReference[] serviceRefs = null; + while (tokenizer.hasMoreTokens()) + { + String protocolToken = tokenizer.nextToken(); + + String osgiFilter = "(" + + ProtocolProviderFactory.PROTOCOL + + "="+protocolToken+")"; + + try + { + serviceRefs = SimpleAccountRegistrationActivator.bundleContext + .getServiceReferences( + AccountRegistrationWizard.class.getName(), osgiFilter); + + if (serviceRefs != null && serviceRefs.length > 0) + { + AccountRegistrationWizard wizard + = (AccountRegistrationWizard) + + SimpleAccountRegistrationActivator + .bundleContext.getService(serviceRefs[0]); + + this.addAccountRegistrationForm(wizard); + } + } + catch (InvalidSyntaxException ex) + { + logger.error("GuiActivator : ", ex); + } + } + } + + /** + * The account registration panel. + */ + private class AccountRegistrationPanel + extends JPanel + { + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private JLabel usernameLabel + = new JLabel(Resources.getString( + "plugin.simpleaccregwizz.LOGIN_USERNAME")); + + private JLabel passwordLabel + = new JLabel(Resources.getString("service.gui.PASSWORD")); + + private JTextField usernameField = new JTextField(); + + private JLabel usernameExampleLabel = new JLabel(); + + private JPasswordField passwordField = new JPasswordField(); + + private JPanel labelsPanel = new JPanel(new GridLayout(0, 1, 5, 0)); + + private JPanel fieldsPanel = new JPanel(new GridLayout(0, 1, 5, 0)); + + private JPanel emptyPanel = new JPanel(); + + private JPanel inputPanel = new JPanel(new BorderLayout(5, 5)); + + private JPanel iconDescriptionPanel = new JPanel(new BorderLayout()); + + private JTextArea descriptionArea = new JTextArea(); + + private final AccountRegistrationWizard wizard; + + public AccountRegistrationPanel( + AccountRegistrationWizard accountWizard, + boolean isPreferredWizard) + { + super(new BorderLayout(5, 5)); + + this.wizard = accountWizard; + + // Obtain the simple form in order to initialize all predefined + // values. + // TODO: Use the simple form instead of creating new fields and + // panels here. + wizard.getSimpleForm(false); + + JLabel protocolLabel = new JLabel(); + JPanel inputRegisterPanel = new JPanel(new BorderLayout()); + + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + this.setOpaque(false); + + this.inputPanel.setOpaque(false); + this.labelsPanel.setOpaque(false); + this.fieldsPanel.setOpaque(false); + this.emptyPanel.setOpaque(false); + inputRegisterPanel.setOpaque(false); + this.iconDescriptionPanel.setOpaque(false); + + this.add(inputRegisterPanel, BorderLayout.CENTER); + + inputRegisterPanel.add(inputPanel, BorderLayout.NORTH); + + if (((wizard instanceof ExtendedAccountRegistrationWizard) + && ((ExtendedAccountRegistrationWizard) wizard) + .isSignupSupported()) || wizard.isWebSignupSupported()) + { + String textKey = + isPreferredWizard ? "plugin.simpleaccregwizz.SPECIAL_SIGNUP" + : "plugin.simpleaccregwizz.SIGNUP"; + JLabel signupLabel = + new JLabel("" + + Resources.getString(textKey) + "", + JLabel.RIGHT); + + signupLabel.setFont(signupLabel.getFont().deriveFont(10f)); + signupLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); + signupLabel.setToolTipText( + Resources.getString( + "plugin.simpleaccregwizz.SPECIAL_SIGNUP")); + signupLabel.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent e) + { + try + { + if ((wizard + instanceof ExtendedAccountRegistrationWizard) + && ((ExtendedAccountRegistrationWizard) wizard) + .isSignupSupported()) + { + showCreateAccountWindow(wizard); + dispose(); + } + else if (wizard.isWebSignupSupported()) + { + wizard.webSignup(); + } + } + catch (UnsupportedOperationException ex) + { + // This should not happen, because we check if the + // operation is supported, before adding the sign + // up. + logger.error("The web sign up is not supported.", + ex); + } + } + }); + + inputRegisterPanel.add(signupLabel, BorderLayout.SOUTH); + } + + this.inputPanel.add(labelsPanel, BorderLayout.WEST); + + this.inputPanel.add(fieldsPanel, BorderLayout.CENTER); + + this.iconDescriptionPanel.add( + protocolLabel, BorderLayout.NORTH); + + protocolLabel.setFont( + protocolLabel.getFont().deriveFont(Font.BOLD, 14f)); + this.usernameExampleLabel.setForeground(Color.DARK_GRAY); + this.usernameExampleLabel.setFont( + usernameExampleLabel.getFont().deriveFont(8f)); + this.emptyPanel.setMaximumSize(new Dimension(40, 25)); + + this.labelsPanel.add(usernameLabel); + this.labelsPanel.add(emptyPanel); + this.labelsPanel.add(passwordLabel); + + this.fieldsPanel.add(usernameField); + this.fieldsPanel.add(usernameExampleLabel); + this.fieldsPanel.add(passwordField); + + this.usernameExampleLabel.setText(wizard.getUserNameExample()); + + protocolLabel.setText(wizard.getProtocolName()); + + Image image = null; + try + { + image = ImageIO.read( + new ByteArrayInputStream(wizard.getPageImage())); + } + catch (IOException e) + { + logger.error("Unable to load image.", e); + } + + if (image != null) + { + image = image.getScaledInstance(28, 28, Image.SCALE_SMOOTH); + + protocolLabel.setIcon(new ImageIcon(image)); + } + + if (isPreferredWizard) + { + descriptionArea.setBorder(BorderFactory + .createEmptyBorder(10, 0, 0, 0)); + + descriptionArea.setFont( + descriptionArea.getFont().deriveFont(10f)); + descriptionArea.setPreferredSize(new Dimension(220, 50)); + descriptionArea.setLineWrap(true); + descriptionArea.setWrapStyleWord(true); + descriptionArea.setText(wizard.getProtocolDescription()); + descriptionArea.setEditable(false); + descriptionArea.setOpaque(false); + + this.iconDescriptionPanel.add( + descriptionArea, BorderLayout.CENTER); + + this.add(iconDescriptionPanel, BorderLayout.WEST); + } + else + { + this.add(iconDescriptionPanel, BorderLayout.NORTH); + } + } + + @Override + public void paintComponent(Graphics g) + { + // do the superclass behavior first + super.paintComponent(g); + + g = g.create(); + try + { + AntialiasingManager.activateAntialiasing(g); + + Graphics2D g2d = (Graphics2D) g; + + // paint the background with the chosen color + g2d.setColor(Color.GRAY); + g2d.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15); + } + finally + { + g.dispose(); + } + } + + public boolean isFilled() + { + String username = usernameField.getText(); + return (username != null) && (username.length() > 0); + } + + public void signin() throws OperationFailedException + { + ProtocolProviderService protocolProvider = + wizard.signin(usernameField.getText(), new String(passwordField + .getPassword())); + + saveAccountWizard(protocolProvider, wizard); + } + } + + /** + * Adds a simple account registration form corresponding to the given + * AccountRegistrationWizard. + * + * @param wizard the AccountRegistrationWizard, which gives us + * information to fill our simple form. + */ + private void addAccountRegistrationForm(AccountRegistrationWizard wizard) + { + // We don't need to add wizards that are not interested in a + // simple sign in form. + if (!wizard.isSimpleFormEnabled()) + return; + + String preferredWizardName + = Resources.getLoginProperty("impl.gui.PREFERRED_ACCOUNT_WIZARD"); + + AccountRegistrationPanel accountPanel; + + if (preferredWizardName != null + && preferredWizardName.equals(wizard.getClass().getName())) + { + accountPanel = new AccountRegistrationPanel(wizard, true); + + mainAccountsPanel.add( + accountPanel, + BorderLayout.NORTH); + + mainAccountsPanel.validate(); + } + else + { + accountPanel = new AccountRegistrationPanel(wizard, false); + + accountsPanel.add(accountPanel); + + accountsPanel.validate(); + } + + this.registrationForms.add(accountPanel); + } + + /** + * Handles the event triggered by the "service.gui.SIGN_IN" button. + */ + private class SigninActionListener implements ActionListener + { + public void actionPerformed(ActionEvent evt) + { + JButton button = (JButton) evt.getSource(); + + if (button.equals(signinButton)) + { + Iterator regIterator = + registrationForms.iterator(); + + if (regIterator.hasNext()) + setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + + while(regIterator.hasNext()) + { + AccountRegistrationPanel regForm = regIterator.next(); + + try + { + if (regForm.isFilled()) + regForm.signin(); + } + catch (OperationFailedException e) + { + if (logger.isDebugEnabled()) + logger.debug("The sign in operation has failed."); + + PopupDialog popupDialog + = SimpleAccountRegistrationActivator.getUIService() + .getPopupDialog(); + + if (e.getErrorCode() + == OperationFailedException.ILLEGAL_ARGUMENT) + { + popupDialog.showMessagePopupDialog( + Resources.getString( + "service.gui.USERNAME_NULL"), + Resources.getString( + "service.gui.ERROR"), + PopupDialog.ERROR_MESSAGE); + } + else if (e.getErrorCode() + == OperationFailedException + .IDENTIFICATION_CONFLICT) + { + popupDialog.showMessagePopupDialog( + Resources.getString( + "service.gui.USER_EXISTS_ERROR"), + Resources.getString( + "service.gui.ERROR"), + PopupDialog.ERROR_MESSAGE); + } + else if (e.getErrorCode() + == OperationFailedException + .SERVER_NOT_SPECIFIED) + { + popupDialog.showMessagePopupDialog( + Resources.getString( + "service.gui.SPECIFY_SERVER"), + Resources.getString( + "service.gui.ERROR"), + PopupDialog.ERROR_MESSAGE); + } + } + } + } + + InitialAccountRegistrationFrame initialAccountRegistrationFrame = + InitialAccountRegistrationFrame.this; + initialAccountRegistrationFrame.setVisible(false); + initialAccountRegistrationFrame.dispose(); + } + } + + /** + * Saves the (protocol provider, wizard) pair in through the + * ConfigurationService. + * + * @param protocolProvider the protocol provider to save + * @param wizard the wizard to save + */ + private void saveAccountWizard(ProtocolProviderService protocolProvider, + AccountRegistrationWizard wizard) + { + String prefix = "net.java.sip.communicator.impl.gui.accounts"; + + ConfigurationService configService = getConfigurationService(); + + List accounts = configService.getPropertyNamesByPrefix(prefix, true); + boolean savedAccount = false; + + for (String accountRootPropName : accounts) + { + String accountUID = configService.getString(accountRootPropName); + + if (accountUID.equals(protocolProvider.getAccountID() + .getAccountUniqueID())) + { + + configService.setProperty(accountRootPropName + ".wizard", + wizard.getClass().getName().replace('.', '_')); + + savedAccount = true; + } + } + + if (!savedAccount) + { + String accNodeName = + "acc" + Long.toString(System.currentTimeMillis()); + + String accountPackage = + "net.java.sip.communicator.impl.gui.accounts." + accNodeName; + + configService.setProperty(accountPackage, protocolProvider + .getAccountID().getAccountUniqueID()); + + configService.setProperty(accountPackage + ".wizard", wizard); + } + } + + /** + * Returns the ConfigurationService. + * + * @return the ConfigurationService + */ + public ConfigurationService getConfigurationService() + { + if (configurationService == null) + { + BundleContext bundleContext = + SimpleAccountRegistrationActivator.bundleContext; + ServiceReference configReference = + bundleContext.getServiceReference(ConfigurationService.class + .getName()); + + configurationService = + (ConfigurationService) bundleContext + .getService(configReference); + } + return configurationService; + } + + /** + * Creates the title component. + * @return the newly created title component + */ + private JComponent createTitleComponent() + { + JTextPane titlePane = new JTextPane(); + SimpleAttributeSet aSet = new SimpleAttributeSet(); + StyleConstants.setAlignment(aSet, StyleConstants.ALIGN_CENTER); + StyleConstants.setBold(aSet, true); + StyleConstants.setFontFamily(aSet, titlePane.getFont().getFamily()); + + titlePane.setParagraphAttributes(aSet, true); + titlePane.setEditable(false); + titlePane.setText(Resources.getString( + "plugin.simpleaccregwizz.INITIAL_ACCOUNT_REGISTRATION")); + titlePane.setOpaque(false); + + return titlePane; + } + + /** + * Show the create account window for the given wizard. + * + * @param wizard the AccountRegistrationWizard, for which we're + * opening the window + */ + private void showCreateAccountWindow(AccountRegistrationWizard wizard) + { + CreateAccountWindow createAccountWindow + = SimpleAccountRegistrationActivator + .getUIService().getCreateAccountWindow(); + + createAccountWindow.setSelectedWizard(wizard, true); + + if (wizard instanceof ExtendedAccountRegistrationWizard) + { + ((ExtendedAccountRegistrationWizard) wizard).setCreateAccountView(); + } + + createAccountWindow.setVisible(true); + } + + @Override + protected void close(boolean isEscaped) + { + } +} diff --git a/src/net/java/sip/communicator/plugin/simpleaccreg/Resources.java b/src/net/java/sip/communicator/plugin/simpleaccreg/Resources.java index 7249e66..f62093f 100644 --- a/src/net/java/sip/communicator/plugin/simpleaccreg/Resources.java +++ b/src/net/java/sip/communicator/plugin/simpleaccreg/Resources.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,92 +15,92 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.simpleaccreg; - -import javax.swing.*; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author Yana Stamcheva - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - /** - * Returns an internationalized string corresponding to the given key. - * - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Returns an int RGB color corresponding to the given key. - * - * @param key The key of the string. - * - * @return An internationalized string corresponding to the given key. - */ - public static int getColor(String key) - { - return getResources().getColor(key); - } - - /** - * Returns the application property corresponding to the given key. - * - * @param key The key of the string. - * - * @return the application property corresponding to the given key - */ - public static String getLoginProperty(String key) - { - return getResources().getSettingsString(key); - } - - /** - * Returns the application property corresponding to the given key. - * - * @param key The key of the string. - * - * @return the application property corresponding to the given key - */ - public static String getApplicationProperty(String key) - { - return getResources().getSettingsString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static ImageIcon getImage(String imageID) - { - return getResources().getImage(imageID); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(SimpleAccountRegistrationActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.simpleaccreg; + +import javax.swing.*; + +import net.java.sip.communicator.service.resources.*; + +import org.jitsi.service.resources.*; + +/** + * The Resources class manages the access to the internationalization + * properties files and the image resources used in this plugin. + * + * @author Yana Stamcheva + */ +public class Resources +{ + private static ResourceManagementService resourcesService; + + /** + * Returns an internationalized string corresponding to the given key. + * + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + return getResources().getI18NString(key); + } + + /** + * Returns an int RGB color corresponding to the given key. + * + * @param key The key of the string. + * + * @return An internationalized string corresponding to the given key. + */ + public static int getColor(String key) + { + return getResources().getColor(key); + } + + /** + * Returns the application property corresponding to the given key. + * + * @param key The key of the string. + * + * @return the application property corresponding to the given key + */ + public static String getLoginProperty(String key) + { + return getResources().getSettingsString(key); + } + + /** + * Returns the application property corresponding to the given key. + * + * @param key The key of the string. + * + * @return the application property corresponding to the given key + */ + public static String getApplicationProperty(String key) + { + return getResources().getSettingsString(key); + } + + /** + * Loads an image from a given image identifier. + * @param imageID The identifier of the image. + * @return The image for the given identifier. + */ + public static ImageIcon getImage(String imageID) + { + return getResources().getImage(imageID); + } + + /** + * Returns the ResourceManagementService. + * + * @return the ResourceManagementService. + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils + .getService(SimpleAccountRegistrationActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java index 6263508..bb13f2b 100644 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java +++ b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,122 +15,122 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.sip2sipaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. - * - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class Sip2SipAccRegWizzActivator - implements BundleActivator -{ - /** - * The bundle context. - */ - public static BundleContext bundleContext; - - /** - * The browser launcher service. - */ - private static BrowserLauncherService browserLauncherService; - - /** - * The resources service. - */ - private static ResourceManagementService resourcesService; - - /** - * The ui service. - */ - private static UIService uiService; - - /** - * Starts this bundle. - * @param bc BundleContext - * @throws Exception - */ - public void start(BundleContext bc) - throws Exception - { - bundleContext = bc; - - System.setProperty( - "http.agent", - System.getProperty("sip-communicator.application.name") - + "/" - + System.getProperty("sip-communicator.version")); - - uiService = - (UIService) bundleContext.getService(bundleContext - .getServiceReference(UIService.class.getName())); - - Sip2SipAccountRegistrationWizard wizard - = new Sip2SipAccountRegistrationWizard(uiService - .getAccountRegWizardContainer()); - - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - Sip2SipAccountRegistrationWizard.PROTOCOL); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - wizard, - containerFilter); - } - - public void stop(BundleContext bundleContext) throws Exception {} - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - browserLauncherService - = (BrowserLauncherService) bundleContext.getService( - bundleContext.getServiceReference( - BrowserLauncherService.class.getName())); - } - return browserLauncherService; - } - - /** - * Returns the service giving access to resources. - * @return the service giving access to resources - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = ResourceManagementServiceUtils - .getService(Sip2SipAccRegWizzActivator.bundleContext); - return resourcesService; - } -} +package net.java.sip.communicator.plugin.sip2sipaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. + * + * @author Lubomir Marinov + * @author Yana Stamcheva + */ +public class Sip2SipAccRegWizzActivator + implements BundleActivator +{ + /** + * The bundle context. + */ + public static BundleContext bundleContext; + + /** + * The browser launcher service. + */ + private static BrowserLauncherService browserLauncherService; + + /** + * The resources service. + */ + private static ResourceManagementService resourcesService; + + /** + * The ui service. + */ + private static UIService uiService; + + /** + * Starts this bundle. + * @param bc BundleContext + * @throws Exception + */ + public void start(BundleContext bc) + throws Exception + { + bundleContext = bc; + + System.setProperty( + "http.agent", + System.getProperty("sip-communicator.application.name") + + "/" + + System.getProperty("sip-communicator.version")); + + uiService = + (UIService) bundleContext.getService(bundleContext + .getServiceReference(UIService.class.getName())); + + Sip2SipAccountRegistrationWizard wizard + = new Sip2SipAccountRegistrationWizard(uiService + .getAccountRegWizardContainer()); + + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + ProtocolProviderFactory.PROTOCOL, + Sip2SipAccountRegistrationWizard.PROTOCOL); + + bundleContext.registerService( + AccountRegistrationWizard.class.getName(), + wizard, + containerFilter); + } + + public void stop(BundleContext bundleContext) throws Exception {} + + /** + * Returns the UIService. + * + * @return the UIService + */ + public static UIService getUIService() + { + return uiService; + } + + /** + * Returns the BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService obtained from the bundle + * context + */ + public static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncherService == null) + { + browserLauncherService + = (BrowserLauncherService) bundleContext.getService( + bundleContext.getServiceReference( + BrowserLauncherService.class.getName())); + } + return browserLauncherService; + } + + /** + * Returns the service giving access to resources. + * @return the service giving access to resources + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = ResourceManagementServiceUtils + .getService(Sip2SipAccRegWizzActivator.bundleContext); + return resourcesService; + } +} diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java index d6b09d8..55e6f36 100644 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,255 +15,255 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.sip2sipaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.sipaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.sip.*; - -/** - * The Sip2SipAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the SIP protocol. It should allow - * the user to create and configure a new IP Tel SIP account. - * - * @author Yana Stamcheva - */ -public class Sip2SipAccountRegistrationWizard - extends SIPAccountRegistrationWizard -{ - /** - * A constant pointing to the IP Tel protocol logo image. - */ - private static final String PROTOCOL_ICON - = "service.protocol.sip2sip.SIP2SIP_16x16"; - - /** - * A constant pointing to the IP Tel protocol wizard page image. - */ - private static final String PAGE_IMAGE - = "service.protocol.sip2sip.SIP2SIP_64x64"; - - /** - * The protocol name. - */ - public static final String PROTOCOL = "sip2sip.info"; - - /** - * The create account form. - */ - CreateSip2SipAccountForm createAccountForm = new CreateSip2SipAccountForm(); - - /** - * Creates an instance of IptelAccountRegistrationWizard. - * @param wizardContainer the wizard container - */ - public Sip2SipAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all predefined properties specific for this account wizard. - * - * @param reg the registration object - */ - private void setPredefinedProperties(SIPAccountRegistration reg) - { - // set properties common for sip2sip - reg.setKeepAliveMethod("NONE"); - reg.setDefaultDomain("sip2sip.info"); - reg.setXCapEnable(true); - reg.setClistOptionServerUri( - "https://xcap.sipthor.net/xcap-root@sip2sip.info"); - reg.setClistOptionUseSipCredentials(true); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return Sip2SipAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Sip2SipAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString( - "plugin.sip2sipaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources.getString( - "plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: myusername or myusername@sip2sip.info"; - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/sip2sip"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/sip2sip/sip32x32.png"; - } - - /** - * Opens the browser on the page sign up - */ - @Override - public void webSignup() - { - Sip2SipAccRegWizzActivator.getBrowserLauncher() - .openURL("http://wiki.sip2sip.info"); - } - - /** - * Returns the name of the web sign up link. - * @return the name of the web sign up link - */ - @Override - public String getWebSignupLinkName() - { - return Resources.getString("plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE"); - } - - /** - * Returns an instance of CreateAccountService through which the - * user could create an account. This method is meant to be implemented by - * specific protocol provider wizards. - * @return an instance of CreateAccountService - */ - @Override - protected SIPAccountCreationFormService getCreateAccountService() - { - return createAccountForm; - } - - /** - * Returns the display label used for the sip id field. - * @return the sip id display label string. - */ - @Override - protected String getUsernameLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.USERNAME"); - } - - /** - * Return the string for add existing account button. - * @return the string for add existing account button. - */ - @Override - protected String getExistingAccountLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.EXISTING_ACCOUNT"); - } - - /** - * Return the string for create new account button. - * @return the string for create new account button. - */ - @Override - protected String getCreateAccountLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.CREATE_ACCOUNT"); - } -} +package net.java.sip.communicator.plugin.sip2sipaccregwizz; + +import java.util.*; + +import net.java.sip.communicator.plugin.sipaccregwizz.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.sip.*; + +/** + * The Sip2SipAccountRegistrationWizard is an implementation of the + * AccountRegistrationWizard for the SIP protocol. It should allow + * the user to create and configure a new IP Tel SIP account. + * + * @author Yana Stamcheva + */ +public class Sip2SipAccountRegistrationWizard + extends SIPAccountRegistrationWizard +{ + /** + * A constant pointing to the IP Tel protocol logo image. + */ + private static final String PROTOCOL_ICON + = "service.protocol.sip2sip.SIP2SIP_16x16"; + + /** + * A constant pointing to the IP Tel protocol wizard page image. + */ + private static final String PAGE_IMAGE + = "service.protocol.sip2sip.SIP2SIP_64x64"; + + /** + * The protocol name. + */ + public static final String PROTOCOL = "sip2sip.info"; + + /** + * The create account form. + */ + CreateSip2SipAccountForm createAccountForm = new CreateSip2SipAccountForm(); + + /** + * Creates an instance of IptelAccountRegistrationWizard. + * @param wizardContainer the wizard container + */ + public Sip2SipAccountRegistrationWizard(WizardContainer wizardContainer) + { + super(wizardContainer); + } + + /** + * Returns the set of pages contained in this wizard. + * @return Iterator + */ + @Override + public Iterator getPages() + { + SIPAccountRegistration reg = new SIPAccountRegistration(); + + setPredefinedProperties(reg); + + return getPages(reg); + } + + /** + * Returns a simple account registration form that would be the first form + * shown to the user. Only if the user needs more settings she'll choose + * to open the advanced wizard, consisted by all pages. + * + * @param isCreateAccount indicates if the simple form should be opened as + * a create account form or as a login form + * @return a simple account registration form + */ + @Override + public Object getSimpleForm(boolean isCreateAccount) + { + SIPAccountRegistration reg = new SIPAccountRegistration(); + + setPredefinedProperties(reg); + + return getSimpleForm(reg, isCreateAccount); + } + + /** + * Sets all predefined properties specific for this account wizard. + * + * @param reg the registration object + */ + private void setPredefinedProperties(SIPAccountRegistration reg) + { + // set properties common for sip2sip + reg.setKeepAliveMethod("NONE"); + reg.setDefaultDomain("sip2sip.info"); + reg.setXCapEnable(true); + reg.setClistOptionServerUri( + "https://xcap.sipthor.net/xcap-root@sip2sip.info"); + reg.setClistOptionUseSipCredentials(true); + } + + /** + * Implements the AccountRegistrationWizard.getIcon method. + * Returns the icon to be used for this wizard. + * @return byte[] + */ + @Override + public byte[] getIcon() + { + return Sip2SipAccRegWizzActivator.getResources() + .getImageInBytes(PROTOCOL_ICON); + } + + /** + * Implements the AccountRegistrationWizard.getPageImage method. + * Returns the image used to decorate the wizard page + * + * @return byte[] the image used to decorate the wizard page + */ + @Override + public byte[] getPageImage() + { + return Sip2SipAccRegWizzActivator.getResources() + .getImageInBytes(PAGE_IMAGE); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolName + * method. Returns the protocol name for this wizard. + * @return String + */ + @Override + public String getProtocolName() + { + return Resources.getString( + "plugin.sip2sipaccregwizz.PROTOCOL_NAME"); + } + + /** + * Implements the AccountRegistrationWizard.getProtocolDescription + * method. Returns the description of the protocol for this wizard. + * @return String + */ + @Override + public String getProtocolDescription() + { + return Resources.getString( + "plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION"); + } + + /** + * Returns an example string, which should indicate to the user how the + * user name should look like. + * @return an example string, which should indicate to the user how the + * user name should look like. + */ + @Override + public String getUserNameExample() + { + return "Ex: myusername or myusername@sip2sip.info"; + } + + /** + * Returns the protocol name as listed in "ProtocolNames" or just the name + * of the service. + * @return the protocol name + */ + @Override + public String getProtocol() + { + return PROTOCOL; + } + + /** + * Returns the protocol icon path. + * @return the protocol icon path + */ + @Override + public String getProtocolIconPath() + { + return "resources/images/protocol/sip2sip"; + } + + /** + * Returns the account icon path. + * @return the account icon path + */ + @Override + public String getAccountIconPath() + { + return "resources/images/protocol/sip2sip/sip32x32.png"; + } + + /** + * Opens the browser on the page sign up + */ + @Override + public void webSignup() + { + Sip2SipAccRegWizzActivator.getBrowserLauncher() + .openURL("http://wiki.sip2sip.info"); + } + + /** + * Returns the name of the web sign up link. + * @return the name of the web sign up link + */ + @Override + public String getWebSignupLinkName() + { + return Resources.getString("plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE"); + } + + /** + * Returns an instance of CreateAccountService through which the + * user could create an account. This method is meant to be implemented by + * specific protocol provider wizards. + * @return an instance of CreateAccountService + */ + @Override + protected SIPAccountCreationFormService getCreateAccountService() + { + return createAccountForm; + } + + /** + * Returns the display label used for the sip id field. + * @return the sip id display label string. + */ + @Override + protected String getUsernameLabel() + { + return Resources.getString("plugin.sip2sipaccregwizz.USERNAME"); + } + + /** + * Return the string for add existing account button. + * @return the string for add existing account button. + */ + @Override + protected String getExistingAccountLabel() + { + return Resources.getString("plugin.sip2sipaccregwizz.EXISTING_ACCOUNT"); + } + + /** + * Return the string for create new account button. + * @return the string for create new account button. + */ + @Override + protected String getCreateAccountLabel() + { + return Resources.getString("plugin.sip2sipaccregwizz.CREATE_ACCOUNT"); + } +} diff --git a/src/net/java/sip/communicator/plugin/spellcheck/SpellCheckerConfigDialog.java b/src/net/java/sip/communicator/plugin/spellcheck/SpellCheckerConfigDialog.java index 35ef36b..6882d36 100644 --- a/src/net/java/sip/communicator/plugin/spellcheck/SpellCheckerConfigDialog.java +++ b/src/net/java/sip/communicator/plugin/spellcheck/SpellCheckerConfigDialog.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,423 +15,423 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.spellcheck; - -import java.awt.*; -import java.awt.event.*; -import java.util.List; - -import javax.swing.*; -import javax.swing.event.*; -import javax.swing.text.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.dts.spell.dictionary.*; -import org.jitsi.service.resources.*; - -/** - * The spell check dialog that would be opened from the right click menu in the - * chat window. - * - * @author Purvesh Sahoo - */ -public class SpellCheckerConfigDialog - extends SIPCommDialog - implements ActionListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private static final Logger logger = Logger - .getLogger(SpellCheckerConfigDialog.class); - - /** - * UI Components - */ - private JTextComponent currentWord; - - private JList suggestionList; - - private JScrollPane suggestionScroll; - - private JButton changeButton; - - private JButton nextButton; - - private JButton addButton; - - private JPanel checkPanel; - - private JPanel buttonsPanel; - - private JPanel topPanel; - - private JPanel suggestionPanel; - - private SpellDictionary dict; - - private Chat chat; - - private final ResourceManagementService resources = Resources - .getResources(); - - private String word; - - private int index; - - private Word clickedWord; - - public SpellCheckerConfigDialog(Chat chat, Word clickedWord, - SpellDictionary dict) - { - - super(false); - - this.dict = dict; - this.chat = chat; - - initComponents(clickedWord); - - this.setTitle(resources.getI18NString("plugin.spellcheck.TITLE")); - this.setMinimumSize(new Dimension(450, 320)); - this.setPreferredSize(new Dimension(450, 320)); - this.setResizable(false); - - JPanel mainPanel = new JPanel(new BorderLayout(10, 10)); - mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - mainPanel.add(topPanel); - - this.getContentPane().add(mainPanel); - - this.pack(); - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Dimension screenSize = toolkit.getScreenSize(); - - int x = (screenSize.width - this.getWidth()) / 2; - int y = (screenSize.height - this.getHeight()) / 2; - - this.setLocation(x, y); - - if (!currentWord.getText().equals(" ") - && this.dict.isCorrect(currentWord.getText())) - { - nextButton.doClick(); - } - } - - /** - * Initialises the UI components. - */ - private void initComponents(final Word clickWord) - { - - clickedWord = - (clickWord == null) ? Word.getWord(" ", 1, false) : clickWord; - - topPanel = new TransparentPanel(new BorderLayout()); - topPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); - topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS)); - - checkPanel = new TransparentPanel(new BorderLayout(10, 10)); - checkPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); - checkPanel.setLayout(new BoxLayout(checkPanel, BoxLayout.X_AXIS)); - - currentWord = new JTextField(clickedWord.getText()); - - currentWord.setAlignmentX(LEFT_ALIGNMENT); - currentWord.setMaximumSize(new Dimension(550, 30)); - - currentWord.setText(clickedWord.getText()); - currentWord.selectAll(); - - // JPanel wordPanel = new TransparentPanel(new BorderLayout()); - // wordPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); - // wordPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 5)); - // wordPanel.add(currentWord); - - buttonsPanel = - new TransparentPanel(new FlowLayout(FlowLayout.RIGHT, 0, 10)); - changeButton = - new JButton( - resources.getI18NString("plugin.spellcheck.dialog.REPLACE")); - changeButton.setMnemonic(resources - .getI18nMnemonic("plugin.spellcheck.dialog.REPLACE")); - - changeButton.addActionListener(new ActionListener() - { - - public void actionPerformed(ActionEvent e) - { - if (suggestionList.getSelectedValue() != null) - { - - StringBuffer newMessage = - new StringBuffer(chat.getMessage()); - int endIndex; - - if (word != null) - { - endIndex = index + currentWord.getText().length(); - newMessage.replace(index, endIndex, - (String) suggestionList.getSelectedValue()); - word = (String) suggestionList.getSelectedValue(); - } - else - { - endIndex = - clickedWord.getStart() - + clickedWord.getText().length(); - newMessage.replace(clickedWord.getStart(), endIndex, - (String) suggestionList.getSelectedValue()); - } - currentWord.setText((String) suggestionList - .getSelectedValue()); - chat.setMessage(newMessage.toString()); - - } - } - }); - changeButton.setEnabled(false); - - nextButton = - new JButton( - resources.getI18NString("plugin.spellcheck.dialog.FIND")); - nextButton.setMnemonic(resources - .getI18nMnemonic("plugin.spellcheck.dialog.FIND")); - - nextButton.addActionListener(new ActionListener() - { - - public Word getNextWord() - { - - Word nextWord; - int wordIndex; - - if (word == null) - { - if (currentWord.getText().equals(" ")) - { - String words[] = chat.getMessage().split(" "); - currentWord.setText(words[0]); - - } - - wordIndex = - chat.getMessage().indexOf(currentWord.getText()); - if (dict.isCorrect(currentWord.getText())) - currentWord.setText(""); - } - else - { - wordIndex = chat.getMessage().indexOf(word, index); - } - - Word presentWord = - Word.getWord(chat.getMessage(), wordIndex, false); - - if (presentWord.getEnd() == chat.getMessage().length()) - { - nextWord = Word.getWord(chat.getMessage(), 0, false); - - } - else - { - nextWord = - Word.getWord(chat.getMessage(), - presentWord.getEnd() + 1, false); - } - - index = nextWord.getStart(); - word = nextWord.getText(); - - return nextWord; - } - - public void actionPerformed(ActionEvent e) - { - Word nextWord = getNextWord(); - int breakIndex = nextWord.getStart(); - if(breakIndex == 0) - breakIndex = nextWord.getEnd() + 1; - - if(nextWord.getText().length() == 0) - { - breakIndex++; - nextWord = getNextWord(); - } - - while (dict.isCorrect(nextWord.getText()) - && nextWord.getEnd() + 1 != breakIndex) - { - nextWord = getNextWord(); - - } - - if (!dict.isCorrect(nextWord.getText())) - { - word = nextWord.getText(); - currentWord.setText(nextWord.getText()); - - String clickedWord = currentWord.getText(); - setSuggestionModel(clickedWord); - } - - } - }); - - buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS)); - buttonsPanel.add(changeButton); - buttonsPanel.add(nextButton); - - checkPanel.add(currentWord, BorderLayout.NORTH); - checkPanel.add(Box.createHorizontalStrut(10)); - checkPanel.add(buttonsPanel, BorderLayout.EAST); - - topPanel.add(checkPanel, BorderLayout.NORTH); - topPanel.add(Box.createVerticalStrut(10)); - - DefaultListModel dataModel = new DefaultListModel(); - suggestionList = new JList(dataModel); - - suggestionScroll = new JScrollPane(suggestionList); - suggestionScroll.setAlignmentX(LEFT_ALIGNMENT); - - if (!dict.isCorrect(clickedWord.getText())) - setSuggestionModel(clickedWord.getText()); - - suggestionList.addListSelectionListener(new ListSelectionListener() - { - - public void valueChanged(ListSelectionEvent e) - { - - if (!e.getValueIsAdjusting()) - { - changeButton.setEnabled(true); - } - } - }); - - MouseListener clickListener = new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - if (e.getClickCount() == 2) - { - - StringBuffer newMessage = - new StringBuffer(chat.getMessage()); - int endIndex; - - if (word != null) - { - endIndex = index + currentWord.getText().length(); - newMessage.replace(index, endIndex, - (String) suggestionList.getSelectedValue()); - word = (String) suggestionList.getSelectedValue(); - } - else - { - endIndex = - clickedWord.getStart() - + clickedWord.getText().length(); - newMessage.replace(clickedWord.getStart(), endIndex, - (String) suggestionList.getSelectedValue()); - } - currentWord.setText((String) suggestionList - .getSelectedValue()); - chat.setMessage(newMessage.toString()); - - } - } - }; - - suggestionList.addMouseListener(clickListener); - - addButton = - new JButton(resources.getI18NString("plugin.spellcheck.dialog.ADD")); - addButton.setMnemonic(resources - .getI18nMnemonic("plugin.spellcheck.dialog.ADD")); - - addButton.addActionListener(new ActionListener() - { - - public void actionPerformed(ActionEvent e) - { - - try - { - dict.addWord(currentWord.getText()); - chat.promptRepaint(); - } - catch (SpellDictionaryException exc) - { - String msg = "Unable to add word to personal dictionary"; - logger.error(msg, exc); - } - } - }); - - suggestionPanel = new TransparentPanel(new BorderLayout(10, 10)); - suggestionPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); - suggestionPanel.setLayout(new BoxLayout(suggestionPanel, - BoxLayout.X_AXIS)); - suggestionPanel.add(suggestionScroll); - suggestionPanel.add(Box.createHorizontalStrut(10)); - suggestionPanel.add(addButton); - - topPanel.add(suggestionPanel, BorderLayout.SOUTH); - - } - - /** - * Sets the model for the suggestion list - * - * @param clickedWord - */ - private void setSuggestionModel(String clickedWord) - { - - DefaultListModel dataModel = new DefaultListModel(); - List corrections = this.dict.getSuggestions(clickedWord); - for (String correction : corrections) - { - dataModel.addElement(correction); - } - - suggestionList.setModel(dataModel); - } - - /** - * Returns the selected correction value - * - * @return selected value from suggestion list - */ - public Object getCorrection() - { - - return suggestionList.getSelectedValue(); - } - - public void actionPerformed(ActionEvent e) - { - // TODO Auto-generated method stub - - } - - @Override - protected void close(boolean escaped) - { - // TODO Auto-generated method stub - - } - -} +package net.java.sip.communicator.plugin.spellcheck; + +import java.awt.*; +import java.awt.event.*; +import java.util.List; + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.*; + +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.plugin.desktoputil.*; + +import org.dts.spell.dictionary.*; +import org.jitsi.service.resources.*; + +/** + * The spell check dialog that would be opened from the right click menu in the + * chat window. + * + * @author Purvesh Sahoo + */ +public class SpellCheckerConfigDialog + extends SIPCommDialog + implements ActionListener +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + private static final Logger logger = Logger + .getLogger(SpellCheckerConfigDialog.class); + + /** + * UI Components + */ + private JTextComponent currentWord; + + private JList suggestionList; + + private JScrollPane suggestionScroll; + + private JButton changeButton; + + private JButton nextButton; + + private JButton addButton; + + private JPanel checkPanel; + + private JPanel buttonsPanel; + + private JPanel topPanel; + + private JPanel suggestionPanel; + + private SpellDictionary dict; + + private Chat chat; + + private final ResourceManagementService resources = Resources + .getResources(); + + private String word; + + private int index; + + private Word clickedWord; + + public SpellCheckerConfigDialog(Chat chat, Word clickedWord, + SpellDictionary dict) + { + + super(false); + + this.dict = dict; + this.chat = chat; + + initComponents(clickedWord); + + this.setTitle(resources.getI18NString("plugin.spellcheck.TITLE")); + this.setMinimumSize(new Dimension(450, 320)); + this.setPreferredSize(new Dimension(450, 320)); + this.setResizable(false); + + JPanel mainPanel = new JPanel(new BorderLayout(10, 10)); + mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + mainPanel.add(topPanel); + + this.getContentPane().add(mainPanel); + + this.pack(); + Toolkit toolkit = Toolkit.getDefaultToolkit(); + Dimension screenSize = toolkit.getScreenSize(); + + int x = (screenSize.width - this.getWidth()) / 2; + int y = (screenSize.height - this.getHeight()) / 2; + + this.setLocation(x, y); + + if (!currentWord.getText().equals(" ") + && this.dict.isCorrect(currentWord.getText())) + { + nextButton.doClick(); + } + } + + /** + * Initialises the UI components. + */ + private void initComponents(final Word clickWord) + { + + clickedWord = + (clickWord == null) ? Word.getWord(" ", 1, false) : clickWord; + + topPanel = new TransparentPanel(new BorderLayout()); + topPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS)); + + checkPanel = new TransparentPanel(new BorderLayout(10, 10)); + checkPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + checkPanel.setLayout(new BoxLayout(checkPanel, BoxLayout.X_AXIS)); + + currentWord = new JTextField(clickedWord.getText()); + + currentWord.setAlignmentX(LEFT_ALIGNMENT); + currentWord.setMaximumSize(new Dimension(550, 30)); + + currentWord.setText(clickedWord.getText()); + currentWord.selectAll(); + + // JPanel wordPanel = new TransparentPanel(new BorderLayout()); + // wordPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + // wordPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 5)); + // wordPanel.add(currentWord); + + buttonsPanel = + new TransparentPanel(new FlowLayout(FlowLayout.RIGHT, 0, 10)); + changeButton = + new JButton( + resources.getI18NString("plugin.spellcheck.dialog.REPLACE")); + changeButton.setMnemonic(resources + .getI18nMnemonic("plugin.spellcheck.dialog.REPLACE")); + + changeButton.addActionListener(new ActionListener() + { + + public void actionPerformed(ActionEvent e) + { + if (suggestionList.getSelectedValue() != null) + { + + StringBuffer newMessage = + new StringBuffer(chat.getMessage()); + int endIndex; + + if (word != null) + { + endIndex = index + currentWord.getText().length(); + newMessage.replace(index, endIndex, + (String) suggestionList.getSelectedValue()); + word = (String) suggestionList.getSelectedValue(); + } + else + { + endIndex = + clickedWord.getStart() + + clickedWord.getText().length(); + newMessage.replace(clickedWord.getStart(), endIndex, + (String) suggestionList.getSelectedValue()); + } + currentWord.setText((String) suggestionList + .getSelectedValue()); + chat.setMessage(newMessage.toString()); + + } + } + }); + changeButton.setEnabled(false); + + nextButton = + new JButton( + resources.getI18NString("plugin.spellcheck.dialog.FIND")); + nextButton.setMnemonic(resources + .getI18nMnemonic("plugin.spellcheck.dialog.FIND")); + + nextButton.addActionListener(new ActionListener() + { + + public Word getNextWord() + { + + Word nextWord; + int wordIndex; + + if (word == null) + { + if (currentWord.getText().equals(" ")) + { + String words[] = chat.getMessage().split(" "); + currentWord.setText(words[0]); + + } + + wordIndex = + chat.getMessage().indexOf(currentWord.getText()); + if (dict.isCorrect(currentWord.getText())) + currentWord.setText(""); + } + else + { + wordIndex = chat.getMessage().indexOf(word, index); + } + + Word presentWord = + Word.getWord(chat.getMessage(), wordIndex, false); + + if (presentWord.getEnd() == chat.getMessage().length()) + { + nextWord = Word.getWord(chat.getMessage(), 0, false); + + } + else + { + nextWord = + Word.getWord(chat.getMessage(), + presentWord.getEnd() + 1, false); + } + + index = nextWord.getStart(); + word = nextWord.getText(); + + return nextWord; + } + + public void actionPerformed(ActionEvent e) + { + Word nextWord = getNextWord(); + int breakIndex = nextWord.getStart(); + if(breakIndex == 0) + breakIndex = nextWord.getEnd() + 1; + + if(nextWord.getText().length() == 0) + { + breakIndex++; + nextWord = getNextWord(); + } + + while (dict.isCorrect(nextWord.getText()) + && nextWord.getEnd() + 1 != breakIndex) + { + nextWord = getNextWord(); + + } + + if (!dict.isCorrect(nextWord.getText())) + { + word = nextWord.getText(); + currentWord.setText(nextWord.getText()); + + String clickedWord = currentWord.getText(); + setSuggestionModel(clickedWord); + } + + } + }); + + buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS)); + buttonsPanel.add(changeButton); + buttonsPanel.add(nextButton); + + checkPanel.add(currentWord, BorderLayout.NORTH); + checkPanel.add(Box.createHorizontalStrut(10)); + checkPanel.add(buttonsPanel, BorderLayout.EAST); + + topPanel.add(checkPanel, BorderLayout.NORTH); + topPanel.add(Box.createVerticalStrut(10)); + + DefaultListModel dataModel = new DefaultListModel(); + suggestionList = new JList(dataModel); + + suggestionScroll = new JScrollPane(suggestionList); + suggestionScroll.setAlignmentX(LEFT_ALIGNMENT); + + if (!dict.isCorrect(clickedWord.getText())) + setSuggestionModel(clickedWord.getText()); + + suggestionList.addListSelectionListener(new ListSelectionListener() + { + + public void valueChanged(ListSelectionEvent e) + { + + if (!e.getValueIsAdjusting()) + { + changeButton.setEnabled(true); + } + } + }); + + MouseListener clickListener = new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + if (e.getClickCount() == 2) + { + + StringBuffer newMessage = + new StringBuffer(chat.getMessage()); + int endIndex; + + if (word != null) + { + endIndex = index + currentWord.getText().length(); + newMessage.replace(index, endIndex, + (String) suggestionList.getSelectedValue()); + word = (String) suggestionList.getSelectedValue(); + } + else + { + endIndex = + clickedWord.getStart() + + clickedWord.getText().length(); + newMessage.replace(clickedWord.getStart(), endIndex, + (String) suggestionList.getSelectedValue()); + } + currentWord.setText((String) suggestionList + .getSelectedValue()); + chat.setMessage(newMessage.toString()); + + } + } + }; + + suggestionList.addMouseListener(clickListener); + + addButton = + new JButton(resources.getI18NString("plugin.spellcheck.dialog.ADD")); + addButton.setMnemonic(resources + .getI18nMnemonic("plugin.spellcheck.dialog.ADD")); + + addButton.addActionListener(new ActionListener() + { + + public void actionPerformed(ActionEvent e) + { + + try + { + dict.addWord(currentWord.getText()); + chat.promptRepaint(); + } + catch (SpellDictionaryException exc) + { + String msg = "Unable to add word to personal dictionary"; + logger.error(msg, exc); + } + } + }); + + suggestionPanel = new TransparentPanel(new BorderLayout(10, 10)); + suggestionPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8)); + suggestionPanel.setLayout(new BoxLayout(suggestionPanel, + BoxLayout.X_AXIS)); + suggestionPanel.add(suggestionScroll); + suggestionPanel.add(Box.createHorizontalStrut(10)); + suggestionPanel.add(addButton); + + topPanel.add(suggestionPanel, BorderLayout.SOUTH); + + } + + /** + * Sets the model for the suggestion list + * + * @param clickedWord + */ + private void setSuggestionModel(String clickedWord) + { + + DefaultListModel dataModel = new DefaultListModel(); + List corrections = this.dict.getSuggestions(clickedWord); + for (String correction : corrections) + { + dataModel.addElement(correction); + } + + suggestionList.setModel(dataModel); + } + + /** + * Returns the selected correction value + * + * @return selected value from suggestion list + */ + public Object getCorrection() + { + + return suggestionList.getSelectedValue(); + } + + public void actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + + @Override + protected void close(boolean escaped) + { + // TODO Auto-generated method stub + + } + +} diff --git a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java index 2a1bbe3..00c204e 100644 --- a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java +++ b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,170 +15,170 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.thunderbird; - -import java.util.*; - -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Bundle-Activator for the Thunderbird address book contact source plug-in. - * - * @author Ingo Bauersachs - */ -public class ThunderbirdActivator - implements BundleActivator -{ - /** OSGi context. */ - private static BundleContext bundleContext; - - /** Active address book registrations. */ - private static Map - registrations; - - /** - * The registered PhoneNumberI18nService. - */ - private static PhoneNumberI18nService phoneNumberI18nService; - - /** - * Gets the configuration service. - * @return the configuration service. - */ - static ConfigurationService getConfigService() - { - return ServiceUtils.getService(bundleContext, - ConfigurationService.class); - } - - /** - * Gets the resource service. - * @return the resource service. - */ - static ResourceManagementService getResources() - { - return ServiceUtils.getService(bundleContext, - ResourceManagementService.class); - } - - /** - * Gets all registered Thunderbird address book services. - * @return all registered Thunderbird address book services. - */ - static List getActiveServices() - { - return new LinkedList( - registrations.keySet()); - } - - /** - * Loads and registers an address book service. - * @param config the name of the base property of the service to load. - */ - static void add(String config) - { - ThunderbirdContactSourceService service - = new ThunderbirdContactSourceService(config); - registrations.put(service, - bundleContext.registerService( - ContactSourceService.class.getName(), service, null)); - } - - /** - * Stops an address book service and deletes the corresponding configuration - * data. - * - * @param service the address book instance to remove. - */ - static void remove(ThunderbirdContactSourceService service) - { - registrations.get(service).unregister(); - registrations.remove(service); - ConfigurationService config = getConfigService(); - config.removeProperty(service.getBaseConfigProperty()); - for (String prop : config.getPropertyNamesByPrefix( - service.getBaseConfigProperty(), false)) - { - config.removeProperty(prop); - } - } - - /** - * Searches the configuration for Thunderbird address books and registers a - * {@link ContactSourceService} for each found config. - */ - public void start(BundleContext bundleContext) throws Exception - { - ThunderbirdActivator.bundleContext = bundleContext; - - ConfigurationService config = getConfigService(); - List configs = - config.getPropertyNamesByPrefix( - ThunderbirdContactSourceService.PNAME_BASE_THUNDERBIRD_CONFIG, - false); - - registrations = new HashMap - (); - for (String cfg : configs) - { - String value = config.getString(cfg); - if (value != null && cfg.endsWith(value)) - { - add(cfg); - } - } - - /* registers the configuration form */ - Dictionary properties - = new Hashtable(); - properties.put( - ConfigurationForm.FORM_TYPE, - ConfigurationForm.CONTACT_SOURCE_TYPE); - - bundleContext.registerService( - ConfigurationForm.class.getName(), - new LazyConfigurationForm( - ThunderbirdConfigForm.class.getName(), - getClass().getClassLoader(), - null, - "plugin.thunderbird.CONFIG_FORM_TITLE"), - properties); - } - - /** - * Unregisters all {@link ContactSourceService}s that were registered by - * this activator. - */ - public void stop(BundleContext bundleContext) throws Exception - { - for (ServiceRegistration sr : registrations.values()) - { - sr.unregister(); - } - - registrations = null; - } - - /** - * Returns the PhoneNumberI18nService. - * @return returns the PhoneNumberI18nService. - */ - public static PhoneNumberI18nService getPhoneNumberI18nService() - { - if(phoneNumberI18nService == null) - { - phoneNumberI18nService = ServiceUtils.getService( - bundleContext, - PhoneNumberI18nService.class); - } - - return phoneNumberI18nService; - } -} +package net.java.sip.communicator.plugin.thunderbird; + +import java.util.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * Bundle-Activator for the Thunderbird address book contact source plug-in. + * + * @author Ingo Bauersachs + */ +public class ThunderbirdActivator + implements BundleActivator +{ + /** OSGi context. */ + private static BundleContext bundleContext; + + /** Active address book registrations. */ + private static Map + registrations; + + /** + * The registered PhoneNumberI18nService. + */ + private static PhoneNumberI18nService phoneNumberI18nService; + + /** + * Gets the configuration service. + * @return the configuration service. + */ + static ConfigurationService getConfigService() + { + return ServiceUtils.getService(bundleContext, + ConfigurationService.class); + } + + /** + * Gets the resource service. + * @return the resource service. + */ + static ResourceManagementService getResources() + { + return ServiceUtils.getService(bundleContext, + ResourceManagementService.class); + } + + /** + * Gets all registered Thunderbird address book services. + * @return all registered Thunderbird address book services. + */ + static List getActiveServices() + { + return new LinkedList( + registrations.keySet()); + } + + /** + * Loads and registers an address book service. + * @param config the name of the base property of the service to load. + */ + static void add(String config) + { + ThunderbirdContactSourceService service + = new ThunderbirdContactSourceService(config); + registrations.put(service, + bundleContext.registerService( + ContactSourceService.class.getName(), service, null)); + } + + /** + * Stops an address book service and deletes the corresponding configuration + * data. + * + * @param service the address book instance to remove. + */ + static void remove(ThunderbirdContactSourceService service) + { + registrations.get(service).unregister(); + registrations.remove(service); + ConfigurationService config = getConfigService(); + config.removeProperty(service.getBaseConfigProperty()); + for (String prop : config.getPropertyNamesByPrefix( + service.getBaseConfigProperty(), false)) + { + config.removeProperty(prop); + } + } + + /** + * Searches the configuration for Thunderbird address books and registers a + * {@link ContactSourceService} for each found config. + */ + public void start(BundleContext bundleContext) throws Exception + { + ThunderbirdActivator.bundleContext = bundleContext; + + ConfigurationService config = getConfigService(); + List configs = + config.getPropertyNamesByPrefix( + ThunderbirdContactSourceService.PNAME_BASE_THUNDERBIRD_CONFIG, + false); + + registrations = new HashMap + (); + for (String cfg : configs) + { + String value = config.getString(cfg); + if (value != null && cfg.endsWith(value)) + { + add(cfg); + } + } + + /* registers the configuration form */ + Dictionary properties + = new Hashtable(); + properties.put( + ConfigurationForm.FORM_TYPE, + ConfigurationForm.CONTACT_SOURCE_TYPE); + + bundleContext.registerService( + ConfigurationForm.class.getName(), + new LazyConfigurationForm( + ThunderbirdConfigForm.class.getName(), + getClass().getClassLoader(), + null, + "plugin.thunderbird.CONFIG_FORM_TITLE"), + properties); + } + + /** + * Unregisters all {@link ContactSourceService}s that were registered by + * this activator. + */ + public void stop(BundleContext bundleContext) throws Exception + { + for (ServiceRegistration sr : registrations.values()) + { + sr.unregister(); + } + + registrations = null; + } + + /** + * Returns the PhoneNumberI18nService. + * @return returns the PhoneNumberI18nService. + */ + public static PhoneNumberI18nService getPhoneNumberI18nService() + { + if(phoneNumberI18nService == null) + { + phoneNumberI18nService = ServiceUtils.getService( + bundleContext, + PhoneNumberI18nService.class); + } + + return phoneNumberI18nService; + } +} diff --git a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java index 429ff6c..00488f9 100644 --- a/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java +++ b/src/net/java/sip/communicator/plugin/thunderbird/ThunderbirdContactQuery.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,267 +15,267 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.thunderbird; - -import java.io.*; -import java.util.*; -import java.util.Map.Entry; -import java.util.regex.*; - -import org.jitsi.util.StringUtils; - -import mork.*; -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.contactsource.ContactDetail.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Queries a Thunderbird address book for contacts matching the given pattern. - * - * @author Ingo Bauersachs - */ -public class ThunderbirdContactQuery - extends AsyncContactQuery -{ - /** Class logger */ - private final static Logger logger = Logger - .getLogger(ThunderbirdContactQuery.class); - - /** - * Creates a new instance of this class. - * - * @param owner The contact source that created this query. - * @param query The pattern to match against the contacts database. - */ - public ThunderbirdContactQuery(ThunderbirdContactSourceService owner, - Pattern query) - { - super(owner, query); - } - - /** - * Starts the query against the address book database. - */ - @Override - protected void run() - { - String filename = super.getContactSource().getFilename(); - File file = new File(filename); - try - { - if (file.lastModified() > getContactSource().lastDatabaseFileChange) - { - // parse the Thunderbird Mork database - InputStreamReader sr = - new InputStreamReader(new FileInputStream(filename)); - MorkDocument md = new MorkDocument(sr); - sr.close(); - - // We now have rows in their tables and additional rows at - // transaction level. Put the to a better format: - // DB -> Tables -> Rows - Map> db = - new HashMap>(); - for (Table t : md.getTables()) - { - String tableId = t.getTableId() + "/" + t.getScopeName(); - Map table = db.get(tableId); - if (table == null) - { - table = new HashMap(); - db.put(tableId, table); - } - - for (Row r : t.getRows()) - { - String scope = r.getScopeName(); - if (scope == null) - { - scope = t.getScopeName(); - } - - table.put(r.getRowId() + "/" + scope, r); - } - } - - // The additional rows at the root-level update/replace the ones - // in the tables. There's usually neither a table nor a scope - // defined, so lets just use the default. - String defaultScope = md.getDicts().get(0).dereference("^80"); - for (Row r : md.getRows()) - { - String scope = r.getScopeName(); - if (scope == null) - { - scope = defaultScope; - } - - String tableId = "1/" + scope; - Map table = db.get(tableId); - if (table == null) - { - table = new HashMap(); - db.put(tableId, table); - } - - String rowId = r.getRowId() + "/" + scope; - if (rowId.startsWith("-")) - { - rowId = rowId.substring(1); - } - - table.put(rowId, r); - } - - super.getContactSource().database = db; - super.getContactSource().defaultScope = defaultScope; - super.getContactSource().lastDatabaseFileChange = - file.lastModified(); - } - - // okay, "transactions" are applied, now perform the search - for (Entry> table - : super.getContactSource().database.entrySet()) - { - for (Map.Entry e : table.getValue().entrySet()) - { - if (e.getKey().endsWith(getContactSource().defaultScope)) - { - readEntry(e.getValue()); - } - } - } - - super.stopped(true); - } - catch (FileNotFoundException e) - { - logger.warn("Could not open address book", e); - } - catch (Exception e) - { - logger.warn("Could not parse " + file, e); - } - } - - /** - * Processes a database row by matching it against the query and adding it - * to the result set if it matched. - * - * @param r The database row representing a contact. - */ - private void readEntry(Row r) - { - // match the pattern against this contact - boolean hadMatch = false; - for (Alias value : r.getAliases().values()) - { - if (value != null - && (super.query.matcher(value.getValue()).find() || super - .phoneNumberMatches(value.getValue()))) - { - hadMatch = true; - break; - } - } - - // nope, didn't match, ignore - if (!hadMatch) - { - return; - } - - List details = new LinkedList(); - - // e-mail(s) - for (String email : getPropertySet(r, "PrimaryEmail", "SecondEmail", - "DefaultEmail")) - { - ContactDetail detail = new ContactDetail(email, Category.Email); - detail.addSupportedOpSet(OperationSetPersistentPresence.class); - details.add(detail); - } - - // phone number(s) - this.addPhoneDetail(details, r, "HomePhone", SubCategory.Home); - this.addPhoneDetail(details, r, "WorkPhone", SubCategory.Work); - this.addPhoneDetail(details, r, "CellularNumber", SubCategory.Mobile); - - // and the dispaly name - String displayName = r.getValue("DisplayName"); - if (StringUtils.isNullOrEmpty(displayName, true)) - { - displayName = r.getValue("LastName"); - if (displayName != null) - { - displayName = displayName.trim(); - } - - String firstName = r.getValue("FirstName"); - if (!StringUtils.isNullOrEmpty(firstName, true)) - { - displayName = firstName + " " + displayName; - } - } - - // create the contact and add it to the results - GenericSourceContact sc = - new GenericSourceContact(super.getContactSource(), displayName, - details); - addQueryResult(sc); - } - - /** - * Adds a "Phone" {@link ContactDetail} to a query contact. - * - * @param details The {@link List} of {@link ContactDetail}s to which the - * details is added. - * @param r The source database row of the contact. - * @param property The source database property name to add as a detail. - * @param category The Phone-{@link SubCategory} for the phone number to - * add. - */ - private void addPhoneDetail(List details, Row r, - String property, SubCategory category) - { - String phone = r.getValue(property); - if (StringUtils.isNullOrEmpty(phone, true)) - { - return; - } - - phone - = ThunderbirdActivator.getPhoneNumberI18nService().normalize(phone); - ContactDetail detail = - new ContactDetail(phone, ContactDetail.Category.Phone, - new ContactDetail.SubCategory[] - { category }); - - detail.addSupportedOpSet(OperationSetBasicTelephony.class); - detail.addSupportedOpSet(OperationSetPersistentPresence.class); - details.add(detail); - } - - /** - * Gets a set of non-empty properties from the source database row. - * - * @param r The source database row to process. - * @param properties The property-names to extract. - * @return A set of non-empty properties from the source database row. - */ - private Set getPropertySet(Row r, String... properties) - { - Set validValues = new HashSet(properties.length); - for (String prop : properties) - { - String value = r.getValue(prop); - if (!StringUtils.isNullOrEmpty(value, true)) - { - validValues.add(value); - } - } - - return validValues; - } -} +package net.java.sip.communicator.plugin.thunderbird; + +import java.io.*; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.*; + +import org.jitsi.util.StringUtils; + +import mork.*; +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.contactsource.ContactDetail.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * Queries a Thunderbird address book for contacts matching the given pattern. + * + * @author Ingo Bauersachs + */ +public class ThunderbirdContactQuery + extends AsyncContactQuery +{ + /** Class logger */ + private final static Logger logger = Logger + .getLogger(ThunderbirdContactQuery.class); + + /** + * Creates a new instance of this class. + * + * @param owner The contact source that created this query. + * @param query The pattern to match against the contacts database. + */ + public ThunderbirdContactQuery(ThunderbirdContactSourceService owner, + Pattern query) + { + super(owner, query); + } + + /** + * Starts the query against the address book database. + */ + @Override + protected void run() + { + String filename = super.getContactSource().getFilename(); + File file = new File(filename); + try + { + if (file.lastModified() > getContactSource().lastDatabaseFileChange) + { + // parse the Thunderbird Mork database + InputStreamReader sr = + new InputStreamReader(new FileInputStream(filename)); + MorkDocument md = new MorkDocument(sr); + sr.close(); + + // We now have rows in their tables and additional rows at + // transaction level. Put the to a better format: + // DB -> Tables -> Rows + Map> db = + new HashMap>(); + for (Table t : md.getTables()) + { + String tableId = t.getTableId() + "/" + t.getScopeName(); + Map table = db.get(tableId); + if (table == null) + { + table = new HashMap(); + db.put(tableId, table); + } + + for (Row r : t.getRows()) + { + String scope = r.getScopeName(); + if (scope == null) + { + scope = t.getScopeName(); + } + + table.put(r.getRowId() + "/" + scope, r); + } + } + + // The additional rows at the root-level update/replace the ones + // in the tables. There's usually neither a table nor a scope + // defined, so lets just use the default. + String defaultScope = md.getDicts().get(0).dereference("^80"); + for (Row r : md.getRows()) + { + String scope = r.getScopeName(); + if (scope == null) + { + scope = defaultScope; + } + + String tableId = "1/" + scope; + Map table = db.get(tableId); + if (table == null) + { + table = new HashMap(); + db.put(tableId, table); + } + + String rowId = r.getRowId() + "/" + scope; + if (rowId.startsWith("-")) + { + rowId = rowId.substring(1); + } + + table.put(rowId, r); + } + + super.getContactSource().database = db; + super.getContactSource().defaultScope = defaultScope; + super.getContactSource().lastDatabaseFileChange = + file.lastModified(); + } + + // okay, "transactions" are applied, now perform the search + for (Entry> table + : super.getContactSource().database.entrySet()) + { + for (Map.Entry e : table.getValue().entrySet()) + { + if (e.getKey().endsWith(getContactSource().defaultScope)) + { + readEntry(e.getValue()); + } + } + } + + super.stopped(true); + } + catch (FileNotFoundException e) + { + logger.warn("Could not open address book", e); + } + catch (Exception e) + { + logger.warn("Could not parse " + file, e); + } + } + + /** + * Processes a database row by matching it against the query and adding it + * to the result set if it matched. + * + * @param r The database row representing a contact. + */ + private void readEntry(Row r) + { + // match the pattern against this contact + boolean hadMatch = false; + for (Alias value : r.getAliases().values()) + { + if (value != null + && (super.query.matcher(value.getValue()).find() || super + .phoneNumberMatches(value.getValue()))) + { + hadMatch = true; + break; + } + } + + // nope, didn't match, ignore + if (!hadMatch) + { + return; + } + + List details = new LinkedList(); + + // e-mail(s) + for (String email : getPropertySet(r, "PrimaryEmail", "SecondEmail", + "DefaultEmail")) + { + ContactDetail detail = new ContactDetail(email, Category.Email); + detail.addSupportedOpSet(OperationSetPersistentPresence.class); + details.add(detail); + } + + // phone number(s) + this.addPhoneDetail(details, r, "HomePhone", SubCategory.Home); + this.addPhoneDetail(details, r, "WorkPhone", SubCategory.Work); + this.addPhoneDetail(details, r, "CellularNumber", SubCategory.Mobile); + + // and the dispaly name + String displayName = r.getValue("DisplayName"); + if (StringUtils.isNullOrEmpty(displayName, true)) + { + displayName = r.getValue("LastName"); + if (displayName != null) + { + displayName = displayName.trim(); + } + + String firstName = r.getValue("FirstName"); + if (!StringUtils.isNullOrEmpty(firstName, true)) + { + displayName = firstName + " " + displayName; + } + } + + // create the contact and add it to the results + GenericSourceContact sc = + new GenericSourceContact(super.getContactSource(), displayName, + details); + addQueryResult(sc); + } + + /** + * Adds a "Phone" {@link ContactDetail} to a query contact. + * + * @param details The {@link List} of {@link ContactDetail}s to which the + * details is added. + * @param r The source database row of the contact. + * @param property The source database property name to add as a detail. + * @param category The Phone-{@link SubCategory} for the phone number to + * add. + */ + private void addPhoneDetail(List details, Row r, + String property, SubCategory category) + { + String phone = r.getValue(property); + if (StringUtils.isNullOrEmpty(phone, true)) + { + return; + } + + phone + = ThunderbirdActivator.getPhoneNumberI18nService().normalize(phone); + ContactDetail detail = + new ContactDetail(phone, ContactDetail.Category.Phone, + new ContactDetail.SubCategory[] + { category }); + + detail.addSupportedOpSet(OperationSetBasicTelephony.class); + detail.addSupportedOpSet(OperationSetPersistentPresence.class); + details.add(detail); + } + + /** + * Gets a set of non-empty properties from the source database row. + * + * @param r The source database row to process. + * @param properties The property-names to extract. + * @return A set of non-empty properties from the source database row. + */ + private Set getPropertySet(Row r, String... properties) + { + Set validValues = new HashSet(properties.length); + for (String prop : properties) + { + String value = r.getValue(prop); + if (!StringUtils.isNullOrEmpty(value, true)) + { + validValues.add(value); + } + } + + return validValues; + } +} diff --git a/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java b/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java index 20f85b8..9c61233 100644 --- a/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java +++ b/src/net/java/sip/communicator/plugin/update/CheckForUpdatesMenuItemComponent.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,77 +15,77 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.update; - -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.gui.*; - -/** - * Implements PluginComponent for the "Check for Updates" menu - * item. - * - * @author Damian Minkov - * @author Lyubomir Marinov - */ -public class CheckForUpdatesMenuItemComponent - extends AbstractPluginComponent -{ - /** - * The "Check for Updates" menu item. - */ - private JMenuItem checkForUpdatesMenuItem; - - /** - * Initializes a new "Check for Updates" menu item. - * - * @param container the container of the update menu component - */ - public CheckForUpdatesMenuItemComponent(Container container, - PluginComponentFactory parentFactory) - { - super(container, parentFactory); - } - - /** - * Gets the UI Component of this PluginComponent. - * - * @return the UI Component of this PluginComponent - * @see PluginComponent#getComponent() - */ - public JMenuItem getComponent() - { - if(checkForUpdatesMenuItem == null) - { - checkForUpdatesMenuItem - = new JMenuItem( - Resources.getResources().getI18NString( - "plugin.updatechecker.UPDATE_MENU_ENTRY")); - checkForUpdatesMenuItem.addActionListener( - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - UpdateActivator.getUpdateService().checkForUpdates( - true); - } - }); - } - return checkForUpdatesMenuItem; - } - - /** - * Gets the name of this PluginComponent. - * - * @return the name of this PluginComponent - * @see PluginComponent#getName() - */ - public String getName() - { - return - Resources.getResources().getI18NString( - "plugin.updatechecker.UPDATE_MENU_ENTRY"); - } -} +package net.java.sip.communicator.plugin.update; + +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.service.gui.*; + +/** + * Implements PluginComponent for the "Check for Updates" menu + * item. + * + * @author Damian Minkov + * @author Lyubomir Marinov + */ +public class CheckForUpdatesMenuItemComponent + extends AbstractPluginComponent +{ + /** + * The "Check for Updates" menu item. + */ + private JMenuItem checkForUpdatesMenuItem; + + /** + * Initializes a new "Check for Updates" menu item. + * + * @param container the container of the update menu component + */ + public CheckForUpdatesMenuItemComponent(Container container, + PluginComponentFactory parentFactory) + { + super(container, parentFactory); + } + + /** + * Gets the UI Component of this PluginComponent. + * + * @return the UI Component of this PluginComponent + * @see PluginComponent#getComponent() + */ + public JMenuItem getComponent() + { + if(checkForUpdatesMenuItem == null) + { + checkForUpdatesMenuItem + = new JMenuItem( + Resources.getResources().getI18NString( + "plugin.updatechecker.UPDATE_MENU_ENTRY")); + checkForUpdatesMenuItem.addActionListener( + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + UpdateActivator.getUpdateService().checkForUpdates( + true); + } + }); + } + return checkForUpdatesMenuItem; + } + + /** + * Gets the name of this PluginComponent. + * + * @return the name of this PluginComponent + * @see PluginComponent#getName() + */ + public String getName() + { + return + Resources.getResources().getI18NString( + "plugin.updatechecker.UPDATE_MENU_ENTRY"); + } +} diff --git a/src/net/java/sip/communicator/plugin/update/UpdateActivator.java b/src/net/java/sip/communicator/plugin/update/UpdateActivator.java index 8155117..251ac7a 100644 --- a/src/net/java/sip/communicator/plugin/update/UpdateActivator.java +++ b/src/net/java/sip/communicator/plugin/update/UpdateActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,306 +15,306 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.update; - -import java.util.*; -import java.util.concurrent.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.shutdown.*; -import net.java.sip.communicator.service.update.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.util.Logger; - -import org.jitsi.service.configuration.*; -import org.jitsi.util.*; -import org.osgi.framework.*; - -/** - * Implements BundleActivator for the update plug-in. - * - * @author Damian Minkov - * @author Lyubomir Marinov - */ -public class UpdateActivator - extends AbstractServiceDependentActivator -{ - /** - * The Logger used by the UpdateActivator class and its - * instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(UpdateActivator.class); - - /** - * The name of the configuration property which indicates whether the - * checking for updates on application startup is enabled. - */ - private static final String UPDATE_ENABLED - = "net.java.sip.communicator.plugin.updatechecker.ENABLED"; - - /** - * The name of the configuration property which indicates whether the - * "checking for updates" menu entry is disabled. - */ - private static final String CHECK_FOR_UPDATES_MENU_DISABLED_PROP - = "net.java.sip.communicator.plugin.update.checkforupdatesmenu.DISABLED"; - - /** - * The name of the configuration property which indicates whether the client - * should automatically check for updates each day or not. - */ - private static final String CHECK_FOR_UPDATES_DAILY_ENABLED_PROP = - "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.ENABLED"; - - /** - * The name of the configuration property which indicates the hour that - * the client should check for updates (if daily update checking is enabled) - */ - private static final String CHECK_FOR_UPDATES_DAILY_TIME_PROP = - "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.HOUR"; - - /** - * Reference to the BrowserLauncherService. - */ - private static BrowserLauncherService browserLauncher; - - /** - * The BundleContext in which the one and only - * UpdateActivator instance of the update plug-in has been started. - */ - static BundleContext bundleContext; - - /** - * Reference to the ConfigurationService. - */ - private static ConfigurationService configuration; - - /** - * Reference to the UIService. - */ - private static UIService uiService; - - /** - * The update service. - */ - private static UpdateService updateService; - - /** - * A scheduler to check for updates once a day - */ - private ScheduledExecutorService mUpdateExecutor = null; - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncher == null) - { - browserLauncher - = ServiceUtils.getService( - bundleContext, - BrowserLauncherService.class); - } - return browserLauncher; - } - - /** - * Returns the ConfigurationService obtained from the bundle - * context. - * - * @return the ConfigurationService obtained from the bundle - * context - */ - static ConfigurationService getConfiguration() - { - if (configuration == null) - { - configuration - = ServiceUtils.getService( - bundleContext, - ConfigurationService.class); - } - return configuration; - } - - /** - * Gets a reference to a ShutdownService implementation - * currently registered in the bundle context of the active - * UpdateCheckActivator instance. - *

    - * The returned reference to ShutdownService is not being - * cached. - *

    - * - * @return reference to a ShutdownService implementation - * currently registered in the bundle context of the active - * UpdateCheckActivator instance - */ - static ShutdownService getShutdownService() - { - return ServiceUtils.getService(bundleContext, ShutdownService.class); - } - - /** - * Returns a reference to the UIService implementation currently registered - * in the bundle context or null if no such implementation was found. - * - * @return a reference to a UIService implementation currently registered - * in the bundle context or null if no such implementation was found. - */ - static UIService getUIService() - { - if(uiService == null) - uiService = ServiceUtils.getService(bundleContext, UIService.class); - return uiService; - } - - /** - * The dependent service is available and the bundle will start. - * @param dependentService the UIService this activator is waiting. - */ - @Override - public void start(Object dependentService) - { - if (logger.isDebugEnabled()) - logger.debug("Update checker [STARTED]"); - - ConfigurationService cfg = getConfiguration(); - - if (OSUtils.IS_WINDOWS) - { - updateService = new UpdateServiceImpl(); - - bundleContext.registerService( - UpdateService.class.getName(), - updateService, - null); - - // Register the "Check for Updates" menu item if - // the "Check for Updates" property isn't disabled. - if(!cfg.getBoolean(CHECK_FOR_UPDATES_MENU_DISABLED_PROP, false)) - { - // Register the "Check for Updates" menu item. - - Hashtable toolsMenuFilter - = new Hashtable(); - toolsMenuFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_HELP_MENU.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new PluginComponentFactory(Container.CONTAINER_HELP_MENU) - { - @Override - protected PluginComponent getPluginInstance() - { - return new CheckForUpdatesMenuItemComponent( - getContainer(), this); - } - }, - toolsMenuFilter); - } - - // Check for software update upon startup if enabled. - if(cfg.getBoolean(UPDATE_ENABLED, true)) - updateService.checkForUpdates(false); - } - - if (cfg.getBoolean(CHECK_FOR_UPDATES_DAILY_ENABLED_PROP, - false)) - { - logger.info("Scheduled update checking enabled"); - - // Schedule a "check for updates" task that will run once a day - int hoursToWait = calcHoursToWait(); - Runnable updateRunnable = new Runnable() - { - public void run() - { - logger.debug("Performing scheduled update check"); - getUpdateService().checkForUpdates(false); - } - }; - - mUpdateExecutor = Executors.newSingleThreadScheduledExecutor(); - mUpdateExecutor.scheduleAtFixedRate(updateRunnable, - hoursToWait, - 24*60*60, - TimeUnit.SECONDS); - } - - if (logger.isDebugEnabled()) - logger.debug("Update checker [REGISTERED]"); - } - - /** - * This activator depends on UIService. - * @return the class name of uiService. - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * Setting context to the activator, as soon as we have one. - * - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - /** - * Calculate the number of hour to wait until the first scheduled update - * check. This will only be called if daily checking for config updates - * is enabled - * - * @return The number of hours to wait - */ - private int calcHoursToWait() - { - // The hours to wait is the number of hours until midnight tonight (24 - // minus the current hour) plus the hour that the config says updates - // should be - return 24 - Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + - configuration.getInt(CHECK_FOR_UPDATES_DAILY_TIME_PROP, 0); - } - - /** - * Stop the bundle. Nothing to stop for now. - * @param bundleContext BundleContext provided by OSGi framework - * @throws Exception if something goes wrong during stop - */ - public void stop(BundleContext bundleContext) throws Exception - { - if (logger.isDebugEnabled()) - logger.debug("Update checker [STOPPED]"); - - if (mUpdateExecutor != null) - { - mUpdateExecutor.shutdown(); - mUpdateExecutor = null; - } - } - - /** - * Returns the update service instance. - * - * @return the update service instance - */ - static UpdateService getUpdateService() - { - return updateService; - } -} +package net.java.sip.communicator.plugin.update; + +import java.util.*; +import java.util.concurrent.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.shutdown.*; +import net.java.sip.communicator.service.update.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.Logger; + +import org.jitsi.service.configuration.*; +import org.jitsi.util.*; +import org.osgi.framework.*; + +/** + * Implements BundleActivator for the update plug-in. + * + * @author Damian Minkov + * @author Lyubomir Marinov + */ +public class UpdateActivator + extends AbstractServiceDependentActivator +{ + /** + * The Logger used by the UpdateActivator class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(UpdateActivator.class); + + /** + * The name of the configuration property which indicates whether the + * checking for updates on application startup is enabled. + */ + private static final String UPDATE_ENABLED + = "net.java.sip.communicator.plugin.updatechecker.ENABLED"; + + /** + * The name of the configuration property which indicates whether the + * "checking for updates" menu entry is disabled. + */ + private static final String CHECK_FOR_UPDATES_MENU_DISABLED_PROP + = "net.java.sip.communicator.plugin.update.checkforupdatesmenu.DISABLED"; + + /** + * The name of the configuration property which indicates whether the client + * should automatically check for updates each day or not. + */ + private static final String CHECK_FOR_UPDATES_DAILY_ENABLED_PROP = + "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.ENABLED"; + + /** + * The name of the configuration property which indicates the hour that + * the client should check for updates (if daily update checking is enabled) + */ + private static final String CHECK_FOR_UPDATES_DAILY_TIME_PROP = + "net.java.sip.communicator.plugin.update.checkforupdatesmenu.daily.HOUR"; + + /** + * Reference to the BrowserLauncherService. + */ + private static BrowserLauncherService browserLauncher; + + /** + * The BundleContext in which the one and only + * UpdateActivator instance of the update plug-in has been started. + */ + static BundleContext bundleContext; + + /** + * Reference to the ConfigurationService. + */ + private static ConfigurationService configuration; + + /** + * Reference to the UIService. + */ + private static UIService uiService; + + /** + * The update service. + */ + private static UpdateService updateService; + + /** + * A scheduler to check for updates once a day + */ + private ScheduledExecutorService mUpdateExecutor = null; + + /** + * Returns the BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService obtained from the bundle + * context + */ + static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncher == null) + { + browserLauncher + = ServiceUtils.getService( + bundleContext, + BrowserLauncherService.class); + } + return browserLauncher; + } + + /** + * Returns the ConfigurationService obtained from the bundle + * context. + * + * @return the ConfigurationService obtained from the bundle + * context + */ + static ConfigurationService getConfiguration() + { + if (configuration == null) + { + configuration + = ServiceUtils.getService( + bundleContext, + ConfigurationService.class); + } + return configuration; + } + + /** + * Gets a reference to a ShutdownService implementation + * currently registered in the bundle context of the active + * UpdateCheckActivator instance. + *

    + * The returned reference to ShutdownService is not being + * cached. + *

    + * + * @return reference to a ShutdownService implementation + * currently registered in the bundle context of the active + * UpdateCheckActivator instance + */ + static ShutdownService getShutdownService() + { + return ServiceUtils.getService(bundleContext, ShutdownService.class); + } + + /** + * Returns a reference to the UIService implementation currently registered + * in the bundle context or null if no such implementation was found. + * + * @return a reference to a UIService implementation currently registered + * in the bundle context or null if no such implementation was found. + */ + static UIService getUIService() + { + if(uiService == null) + uiService = ServiceUtils.getService(bundleContext, UIService.class); + return uiService; + } + + /** + * The dependent service is available and the bundle will start. + * @param dependentService the UIService this activator is waiting. + */ + @Override + public void start(Object dependentService) + { + if (logger.isDebugEnabled()) + logger.debug("Update checker [STARTED]"); + + ConfigurationService cfg = getConfiguration(); + + if (OSUtils.IS_WINDOWS) + { + updateService = new UpdateServiceImpl(); + + bundleContext.registerService( + UpdateService.class.getName(), + updateService, + null); + + // Register the "Check for Updates" menu item if + // the "Check for Updates" property isn't disabled. + if(!cfg.getBoolean(CHECK_FOR_UPDATES_MENU_DISABLED_PROP, false)) + { + // Register the "Check for Updates" menu item. + + Hashtable toolsMenuFilter + = new Hashtable(); + toolsMenuFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_HELP_MENU.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new PluginComponentFactory(Container.CONTAINER_HELP_MENU) + { + @Override + protected PluginComponent getPluginInstance() + { + return new CheckForUpdatesMenuItemComponent( + getContainer(), this); + } + }, + toolsMenuFilter); + } + + // Check for software update upon startup if enabled. + if(cfg.getBoolean(UPDATE_ENABLED, true)) + updateService.checkForUpdates(false); + } + + if (cfg.getBoolean(CHECK_FOR_UPDATES_DAILY_ENABLED_PROP, + false)) + { + logger.info("Scheduled update checking enabled"); + + // Schedule a "check for updates" task that will run once a day + int hoursToWait = calcHoursToWait(); + Runnable updateRunnable = new Runnable() + { + public void run() + { + logger.debug("Performing scheduled update check"); + getUpdateService().checkForUpdates(false); + } + }; + + mUpdateExecutor = Executors.newSingleThreadScheduledExecutor(); + mUpdateExecutor.scheduleAtFixedRate(updateRunnable, + hoursToWait, + 24*60*60, + TimeUnit.SECONDS); + } + + if (logger.isDebugEnabled()) + logger.debug("Update checker [REGISTERED]"); + } + + /** + * This activator depends on UIService. + * @return the class name of uiService. + */ + @Override + public Class getDependentServiceClass() + { + return UIService.class; + } + + /** + * Setting context to the activator, as soon as we have one. + * + * @param context the context to set. + */ + @Override + public void setBundleContext(BundleContext context) + { + bundleContext = context; + } + + /** + * Calculate the number of hour to wait until the first scheduled update + * check. This will only be called if daily checking for config updates + * is enabled + * + * @return The number of hours to wait + */ + private int calcHoursToWait() + { + // The hours to wait is the number of hours until midnight tonight (24 + // minus the current hour) plus the hour that the config says updates + // should be + return 24 - Calendar.getInstance().get(Calendar.HOUR_OF_DAY) + + configuration.getInt(CHECK_FOR_UPDATES_DAILY_TIME_PROP, 0); + } + + /** + * Stop the bundle. Nothing to stop for now. + * @param bundleContext BundleContext provided by OSGi framework + * @throws Exception if something goes wrong during stop + */ + public void stop(BundleContext bundleContext) throws Exception + { + if (logger.isDebugEnabled()) + logger.debug("Update checker [STOPPED]"); + + if (mUpdateExecutor != null) + { + mUpdateExecutor.shutdown(); + mUpdateExecutor = null; + } + } + + /** + * Returns the update service instance. + * + * @return the update service instance + */ + static UpdateService getUpdateService() + { + return updateService; + } +} diff --git a/src/net/java/sip/communicator/service/certificate/CertificateConfigEntry.java b/src/net/java/sip/communicator/service/certificate/CertificateConfigEntry.java index 4cbcd96..ff03b26 100644 --- a/src/net/java/sip/communicator/service/certificate/CertificateConfigEntry.java +++ b/src/net/java/sip/communicator/service/certificate/CertificateConfigEntry.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,172 +15,172 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.certificate; - -/** - * Data object for client certificate configuration entries. - * - * @author Ingo Bauersachs - */ -public class CertificateConfigEntry -{ - // ------------------------------------------------------------------------ - // Fields - // ------------------------------------------------------------------------ - private KeyStoreType keyStoreType; - private String keyStorePassword; - private String displayName; - private String alias; - private String id; - private String keyStore; - private boolean savePassword; - - // ------------------------------------------------------------------------ - // Properties - // ------------------------------------------------------------------------ - /** - * Sets the key store type. - * - * @param keyStoreType the new key store type - */ - public void setKeyStoreType(KeyStoreType keyStoreType) - { - this.keyStoreType = keyStoreType; - } - - /** - * Gets the key store type. - * - * @return the key store type - */ - public KeyStoreType getKeyStoreType() - { - return keyStoreType; - } - - /** - * Sets the key store password. - * - * @param keyStorePassword the new key store password - */ - public void setKeyStorePassword(String keyStorePassword) - { - this.keyStorePassword = keyStorePassword; - } - - /** - * Gets the key store password. - * - * @return the key store password - */ - public String getKeyStorePassword() - { - return keyStorePassword; - } - - /** - * Sets the display name. - * - * @param displayName the new display name - */ - public void setDisplayName(String displayName) - { - this.displayName = displayName; - } - - /** - * Gets the display name. - * - * @return the display name - */ - public String getDisplayName() - { - return displayName; - } - - /** - * Sets the alias. - * - * @param alias the new alias - */ - public void setAlias(String alias) - { - this.alias = alias; - } - - /** - * Gets the alias. - * - * @return the alias - */ - public String getAlias() - { - return alias; - } - - /** - * Sets the id. - * - * @param id the new id - */ - public void setId(String id) - { - this.id = id; - } - - /** - * Gets the id. - * - * @return the id - */ - public String getId() - { - return id; - } - - /** - * Sets the key store. - * - * @param keyStore the new key store - */ - public void setKeyStore(String keyStore) - { - this.keyStore = keyStore; - } - - /** - * Gets the key store. - * - * @return the key store - */ - public String getKeyStore() - { - return keyStore; - } - - /** - * Sets the save password. - * - * @param savePassword the new save password - */ - public void setSavePassword(boolean savePassword) - { - this.savePassword = savePassword; - } - - /** - * Checks if is save password. - * - * @return true, if is save password - */ - public boolean isSavePassword() - { - return savePassword; - } - - @Override - public String toString() - { - return displayName; - } -} +package net.java.sip.communicator.service.certificate; + +/** + * Data object for client certificate configuration entries. + * + * @author Ingo Bauersachs + */ +public class CertificateConfigEntry +{ + // ------------------------------------------------------------------------ + // Fields + // ------------------------------------------------------------------------ + private KeyStoreType keyStoreType; + private String keyStorePassword; + private String displayName; + private String alias; + private String id; + private String keyStore; + private boolean savePassword; + + // ------------------------------------------------------------------------ + // Properties + // ------------------------------------------------------------------------ + /** + * Sets the key store type. + * + * @param keyStoreType the new key store type + */ + public void setKeyStoreType(KeyStoreType keyStoreType) + { + this.keyStoreType = keyStoreType; + } + + /** + * Gets the key store type. + * + * @return the key store type + */ + public KeyStoreType getKeyStoreType() + { + return keyStoreType; + } + + /** + * Sets the key store password. + * + * @param keyStorePassword the new key store password + */ + public void setKeyStorePassword(String keyStorePassword) + { + this.keyStorePassword = keyStorePassword; + } + + /** + * Gets the key store password. + * + * @return the key store password + */ + public String getKeyStorePassword() + { + return keyStorePassword; + } + + /** + * Sets the display name. + * + * @param displayName the new display name + */ + public void setDisplayName(String displayName) + { + this.displayName = displayName; + } + + /** + * Gets the display name. + * + * @return the display name + */ + public String getDisplayName() + { + return displayName; + } + + /** + * Sets the alias. + * + * @param alias the new alias + */ + public void setAlias(String alias) + { + this.alias = alias; + } + + /** + * Gets the alias. + * + * @return the alias + */ + public String getAlias() + { + return alias; + } + + /** + * Sets the id. + * + * @param id the new id + */ + public void setId(String id) + { + this.id = id; + } + + /** + * Gets the id. + * + * @return the id + */ + public String getId() + { + return id; + } + + /** + * Sets the key store. + * + * @param keyStore the new key store + */ + public void setKeyStore(String keyStore) + { + this.keyStore = keyStore; + } + + /** + * Gets the key store. + * + * @return the key store + */ + public String getKeyStore() + { + return keyStore; + } + + /** + * Sets the save password. + * + * @param savePassword the new save password + */ + public void setSavePassword(boolean savePassword) + { + this.savePassword = savePassword; + } + + /** + * Checks if is save password. + * + * @return true, if is save password + */ + public boolean isSavePassword() + { + return savePassword; + } + + @Override + public String toString() + { + return displayName; + } +} diff --git a/src/net/java/sip/communicator/service/certificate/CertificateMatcher.java b/src/net/java/sip/communicator/service/certificate/CertificateMatcher.java index 365d9a9..a3baf8e 100644 --- a/src/net/java/sip/communicator/service/certificate/CertificateMatcher.java +++ b/src/net/java/sip/communicator/service/certificate/CertificateMatcher.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,24 +15,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.certificate; - -import java.security.cert.*; - -/** - * Interface to verify X.509 certificate - */ -public interface CertificateMatcher -{ - /** - * Implementations check whether one of the supplied identities is - * contained in the certificate. - * - * @param identitiesToTest The that are compared against the certificate. - * @param cert The X.509 certificate that was supplied by the server or - * client. - * @throws CertificateException When any certificate parsing fails. - */ - public void verify(Iterable identitiesToTest, X509Certificate cert) - throws CertificateException; -} +package net.java.sip.communicator.service.certificate; + +import java.security.cert.*; + +/** + * Interface to verify X.509 certificate + */ +public interface CertificateMatcher +{ + /** + * Implementations check whether one of the supplied identities is + * contained in the certificate. + * + * @param identitiesToTest The that are compared against the certificate. + * @param cert The X.509 certificate that was supplied by the server or + * client. + * @throws CertificateException When any certificate parsing fails. + */ + public void verify(Iterable identitiesToTest, X509Certificate cert) + throws CertificateException; +} diff --git a/src/net/java/sip/communicator/service/certificate/CertificateService.java b/src/net/java/sip/communicator/service/certificate/CertificateService.java index f77a3cc..bbe265b 100644 --- a/src/net/java/sip/communicator/service/certificate/CertificateService.java +++ b/src/net/java/sip/communicator/service/certificate/CertificateService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,266 +15,266 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.certificate; - -import java.security.*; -import java.security.cert.*; -import java.security.cert.Certificate; -import java.util.*; - -import javax.net.ssl.*; - -/** - * A service which implementors will ask the user for permission for the - * certificates which are for some reason not valid and not globally trusted. - * - * @author Damian Minkov - * @author Ingo Bauersachs - */ -public interface CertificateService -{ - // ------------------------------------------------------------------------ - // Configuration property names - // ------------------------------------------------------------------------ - /** - * Property for always trust mode. When enabled certificate check is - * skipped. - */ - public final static String PNAME_ALWAYS_TRUST = - "net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED"; - - /** - * When set to true, the certificate check is performed. If the check fails - * the user is not asked and the error is directly reported to the calling - * service. - */ - public final static String PNAME_NO_USER_INTERACTION = - "net.java.sip.communicator.service.tls.NO_USER_INTERACTION"; - - /** - * The property name prefix of all client authentication configurations. - */ - public static final String PNAME_CLIENTAUTH_CERTCONFIG_BASE = - "net.java.sip.communicator.service.cert.clientauth"; - - /** - * Property that is being applied to the system property - * javax.net.ssl.trustStoreType - */ - public static final String PNAME_TRUSTSTORE_TYPE = - "net.java.sip.communicator.service.cert.truststore.type"; - - /** - * Property that is being applied to the system property - * javax.net.ssl.trustStore - */ - public static final String PNAME_TRUSTSTORE_FILE = - "net.java.sip.communicator.service.cert.truststore.file"; - - /** - * Property that is being applied to the system property - * javax.net.ssl.trustStorePassword - */ - public static final String PNAME_TRUSTSTORE_PASSWORD = - "net.java.sip.communicator.service.cert.truststore.password"; - - /** - * Property that is being applied to the system properties - * com.sun.net.ssl.checkRevocation and - * com.sun.security.enableCRLDP - */ - public static final String PNAME_REVOCATION_CHECK_ENABLED = - "net.java.sip.communicator.service.cert.revocation.enabled"; - - /** - * Property that is being applied to the Security property - * ocsp.enable - */ - public static final String PNAME_OCSP_ENABLED = - "net.java.sip.communicator.service.cert.ocsp.enabled"; - - // ------------------------------------------------------------------------ - // constants - // ------------------------------------------------------------------------ - /** - * Result of user interaction. User does not trust this certificate. - */ - public final static int DO_NOT_TRUST = 0; - - /** - * Result of user interaction. User will always trust this certificate. - */ - public final static int TRUST_ALWAYS = 1; - - /** - * Result of user interaction. User will trust this certificate - * only for the current session. - */ - public final static int TRUST_THIS_SESSION_ONLY = 2; - - // ------------------------------------------------------------------------ - // Client authentication configuration - // ------------------------------------------------------------------------ - /** - * Returns all saved {@link CertificateConfigEntry}s. - * - * @return List of the saved authentication configurations. - */ - public List getClientAuthCertificateConfigs(); - - /** - * Deletes a saved {@link CertificateConfigEntry}. - * - * @param id The ID ({@link CertificateConfigEntry#getId()}) of the entry to - * delete. - */ - public void removeClientAuthCertificateConfig(String id); - - /** - * Saves or updates the passed {@link CertificateConfigEntry} to the config. - * If {@link CertificateConfigEntry#getId()} returns null, a new entry is - * created. - * - * @param entry The @see CertificateConfigEntry to save or update. - */ - public void setClientAuthCertificateConfig(CertificateConfigEntry entry); - - /** - * Gets a list of all supported KeyStore types. - * - * @return a list of all supported KeyStore types. - */ - public List getSupportedKeyStoreTypes(); - - // ------------------------------------------------------------------------ - // Certificate trust handling - // ------------------------------------------------------------------------ - /** - * Get an SSL Context that validates certificates based on the JRE default - * check and asks the user when the JRE check fails. - * - * CAUTION: Only the certificate itself is validated, no check is performed - * whether it is valid for a specific server or client. - * - * @return An SSL context based on a user confirming trust manager. - * @throws GeneralSecurityException - */ - public SSLContext getSSLContext() throws GeneralSecurityException; - - /** - * Get an SSL Context with the specified trustmanager. - * - * @param trustManager The trustmanager that will be used by the created - * SSLContext - * @return An SSL context based on the supplied trust manager. - * @throws GeneralSecurityException - */ - public SSLContext getSSLContext(X509TrustManager trustManager) - throws GeneralSecurityException; - - /** - * Get an SSL Context with the specified trustmanager. - * - * @param clientCertConfig The ID of a client certificate configuration - * entry that is to be used when the server asks for a client TLS - * certificate - * @param trustManager The trustmanager that will be used by the created - * SSLContext - * @return An SSL context based on the supplied trust manager. - * @throws GeneralSecurityException - */ - public SSLContext getSSLContext(String clientCertConfig, - X509TrustManager trustManager) - throws GeneralSecurityException; - - /** - * Get an SSL Context with the specified trustmanager. - * - * @param keyManagers The key manager(s) to be used for client - * authentication - * @param trustManager The trustmanager that will be used by the created - * SSLContext - * @return An SSL context based on the supplied trust manager. - * @throws GeneralSecurityException - */ - public SSLContext getSSLContext(KeyManager[] keyManagers, - X509TrustManager trustManager) - throws GeneralSecurityException; - - /** - * Creates a trustmanager that validates the certificate based on the JRE - * default check and asks the user when the JRE check fails. When - * null is passed as the identityToTest then no check is - * performed whether the certificate is valid for a specific server or - * client. The passed identities are checked by applying a behavior similar - * to the on regular browsers use. - * - * @param identitiesToTest when not null, the values are assumed - * to be hostnames for invocations of checkServerTrusted and - * e-mail addresses for invocations of checkClientTrusted - * @return TrustManager to use in an SSLContext - * @throws GeneralSecurityException - */ - public X509TrustManager getTrustManager(Iterable identitiesToTest) - throws GeneralSecurityException; - - /** - * @see #getTrustManager(Iterable) - * - * @param identityToTest when not null, the value is assumed to - * be a hostname for invocations of checkServerTrusted and an - * e-mail address for invocations of checkClientTrusted - * @return TrustManager to use in an SSLContext - * @throws GeneralSecurityException - */ - public X509TrustManager getTrustManager(String identityToTest) - throws GeneralSecurityException; - - /** - * @see #getTrustManager(Iterable, CertificateMatcher, CertificateMatcher) - * - * @param identityToTest The identity to match against the supplied - * verifiers. - * @param clientVerifier The verifier to use in calls to checkClientTrusted - * @param serverVerifier The verifier to use in calls to checkServerTrusted - * @return TrustManager to use in an SSLContext - * @throws GeneralSecurityException - */ - public X509TrustManager getTrustManager( - final String identityToTest, - final CertificateMatcher clientVerifier, - final CertificateMatcher serverVerifier) - throws GeneralSecurityException; - - /** - * Creates a trustmanager that validates the certificate based on the JRE - * default check and asks the user when the JRE check fails. When - * null is passed as the identityToTest then no check is - * performed whether the certificate is valid for a specific server or - * client. - * - * @param identitiesToTest The identities to match against the supplied - * verifiers. - * @param clientVerifier The verifier to use in calls to checkClientTrusted - * @param serverVerifier The verifier to use in calls to checkServerTrusted - * @return TrustManager to use in an SSLContext - * @throws GeneralSecurityException - */ - public X509TrustManager getTrustManager( - final Iterable identitiesToTest, - final CertificateMatcher clientVerifier, - final CertificateMatcher serverVerifier) - throws GeneralSecurityException; - - /** - * Adds a certificate to the local trust store. - * - * @param cert The certificate to add to the trust store. - * @param trustFor - * @param trustMode Whether to trust the certificate permanently or only - * for the current session. - * @throws CertificateException when the thumbprint could not be calculated - */ - public void addCertificateToTrust(Certificate cert, String trustFor, - int trustMode) throws CertificateException; +package net.java.sip.communicator.service.certificate; + +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.util.*; + +import javax.net.ssl.*; + +/** + * A service which implementors will ask the user for permission for the + * certificates which are for some reason not valid and not globally trusted. + * + * @author Damian Minkov + * @author Ingo Bauersachs + */ +public interface CertificateService +{ + // ------------------------------------------------------------------------ + // Configuration property names + // ------------------------------------------------------------------------ + /** + * Property for always trust mode. When enabled certificate check is + * skipped. + */ + public final static String PNAME_ALWAYS_TRUST = + "net.java.sip.communicator.service.gui.ALWAYS_TRUST_MODE_ENABLED"; + + /** + * When set to true, the certificate check is performed. If the check fails + * the user is not asked and the error is directly reported to the calling + * service. + */ + public final static String PNAME_NO_USER_INTERACTION = + "net.java.sip.communicator.service.tls.NO_USER_INTERACTION"; + + /** + * The property name prefix of all client authentication configurations. + */ + public static final String PNAME_CLIENTAUTH_CERTCONFIG_BASE = + "net.java.sip.communicator.service.cert.clientauth"; + + /** + * Property that is being applied to the system property + * javax.net.ssl.trustStoreType + */ + public static final String PNAME_TRUSTSTORE_TYPE = + "net.java.sip.communicator.service.cert.truststore.type"; + + /** + * Property that is being applied to the system property + * javax.net.ssl.trustStore + */ + public static final String PNAME_TRUSTSTORE_FILE = + "net.java.sip.communicator.service.cert.truststore.file"; + + /** + * Property that is being applied to the system property + * javax.net.ssl.trustStorePassword + */ + public static final String PNAME_TRUSTSTORE_PASSWORD = + "net.java.sip.communicator.service.cert.truststore.password"; + + /** + * Property that is being applied to the system properties + * com.sun.net.ssl.checkRevocation and + * com.sun.security.enableCRLDP + */ + public static final String PNAME_REVOCATION_CHECK_ENABLED = + "net.java.sip.communicator.service.cert.revocation.enabled"; + + /** + * Property that is being applied to the Security property + * ocsp.enable + */ + public static final String PNAME_OCSP_ENABLED = + "net.java.sip.communicator.service.cert.ocsp.enabled"; + + // ------------------------------------------------------------------------ + // constants + // ------------------------------------------------------------------------ + /** + * Result of user interaction. User does not trust this certificate. + */ + public final static int DO_NOT_TRUST = 0; + + /** + * Result of user interaction. User will always trust this certificate. + */ + public final static int TRUST_ALWAYS = 1; + + /** + * Result of user interaction. User will trust this certificate + * only for the current session. + */ + public final static int TRUST_THIS_SESSION_ONLY = 2; + + // ------------------------------------------------------------------------ + // Client authentication configuration + // ------------------------------------------------------------------------ + /** + * Returns all saved {@link CertificateConfigEntry}s. + * + * @return List of the saved authentication configurations. + */ + public List getClientAuthCertificateConfigs(); + + /** + * Deletes a saved {@link CertificateConfigEntry}. + * + * @param id The ID ({@link CertificateConfigEntry#getId()}) of the entry to + * delete. + */ + public void removeClientAuthCertificateConfig(String id); + + /** + * Saves or updates the passed {@link CertificateConfigEntry} to the config. + * If {@link CertificateConfigEntry#getId()} returns null, a new entry is + * created. + * + * @param entry The @see CertificateConfigEntry to save or update. + */ + public void setClientAuthCertificateConfig(CertificateConfigEntry entry); + + /** + * Gets a list of all supported KeyStore types. + * + * @return a list of all supported KeyStore types. + */ + public List getSupportedKeyStoreTypes(); + + // ------------------------------------------------------------------------ + // Certificate trust handling + // ------------------------------------------------------------------------ + /** + * Get an SSL Context that validates certificates based on the JRE default + * check and asks the user when the JRE check fails. + * + * CAUTION: Only the certificate itself is validated, no check is performed + * whether it is valid for a specific server or client. + * + * @return An SSL context based on a user confirming trust manager. + * @throws GeneralSecurityException + */ + public SSLContext getSSLContext() throws GeneralSecurityException; + + /** + * Get an SSL Context with the specified trustmanager. + * + * @param trustManager The trustmanager that will be used by the created + * SSLContext + * @return An SSL context based on the supplied trust manager. + * @throws GeneralSecurityException + */ + public SSLContext getSSLContext(X509TrustManager trustManager) + throws GeneralSecurityException; + + /** + * Get an SSL Context with the specified trustmanager. + * + * @param clientCertConfig The ID of a client certificate configuration + * entry that is to be used when the server asks for a client TLS + * certificate + * @param trustManager The trustmanager that will be used by the created + * SSLContext + * @return An SSL context based on the supplied trust manager. + * @throws GeneralSecurityException + */ + public SSLContext getSSLContext(String clientCertConfig, + X509TrustManager trustManager) + throws GeneralSecurityException; + + /** + * Get an SSL Context with the specified trustmanager. + * + * @param keyManagers The key manager(s) to be used for client + * authentication + * @param trustManager The trustmanager that will be used by the created + * SSLContext + * @return An SSL context based on the supplied trust manager. + * @throws GeneralSecurityException + */ + public SSLContext getSSLContext(KeyManager[] keyManagers, + X509TrustManager trustManager) + throws GeneralSecurityException; + + /** + * Creates a trustmanager that validates the certificate based on the JRE + * default check and asks the user when the JRE check fails. When + * null is passed as the identityToTest then no check is + * performed whether the certificate is valid for a specific server or + * client. The passed identities are checked by applying a behavior similar + * to the on regular browsers use. + * + * @param identitiesToTest when not null, the values are assumed + * to be hostnames for invocations of checkServerTrusted and + * e-mail addresses for invocations of checkClientTrusted + * @return TrustManager to use in an SSLContext + * @throws GeneralSecurityException + */ + public X509TrustManager getTrustManager(Iterable identitiesToTest) + throws GeneralSecurityException; + + /** + * @see #getTrustManager(Iterable) + * + * @param identityToTest when not null, the value is assumed to + * be a hostname for invocations of checkServerTrusted and an + * e-mail address for invocations of checkClientTrusted + * @return TrustManager to use in an SSLContext + * @throws GeneralSecurityException + */ + public X509TrustManager getTrustManager(String identityToTest) + throws GeneralSecurityException; + + /** + * @see #getTrustManager(Iterable, CertificateMatcher, CertificateMatcher) + * + * @param identityToTest The identity to match against the supplied + * verifiers. + * @param clientVerifier The verifier to use in calls to checkClientTrusted + * @param serverVerifier The verifier to use in calls to checkServerTrusted + * @return TrustManager to use in an SSLContext + * @throws GeneralSecurityException + */ + public X509TrustManager getTrustManager( + final String identityToTest, + final CertificateMatcher clientVerifier, + final CertificateMatcher serverVerifier) + throws GeneralSecurityException; + + /** + * Creates a trustmanager that validates the certificate based on the JRE + * default check and asks the user when the JRE check fails. When + * null is passed as the identityToTest then no check is + * performed whether the certificate is valid for a specific server or + * client. + * + * @param identitiesToTest The identities to match against the supplied + * verifiers. + * @param clientVerifier The verifier to use in calls to checkClientTrusted + * @param serverVerifier The verifier to use in calls to checkServerTrusted + * @return TrustManager to use in an SSLContext + * @throws GeneralSecurityException + */ + public X509TrustManager getTrustManager( + final Iterable identitiesToTest, + final CertificateMatcher clientVerifier, + final CertificateMatcher serverVerifier) + throws GeneralSecurityException; + + /** + * Adds a certificate to the local trust store. + * + * @param cert The certificate to add to the trust store. + * @param trustFor + * @param trustMode Whether to trust the certificate permanently or only + * for the current session. + * @throws CertificateException when the thumbprint could not be calculated + */ + public void addCertificateToTrust(Certificate cert, String trustFor, + int trustMode) throws CertificateException; } diff --git a/src/net/java/sip/communicator/service/certificate/KeyStoreType.java b/src/net/java/sip/communicator/service/certificate/KeyStoreType.java index ba1fd72..16927d8 100644 --- a/src/net/java/sip/communicator/service/certificate/KeyStoreType.java +++ b/src/net/java/sip/communicator/service/certificate/KeyStoreType.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,65 +15,65 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.certificate; - -/** - * Data object for KeyStore configurations. Primarily used during adding/ - * editing client certificate configurations. - * - * @author Ingo Bauersachs - */ -public class KeyStoreType -{ - private String name; - private String[] fileExtensions; - private boolean hasKeyStorePassword; - - /** - * Creates a new instance of this class. - * @param name the display name of the keystore type. - * @param fileExtensions known file name extensions (including the dot) - * @param hasKeyStorePassword - */ - public KeyStoreType(String name, String[] fileExtensions, - boolean hasKeyStorePassword) - { - this.name = name; - this.fileExtensions = fileExtensions; - this.hasKeyStorePassword = hasKeyStorePassword; - } - - @Override - public String toString() - { - return name; - } - - /** - * Gets the display name. - * @return the display name. - */ - public String getName() - { - return name; - } - - /** - * Gets the known file name extensions. - * @return Known file name extensions (including the dot). - */ - public String[] getFileExtensions() - { - return fileExtensions; - } - - /** - * Flag that indicates if the keystore supports passwords. - * @return true if the keystore supports passwords, false - * otherwise. - */ - public boolean hasKeyStorePassword() - { - return hasKeyStorePassword; - } +package net.java.sip.communicator.service.certificate; + +/** + * Data object for KeyStore configurations. Primarily used during adding/ + * editing client certificate configurations. + * + * @author Ingo Bauersachs + */ +public class KeyStoreType +{ + private String name; + private String[] fileExtensions; + private boolean hasKeyStorePassword; + + /** + * Creates a new instance of this class. + * @param name the display name of the keystore type. + * @param fileExtensions known file name extensions (including the dot) + * @param hasKeyStorePassword + */ + public KeyStoreType(String name, String[] fileExtensions, + boolean hasKeyStorePassword) + { + this.name = name; + this.fileExtensions = fileExtensions; + this.hasKeyStorePassword = hasKeyStorePassword; + } + + @Override + public String toString() + { + return name; + } + + /** + * Gets the display name. + * @return the display name. + */ + public String getName() + { + return name; + } + + /** + * Gets the known file name extensions. + * @return Known file name extensions (including the dot). + */ + public String[] getFileExtensions() + { + return fileExtensions; + } + + /** + * Flag that indicates if the keystore supports passwords. + * @return true if the keystore supports passwords, false + * otherwise. + */ + public boolean hasKeyStorePassword() + { + return hasKeyStorePassword; + } } diff --git a/src/net/java/sip/communicator/service/contactsource/AbstractContactQuery.java b/src/net/java/sip/communicator/service/contactsource/AbstractContactQuery.java index 2c14e52..be9de8a 100644 --- a/src/net/java/sip/communicator/service/contactsource/AbstractContactQuery.java +++ b/src/net/java/sip/communicator/service/contactsource/AbstractContactQuery.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,286 +15,286 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.contactsource; - -import java.util.*; - -/** - * Provides an abstract implementation of the basic functionality of - * ContactQuery and allows extenders to focus on the specifics of their - * implementation. - * - * @author Lyubomir Marinov - * @param the very type of ContactSourceService which performs the - * ContactQuery - */ -public abstract class AbstractContactQuery - implements ContactQuery -{ - /** - * The ContactSourceService which is performing this - * ContactQuery. - */ - private final T contactSource; - - /** - * The List of ContactQueryListeners which are to be - * notified by this ContactQuery about changes in its status, the - * receipt of new ContactSources via this ContactQuery, - * etc. - */ - private final List listeners - = new LinkedList(); - - /** - * The status of this ContactQuery which is one of the - * QUERY_XXX constants defined by the ContactQuery class. - */ - private int status = QUERY_IN_PROGRESS; - - /** - * Initializes a new AbstractContactQuery which is to be performed - * by a specific ContactSourceService. The status of the new - * instance is {@link ContactQuery#QUERY_IN_PROGRESS}. - * - * @param contactSource the ContactSourceService which is to - * perform the new AbstractContactQuery - */ - protected AbstractContactQuery(T contactSource) - { - this.contactSource = contactSource; - } - - /** - * Adds a ContactQueryListener to the list of listeners interested - * in notifications about this ContactQuery changing its status, - * the receipt of new SourceContacts via this - * ContactQuery, etc. - * - * @param l the ContactQueryListener to be added to the list of - * listeners interested in the notifications raised by this - * ContactQuery - * @see ContactQuery#addContactQueryListener(ContactQueryListener) - */ - public void addContactQueryListener(ContactQueryListener l) - { - if (l == null) - throw new NullPointerException("l"); - else - { - synchronized (listeners) - { - if (!listeners.contains(l)) - listeners.add(l); - } - } - } - - /** - * Cancels this ContactQuery. - * - * @see ContactQuery#cancel() - */ - public void cancel() - { - if (getStatus() == QUERY_IN_PROGRESS) - setStatus(QUERY_CANCELED); - } - - /** - * Notifies the ContactQueryListeners registered with this - * ContactQuery that a new SourceContact has been - * received. - * - * @param contact the SourceContact which has been received and - * which the registered ContactQueryListeners are to be notified - * about - * @param showMoreEnabled indicates whether show more label should be shown - * or not. - */ - protected void fireContactReceived(SourceContact contact, - boolean showMoreEnabled) - { - ContactQueryListener[] ls; - - synchronized (listeners) - { - ls = listeners.toArray(new ContactQueryListener[listeners.size()]); - } - - ContactReceivedEvent ev - = new ContactReceivedEvent(this, contact, showMoreEnabled); - - for (ContactQueryListener l : ls) - { - l.contactReceived(ev); - } - } - - /** - * Notifies the ContactQueryListeners registered with this - * ContactQuery that a new SourceContact has been - * received. - * - * @param contact the SourceContact which has been received and - * which the registered ContactQueryListeners are to be notified - * about - */ - protected void fireContactReceived(SourceContact contact) - { - fireContactReceived(contact, true); - } - - /** - * Notifies the ContactQueryListeners registered with this - * ContactQuery that a SourceContact has been - * removed. - * - * @param contact the SourceContact which has been removed and - * which the registered ContactQueryListeners are to be notified - * about - */ - protected void fireContactRemoved(SourceContact contact) - { - ContactQueryListener[] ls; - - synchronized (listeners) - { - ls = listeners.toArray(new ContactQueryListener[listeners.size()]); - } - - ContactRemovedEvent ev = new ContactRemovedEvent(this, contact); - - for (ContactQueryListener l : ls) - l.contactRemoved(ev); - } - - /** - * Notifies the ContactQueryListeners registered with this - * ContactQuery that a SourceContact has been - * changed. - * - * @param contact the SourceContact which has been changed and - * which the registered ContactQueryListeners are to be notified - * about - */ - protected void fireContactChanged(SourceContact contact) - { - ContactQueryListener[] ls; - - synchronized (listeners) - { - ls = listeners.toArray(new ContactQueryListener[listeners.size()]); - } - - ContactChangedEvent ev = new ContactChangedEvent(this, contact); - - for (ContactQueryListener l : ls) - l.contactChanged(ev); - } - - /** - * Notifies the ContactQueryListeners registered with this - * ContactQuery that its state has changed. - * - * @param eventType the type of the ContactQueryStatusEvent to be - * fired which can be one of the QUERY_XXX constants defined by - * ContactQueryStatusEvent - */ - protected void fireQueryStatusChanged(int eventType) - { - ContactQueryListener[] ls; - - synchronized (listeners) - { - ls = listeners.toArray(new ContactQueryListener[listeners.size()]); - } - - ContactQueryStatusEvent ev - = new ContactQueryStatusEvent(this, eventType); - - for (ContactQueryListener l : ls) - l.queryStatusChanged(ev); - } - - /** - * Gets the ContactSourceService which is performing this - * ContactQuery. - * - * @return the ContactSourceService which is performing this - * ContactQuery - * @see ContactQuery#getContactSource() - */ - public T getContactSource() - { - return contactSource; - } - - /** - * Gets the status of this ContactQuery which can be one of the - * QUERY_XXX constants defined by ContactQuery. - * - * @return the status of this ContactQuery which can be one of the - * QUERY_XXX constants defined by ContactQuery - * @see ContactQuery#getStatus() - */ - public int getStatus() - { - return status; - } - - /** - * Removes a ContactQueryListener from the list of listeners - * interested in notifications about this ContactQuery changing its - * status, the receipt of new SourceContacts via this - * ContactQuery, etc. - * - * @param l the ContactQueryListener to be removed from the list of - * listeners interested in notifications raised by this ContactQuery - * @see ContactQuery#removeContactQueryListener(ContactQueryListener) - */ - public void removeContactQueryListener(ContactQueryListener l) - { - if (l != null) - { - synchronized (listeners) - { - listeners.remove(l); - } - } - } - - /** - * Sets the status of this ContactQuery. - * - * @param status {@link ContactQuery#QUERY_CANCELED}, - * {@link ContactQuery#QUERY_COMPLETED}, or - * {@link ContactQuery#QUERY_ERROR} - */ - public void setStatus(int status) - { - if (this.status != status) - { - int eventType; - - switch (status) - { - case QUERY_CANCELED: - eventType = ContactQueryStatusEvent.QUERY_CANCELED; - break; - case QUERY_COMPLETED: - eventType = ContactQueryStatusEvent.QUERY_COMPLETED; - break; - case QUERY_ERROR: - eventType = ContactQueryStatusEvent.QUERY_ERROR; - break; - case QUERY_IN_PROGRESS: - default: - throw new IllegalArgumentException("status"); - } - - this.status = status; - fireQueryStatusChanged(eventType); - } - } -} +package net.java.sip.communicator.service.contactsource; + +import java.util.*; + +/** + * Provides an abstract implementation of the basic functionality of + * ContactQuery and allows extenders to focus on the specifics of their + * implementation. + * + * @author Lyubomir Marinov + * @param the very type of ContactSourceService which performs the + * ContactQuery + */ +public abstract class AbstractContactQuery + implements ContactQuery +{ + /** + * The ContactSourceService which is performing this + * ContactQuery. + */ + private final T contactSource; + + /** + * The List of ContactQueryListeners which are to be + * notified by this ContactQuery about changes in its status, the + * receipt of new ContactSources via this ContactQuery, + * etc. + */ + private final List listeners + = new LinkedList(); + + /** + * The status of this ContactQuery which is one of the + * QUERY_XXX constants defined by the ContactQuery class. + */ + private int status = QUERY_IN_PROGRESS; + + /** + * Initializes a new AbstractContactQuery which is to be performed + * by a specific ContactSourceService. The status of the new + * instance is {@link ContactQuery#QUERY_IN_PROGRESS}. + * + * @param contactSource the ContactSourceService which is to + * perform the new AbstractContactQuery + */ + protected AbstractContactQuery(T contactSource) + { + this.contactSource = contactSource; + } + + /** + * Adds a ContactQueryListener to the list of listeners interested + * in notifications about this ContactQuery changing its status, + * the receipt of new SourceContacts via this + * ContactQuery, etc. + * + * @param l the ContactQueryListener to be added to the list of + * listeners interested in the notifications raised by this + * ContactQuery + * @see ContactQuery#addContactQueryListener(ContactQueryListener) + */ + public void addContactQueryListener(ContactQueryListener l) + { + if (l == null) + throw new NullPointerException("l"); + else + { + synchronized (listeners) + { + if (!listeners.contains(l)) + listeners.add(l); + } + } + } + + /** + * Cancels this ContactQuery. + * + * @see ContactQuery#cancel() + */ + public void cancel() + { + if (getStatus() == QUERY_IN_PROGRESS) + setStatus(QUERY_CANCELED); + } + + /** + * Notifies the ContactQueryListeners registered with this + * ContactQuery that a new SourceContact has been + * received. + * + * @param contact the SourceContact which has been received and + * which the registered ContactQueryListeners are to be notified + * about + * @param showMoreEnabled indicates whether show more label should be shown + * or not. + */ + protected void fireContactReceived(SourceContact contact, + boolean showMoreEnabled) + { + ContactQueryListener[] ls; + + synchronized (listeners) + { + ls = listeners.toArray(new ContactQueryListener[listeners.size()]); + } + + ContactReceivedEvent ev + = new ContactReceivedEvent(this, contact, showMoreEnabled); + + for (ContactQueryListener l : ls) + { + l.contactReceived(ev); + } + } + + /** + * Notifies the ContactQueryListeners registered with this + * ContactQuery that a new SourceContact has been + * received. + * + * @param contact the SourceContact which has been received and + * which the registered ContactQueryListeners are to be notified + * about + */ + protected void fireContactReceived(SourceContact contact) + { + fireContactReceived(contact, true); + } + + /** + * Notifies the ContactQueryListeners registered with this + * ContactQuery that a SourceContact has been + * removed. + * + * @param contact the SourceContact which has been removed and + * which the registered ContactQueryListeners are to be notified + * about + */ + protected void fireContactRemoved(SourceContact contact) + { + ContactQueryListener[] ls; + + synchronized (listeners) + { + ls = listeners.toArray(new ContactQueryListener[listeners.size()]); + } + + ContactRemovedEvent ev = new ContactRemovedEvent(this, contact); + + for (ContactQueryListener l : ls) + l.contactRemoved(ev); + } + + /** + * Notifies the ContactQueryListeners registered with this + * ContactQuery that a SourceContact has been + * changed. + * + * @param contact the SourceContact which has been changed and + * which the registered ContactQueryListeners are to be notified + * about + */ + protected void fireContactChanged(SourceContact contact) + { + ContactQueryListener[] ls; + + synchronized (listeners) + { + ls = listeners.toArray(new ContactQueryListener[listeners.size()]); + } + + ContactChangedEvent ev = new ContactChangedEvent(this, contact); + + for (ContactQueryListener l : ls) + l.contactChanged(ev); + } + + /** + * Notifies the ContactQueryListeners registered with this + * ContactQuery that its state has changed. + * + * @param eventType the type of the ContactQueryStatusEvent to be + * fired which can be one of the QUERY_XXX constants defined by + * ContactQueryStatusEvent + */ + protected void fireQueryStatusChanged(int eventType) + { + ContactQueryListener[] ls; + + synchronized (listeners) + { + ls = listeners.toArray(new ContactQueryListener[listeners.size()]); + } + + ContactQueryStatusEvent ev + = new ContactQueryStatusEvent(this, eventType); + + for (ContactQueryListener l : ls) + l.queryStatusChanged(ev); + } + + /** + * Gets the ContactSourceService which is performing this + * ContactQuery. + * + * @return the ContactSourceService which is performing this + * ContactQuery + * @see ContactQuery#getContactSource() + */ + public T getContactSource() + { + return contactSource; + } + + /** + * Gets the status of this ContactQuery which can be one of the + * QUERY_XXX constants defined by ContactQuery. + * + * @return the status of this ContactQuery which can be one of the + * QUERY_XXX constants defined by ContactQuery + * @see ContactQuery#getStatus() + */ + public int getStatus() + { + return status; + } + + /** + * Removes a ContactQueryListener from the list of listeners + * interested in notifications about this ContactQuery changing its + * status, the receipt of new SourceContacts via this + * ContactQuery, etc. + * + * @param l the ContactQueryListener to be removed from the list of + * listeners interested in notifications raised by this ContactQuery + * @see ContactQuery#removeContactQueryListener(ContactQueryListener) + */ + public void removeContactQueryListener(ContactQueryListener l) + { + if (l != null) + { + synchronized (listeners) + { + listeners.remove(l); + } + } + } + + /** + * Sets the status of this ContactQuery. + * + * @param status {@link ContactQuery#QUERY_CANCELED}, + * {@link ContactQuery#QUERY_COMPLETED}, or + * {@link ContactQuery#QUERY_ERROR} + */ + public void setStatus(int status) + { + if (this.status != status) + { + int eventType; + + switch (status) + { + case QUERY_CANCELED: + eventType = ContactQueryStatusEvent.QUERY_CANCELED; + break; + case QUERY_COMPLETED: + eventType = ContactQueryStatusEvent.QUERY_COMPLETED; + break; + case QUERY_ERROR: + eventType = ContactQueryStatusEvent.QUERY_ERROR; + break; + case QUERY_IN_PROGRESS: + default: + throw new IllegalArgumentException("status"); + } + + this.status = status; + fireQueryStatusChanged(eventType); + } + } +} diff --git a/src/net/java/sip/communicator/service/contactsource/AsyncContactQuery.java b/src/net/java/sip/communicator/service/contactsource/AsyncContactQuery.java index 1eb38f8..9570dad 100644 --- a/src/net/java/sip/communicator/service/contactsource/AsyncContactQuery.java +++ b/src/net/java/sip/communicator/service/contactsource/AsyncContactQuery.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,410 +15,410 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.contactsource; - -import java.util.*; -import java.util.regex.*; - -/** - * Provides an abstract implementation of a ContactQuery which runs in - * a separate Thread. - * - * @author Lyubomir Marinov - * @param the very type of ContactSourceService which performs the - * ContactQuery - */ -public abstract class AsyncContactQuery - extends AbstractContactQuery -{ - /** - * The {@link #query} in the form of a String telephone number if - * such parsing, formatting and validation is possible; otherwise, - * null. - */ - private String phoneNumberQuery; - - /** - * The Pattern for which the associated - * ContactSourceService is being queried. - */ - protected final Pattern query; - - /** - * The indicator which determines whether there has been an attempt to - * convert {@link #query} to {@link #phoneNumberQuery}. If the conversion has - * been successful, phoneNumberQuery will be non-null. - */ - private boolean queryIsConvertedToPhoneNumber; - - /** - * The SourceContacts which match {@link #query}. - */ - private Collection queryResults - = new LinkedList(); - - /** - * The Thread in which this AsyncContactQuery is - * performing {@link #query}. - */ - private Thread thread; - - /** - * Initializes a new AsyncContactQuery instance which is to perform - * a specific query on behalf of a specific contactSource. - * - * @param contactSource the ContactSourceService which is to - * perform the new ContactQuery instance - * @param query the Pattern for which contactSource is - * being queried - * @param isSorted indicates if the results of this query should be sorted - */ - protected AsyncContactQuery(T contactSource, - Pattern query, - boolean isSorted) - { - super(contactSource); - - this.query = query; - - if (isSorted) - queryResults = new TreeSet(); - } - - /** - * Initializes a new AsyncContactQuery instance which is to perform - * a specific query on behalf of a specific contactSource. - * - * @param contactSource the ContactSourceService which is to - * perform the new ContactQuery instance - * @param query the Pattern for which contactSource is - * being queried - */ - protected AsyncContactQuery(T contactSource, Pattern query) - { - super(contactSource); - - this.query = query; - } - - /** - * Adds a specific SourceContact to the list of - * SourceContacts to be returned by this ContactQuery in - * response to {@link #getQueryResults()}. - * - * @param sourceContact the SourceContact to be added to the - * queryResults of this ContactQuery - * @param showMoreEnabled indicates whether show more label should be shown - * or not. - * @return true if the queryResults of this - * ContactQuery has changed in response to the call - */ - protected boolean addQueryResult(SourceContact sourceContact, - boolean showMoreEnabled) - { - boolean changed; - - synchronized (queryResults) - { - changed = queryResults.add(sourceContact); - } - if (changed) - fireContactReceived(sourceContact, showMoreEnabled); - - return changed; - } - - /** - * Adds a specific SourceContact to the list of - * SourceContacts to be returned by this ContactQuery in - * response to {@link #getQueryResults()}. - * - * @param sourceContact the SourceContact to be added to the - * queryResults of this ContactQuery - * @return true if the queryResults of this - * ContactQuery has changed in response to the call - */ - protected boolean addQueryResult(SourceContact sourceContact) - { - boolean changed; - - synchronized (queryResults) - { - changed = queryResults.add(sourceContact); - } - if (changed) - fireContactReceived(sourceContact); - - return changed; - } - - /** - * Removes a specific SourceContact from the list of - * SourceContacts. - * - * @param sourceContact the SourceContact to be removed from the - * queryResults of this ContactQuery - * @return true if the queryResults of this - * ContactQuery has changed in response to the call - */ - protected boolean removeQueryResult(SourceContact sourceContact) - { - boolean changed; - - synchronized (queryResults) - { - changed = queryResults.remove(sourceContact); - } - if (changed) - fireContactRemoved(sourceContact); - - return changed; - } - - /** - * Adds a set of SourceContact instances to the list of - * SourceContacts to be returned by this ContactQuery in - * response to {@link #getQueryResults()}. - * - * @param sourceContacts the set of SourceContact to be added to - * the queryResults of this ContactQuery - * @return true if the queryResults of this - * ContactQuery has changed in response to the call - */ - protected boolean addQueryResults( - final Set sourceContacts) - { - final boolean changed; - - synchronized (queryResults) - { - changed = queryResults.addAll(sourceContacts); - } - - if (changed) - { - // TODO Need something to fire one event for multiple contacts. - for (SourceContact contact : sourceContacts) - { - fireContactReceived(contact, false); - } - } - - return changed; - } - - - /** - * Gets the {@link #query} of this AsyncContactQuery as a - * String which represents a phone number (if possible). - * - * @return a String which represents the query of this - * AsyncContactQuery as a phone number if such parsing, formatting - * and validation is possible; otherwise, null - */ - protected String getPhoneNumberQuery() - { - if ((phoneNumberQuery == null) && !queryIsConvertedToPhoneNumber) - { - try - { - String pattern = query.pattern(); - - if (pattern != null) - { - int patternLength = pattern.length(); - - if ((patternLength > 2) - && (pattern.charAt(0) == '^') - && (pattern.charAt(patternLength - 1) == '$')) - { - phoneNumberQuery - = pattern.substring(1, patternLength - 1); - } - else if ((patternLength > 4) - && (pattern.charAt(0) == '\\') - && (pattern.charAt(1) == 'Q') - && (pattern.charAt(patternLength - 2) == '\\') - && (pattern.charAt(patternLength - 1) == 'E')) - { - phoneNumberQuery - = pattern.substring(2, patternLength - 2); - } - - } - } - finally - { - queryIsConvertedToPhoneNumber = true; - } - } - return phoneNumberQuery; - } - - /** - * Gets the number of SourceContacts which match this - * ContactQuery. - * - * @return the number of SourceContact which match this - * ContactQuery - */ - public int getQueryResultCount() - { - synchronized (queryResults) - { - return queryResults.size(); - } - } - - /** - * Gets the List of SourceContacts which match this - * ContactQuery. - * - * @return the List of SourceContacts which match this - * ContactQuery - * @see ContactQuery#getQueryResults() - */ - public List getQueryResults() - { - List qr; - - synchronized (queryResults) - { - qr = new ArrayList(queryResults.size()); - qr.addAll(queryResults); - } - return qr; - } - - /** - * Returns the query string, this query was created for. - * - * @return the query string, this query was created for - */ - public String getQueryString() - { - return query.toString(); - } - - /** - * Performs this ContactQuery in a background Thread. - */ - protected abstract void run(); - - /** - * Starts this AsyncContactQuery. - */ - public synchronized void start() - { - if (thread == null) - { - thread - = new Thread() - { - @Override - public void run() - { - boolean completed = false; - - try - { - AsyncContactQuery.this.run(); - completed = true; - } - finally - { - synchronized (AsyncContactQuery.this) - { - if (thread == Thread.currentThread()) - stopped(completed); - } - } - } - }; - thread.setDaemon(true); - thread.start(); - } - else - throw new IllegalStateException("thread"); - } - - /** - * Notifies this AsyncContactQuery that it has stopped performing - * in the associated background Thread. - * - * @param completed true if this ContactQuery has - * successfully completed, false if an error has been encountered - * during its execution - */ - protected void stopped(boolean completed) - { - if (getStatus() == QUERY_IN_PROGRESS) - setStatus(completed ? QUERY_COMPLETED : QUERY_ERROR); - } - - /** - * Determines whether a specific String phone number matches the - * {@link #query} of this AsyncContactQuery. - * - * @param phoneNumber the String which represents the phone number - * to match to the query of this AsyncContactQuery - * @return true if the specified phoneNumber matches the - * query of this AsyncContactQuery; otherwise, - * false - */ - protected boolean phoneNumberMatches(String phoneNumber) - { - /* - * PhoneNumberI18nService implements functionality to aid the parsing, - * formatting and validation of international phone numbers so attempt - * to use it to determine whether the specified phoneNumber matches the - * query. For example, check whether the normalized phoneNumber matches - * the query. - */ - - boolean phoneNumberMatches = false; - - if (query - .matcher(ContactSourceActivator.getPhoneNumberI18nService() - .normalize(phoneNumber)).find()) - { - phoneNumberMatches = true; - } - else - { - /* - * The fact that the normalized form of the phoneNumber doesn't - * match the query doesn't mean that, for example, it doesn't - * match the normalized form of the query. The latter, though, - * requires the query to look like a phone number as well. In - * order to not accidentally start matching all queries to phone - * numbers, it seems justified to normalize the query only when - * it is a phone number, not whenever it looks like a piece of a - * phone number. - */ - - String phoneNumberQuery = getPhoneNumberQuery(); - - if ((phoneNumberQuery != null) - && (phoneNumberQuery.length() != 0)) - { - try - { - phoneNumberMatches - = ContactSourceActivator.getPhoneNumberI18nService() - .phoneNumbersMatch( - phoneNumberQuery, - phoneNumber); - } - catch (IllegalArgumentException iaex) - { - /* - * Ignore it, phoneNumberMatches will remain equal to - * false. - */ - } - } - } - return phoneNumberMatches; - } -} +package net.java.sip.communicator.service.contactsource; + +import java.util.*; +import java.util.regex.*; + +/** + * Provides an abstract implementation of a ContactQuery which runs in + * a separate Thread. + * + * @author Lyubomir Marinov + * @param the very type of ContactSourceService which performs the + * ContactQuery + */ +public abstract class AsyncContactQuery + extends AbstractContactQuery +{ + /** + * The {@link #query} in the form of a String telephone number if + * such parsing, formatting and validation is possible; otherwise, + * null. + */ + private String phoneNumberQuery; + + /** + * The Pattern for which the associated + * ContactSourceService is being queried. + */ + protected final Pattern query; + + /** + * The indicator which determines whether there has been an attempt to + * convert {@link #query} to {@link #phoneNumberQuery}. If the conversion has + * been successful, phoneNumberQuery will be non-null. + */ + private boolean queryIsConvertedToPhoneNumber; + + /** + * The SourceContacts which match {@link #query}. + */ + private Collection queryResults + = new LinkedList(); + + /** + * The Thread in which this AsyncContactQuery is + * performing {@link #query}. + */ + private Thread thread; + + /** + * Initializes a new AsyncContactQuery instance which is to perform + * a specific query on behalf of a specific contactSource. + * + * @param contactSource the ContactSourceService which is to + * perform the new ContactQuery instance + * @param query the Pattern for which contactSource is + * being queried + * @param isSorted indicates if the results of this query should be sorted + */ + protected AsyncContactQuery(T contactSource, + Pattern query, + boolean isSorted) + { + super(contactSource); + + this.query = query; + + if (isSorted) + queryResults = new TreeSet(); + } + + /** + * Initializes a new AsyncContactQuery instance which is to perform + * a specific query on behalf of a specific contactSource. + * + * @param contactSource the ContactSourceService which is to + * perform the new ContactQuery instance + * @param query the Pattern for which contactSource is + * being queried + */ + protected AsyncContactQuery(T contactSource, Pattern query) + { + super(contactSource); + + this.query = query; + } + + /** + * Adds a specific SourceContact to the list of + * SourceContacts to be returned by this ContactQuery in + * response to {@link #getQueryResults()}. + * + * @param sourceContact the SourceContact to be added to the + * queryResults of this ContactQuery + * @param showMoreEnabled indicates whether show more label should be shown + * or not. + * @return true if the queryResults of this + * ContactQuery has changed in response to the call + */ + protected boolean addQueryResult(SourceContact sourceContact, + boolean showMoreEnabled) + { + boolean changed; + + synchronized (queryResults) + { + changed = queryResults.add(sourceContact); + } + if (changed) + fireContactReceived(sourceContact, showMoreEnabled); + + return changed; + } + + /** + * Adds a specific SourceContact to the list of + * SourceContacts to be returned by this ContactQuery in + * response to {@link #getQueryResults()}. + * + * @param sourceContact the SourceContact to be added to the + * queryResults of this ContactQuery + * @return true if the queryResults of this + * ContactQuery has changed in response to the call + */ + protected boolean addQueryResult(SourceContact sourceContact) + { + boolean changed; + + synchronized (queryResults) + { + changed = queryResults.add(sourceContact); + } + if (changed) + fireContactReceived(sourceContact); + + return changed; + } + + /** + * Removes a specific SourceContact from the list of + * SourceContacts. + * + * @param sourceContact the SourceContact to be removed from the + * queryResults of this ContactQuery + * @return true if the queryResults of this + * ContactQuery has changed in response to the call + */ + protected boolean removeQueryResult(SourceContact sourceContact) + { + boolean changed; + + synchronized (queryResults) + { + changed = queryResults.remove(sourceContact); + } + if (changed) + fireContactRemoved(sourceContact); + + return changed; + } + + /** + * Adds a set of SourceContact instances to the list of + * SourceContacts to be returned by this ContactQuery in + * response to {@link #getQueryResults()}. + * + * @param sourceContacts the set of SourceContact to be added to + * the queryResults of this ContactQuery + * @return true if the queryResults of this + * ContactQuery has changed in response to the call + */ + protected boolean addQueryResults( + final Set sourceContacts) + { + final boolean changed; + + synchronized (queryResults) + { + changed = queryResults.addAll(sourceContacts); + } + + if (changed) + { + // TODO Need something to fire one event for multiple contacts. + for (SourceContact contact : sourceContacts) + { + fireContactReceived(contact, false); + } + } + + return changed; + } + + + /** + * Gets the {@link #query} of this AsyncContactQuery as a + * String which represents a phone number (if possible). + * + * @return a String which represents the query of this + * AsyncContactQuery as a phone number if such parsing, formatting + * and validation is possible; otherwise, null + */ + protected String getPhoneNumberQuery() + { + if ((phoneNumberQuery == null) && !queryIsConvertedToPhoneNumber) + { + try + { + String pattern = query.pattern(); + + if (pattern != null) + { + int patternLength = pattern.length(); + + if ((patternLength > 2) + && (pattern.charAt(0) == '^') + && (pattern.charAt(patternLength - 1) == '$')) + { + phoneNumberQuery + = pattern.substring(1, patternLength - 1); + } + else if ((patternLength > 4) + && (pattern.charAt(0) == '\\') + && (pattern.charAt(1) == 'Q') + && (pattern.charAt(patternLength - 2) == '\\') + && (pattern.charAt(patternLength - 1) == 'E')) + { + phoneNumberQuery + = pattern.substring(2, patternLength - 2); + } + + } + } + finally + { + queryIsConvertedToPhoneNumber = true; + } + } + return phoneNumberQuery; + } + + /** + * Gets the number of SourceContacts which match this + * ContactQuery. + * + * @return the number of SourceContact which match this + * ContactQuery + */ + public int getQueryResultCount() + { + synchronized (queryResults) + { + return queryResults.size(); + } + } + + /** + * Gets the List of SourceContacts which match this + * ContactQuery. + * + * @return the List of SourceContacts which match this + * ContactQuery + * @see ContactQuery#getQueryResults() + */ + public List getQueryResults() + { + List qr; + + synchronized (queryResults) + { + qr = new ArrayList(queryResults.size()); + qr.addAll(queryResults); + } + return qr; + } + + /** + * Returns the query string, this query was created for. + * + * @return the query string, this query was created for + */ + public String getQueryString() + { + return query.toString(); + } + + /** + * Performs this ContactQuery in a background Thread. + */ + protected abstract void run(); + + /** + * Starts this AsyncContactQuery. + */ + public synchronized void start() + { + if (thread == null) + { + thread + = new Thread() + { + @Override + public void run() + { + boolean completed = false; + + try + { + AsyncContactQuery.this.run(); + completed = true; + } + finally + { + synchronized (AsyncContactQuery.this) + { + if (thread == Thread.currentThread()) + stopped(completed); + } + } + } + }; + thread.setDaemon(true); + thread.start(); + } + else + throw new IllegalStateException("thread"); + } + + /** + * Notifies this AsyncContactQuery that it has stopped performing + * in the associated background Thread. + * + * @param completed true if this ContactQuery has + * successfully completed, false if an error has been encountered + * during its execution + */ + protected void stopped(boolean completed) + { + if (getStatus() == QUERY_IN_PROGRESS) + setStatus(completed ? QUERY_COMPLETED : QUERY_ERROR); + } + + /** + * Determines whether a specific String phone number matches the + * {@link #query} of this AsyncContactQuery. + * + * @param phoneNumber the String which represents the phone number + * to match to the query of this AsyncContactQuery + * @return true if the specified phoneNumber matches the + * query of this AsyncContactQuery; otherwise, + * false + */ + protected boolean phoneNumberMatches(String phoneNumber) + { + /* + * PhoneNumberI18nService implements functionality to aid the parsing, + * formatting and validation of international phone numbers so attempt + * to use it to determine whether the specified phoneNumber matches the + * query. For example, check whether the normalized phoneNumber matches + * the query. + */ + + boolean phoneNumberMatches = false; + + if (query + .matcher(ContactSourceActivator.getPhoneNumberI18nService() + .normalize(phoneNumber)).find()) + { + phoneNumberMatches = true; + } + else + { + /* + * The fact that the normalized form of the phoneNumber doesn't + * match the query doesn't mean that, for example, it doesn't + * match the normalized form of the query. The latter, though, + * requires the query to look like a phone number as well. In + * order to not accidentally start matching all queries to phone + * numbers, it seems justified to normalize the query only when + * it is a phone number, not whenever it looks like a piece of a + * phone number. + */ + + String phoneNumberQuery = getPhoneNumberQuery(); + + if ((phoneNumberQuery != null) + && (phoneNumberQuery.length() != 0)) + { + try + { + phoneNumberMatches + = ContactSourceActivator.getPhoneNumberI18nService() + .phoneNumbersMatch( + phoneNumberQuery, + phoneNumber); + } + catch (IllegalArgumentException iaex) + { + /* + * Ignore it, phoneNumberMatches will remain equal to + * false. + */ + } + } + } + return phoneNumberMatches; + } +} diff --git a/src/net/java/sip/communicator/service/contactsource/AsyncContactSourceService.java b/src/net/java/sip/communicator/service/contactsource/AsyncContactSourceService.java index 848a723..14d06a4 100644 --- a/src/net/java/sip/communicator/service/contactsource/AsyncContactSourceService.java +++ b/src/net/java/sip/communicator/service/contactsource/AsyncContactSourceService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,70 +15,70 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.contactsource; - -import java.util.regex.*; - -/** - * Declares the interface of a ContactSourceService which performs - * ContactQuerys in a separate Thread. - * - * @author Lyubomir Marinov - */ -public abstract class AsyncContactSourceService - implements ExtendedContactSourceService -{ - /** - * Creates query that searches for SourceContacts - * which match a specific query String. - * - * @param query the String which this ContactSourceService - * is being queried for - * @return a ContactQuery which represents the query of this - * ContactSourceService implementation for the specified - * String and via which the matching SourceContacts (if - * any) will be returned - * @see ContactSourceService#queryContactSource(String) - */ - public ContactQuery createContactQuery(String query) - { - return createContactQuery( - Pattern.compile(query, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)); - } - - /** - * Creates query that searches for SourceContacts - * which match a specific query String. - * - * @param query the String which this ContactSourceService - * is being queried for - * @param contactCount the maximum count of result contacts - * @return a ContactQuery which represents the query of this - * ContactSourceService implementation for the specified - * String and via which the matching SourceContacts (if - * any) will be returned - * @see ContactSourceService#queryContactSource(String) - */ - public ContactQuery createContactQuery(String query, int contactCount) - { - return createContactQuery( - Pattern.compile(query, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)); - } - - /** - * Stops this ContactSourceService. - */ - public abstract void stop(); - - /** - * Defines whether using this contact source service (Outlook or MacOSX - * Contacs) can be used as result for the search field. This is - * useful when an external plugin looks for result of this contact source - * service, but want to display the search field result from its own (avoid - * duplicate results). - * - * @return True if this contact source service can be used to perform search - * for contacts. False otherwise. - */ - public abstract boolean canBeUsedToSearchContacts(); -} +package net.java.sip.communicator.service.contactsource; + +import java.util.regex.*; + +/** + * Declares the interface of a ContactSourceService which performs + * ContactQuerys in a separate Thread. + * + * @author Lyubomir Marinov + */ +public abstract class AsyncContactSourceService + implements ExtendedContactSourceService +{ + /** + * Creates query that searches for SourceContacts + * which match a specific query String. + * + * @param query the String which this ContactSourceService + * is being queried for + * @return a ContactQuery which represents the query of this + * ContactSourceService implementation for the specified + * String and via which the matching SourceContacts (if + * any) will be returned + * @see ContactSourceService#queryContactSource(String) + */ + public ContactQuery createContactQuery(String query) + { + return createContactQuery( + Pattern.compile(query, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)); + } + + /** + * Creates query that searches for SourceContacts + * which match a specific query String. + * + * @param query the String which this ContactSourceService + * is being queried for + * @param contactCount the maximum count of result contacts + * @return a ContactQuery which represents the query of this + * ContactSourceService implementation for the specified + * String and via which the matching SourceContacts (if + * any) will be returned + * @see ContactSourceService#queryContactSource(String) + */ + public ContactQuery createContactQuery(String query, int contactCount) + { + return createContactQuery( + Pattern.compile(query, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)); + } + + /** + * Stops this ContactSourceService. + */ + public abstract void stop(); + + /** + * Defines whether using this contact source service (Outlook or MacOSX + * Contacs) can be used as result for the search field. This is + * useful when an external plugin looks for result of this contact source + * service, but want to display the search field result from its own (avoid + * duplicate results). + * + * @return True if this contact source service can be used to perform search + * for contacts. False otherwise. + */ + public abstract boolean canBeUsedToSearchContacts(); +} diff --git a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java index a77adee..0c0cb0d 100644 --- a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java +++ b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,295 +15,295 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.contactsource; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Implements a generic SourceContact for the purposes of the support - * for the OS-specific Address Book. - * - * @author Lyubomir Marinov - */ -public class GenericSourceContact - extends DataObject - implements SourceContact -{ - /** - * The ContactDetails of this SourceContact. - */ - protected final List contactDetails; - - /** - * The ContactSourceService which has created this - * SourceContact. - */ - private final ContactSourceService contactSource; - - /** - * The display name of this SourceContact. - */ - private String displayName; - - /** - * The display details of this contact. - */ - private String displayDetails; - - /** - * The presence status of this contact. - */ - private PresenceStatus presenceStatus; - - /** - * The image/avatar of this SourceContact - */ - private byte[] image; - - /** - * The address of the contact. - */ - private String contactAddress = null; - - /** - * Initializes a new AddrBookSourceContact instance. - * - * @param contactSource the ContactSourceService which is creating - * the new instance - * @param displayName the display name of the new instance - * @param contactDetails the ContactDetails of the new instance - */ - public GenericSourceContact( - ContactSourceService contactSource, - String displayName, - List contactDetails) - { - this.contactSource = contactSource; - this.displayName = displayName; - this.contactDetails = contactDetails; - } - - /** - * Returns the address of the contact. - * - * @return the contact address. - */ - public String getContactAddress() - { - return contactAddress; - } - - /** - * Gets the ContactDetails of this SourceContact. - * - * @return the ContactDetails of this SourceContact - * @see SourceContact#getContactDetails() - */ - public List getContactDetails() - { - return Collections.unmodifiableList(contactDetails); - } - - /** - * Gets the ContactDetails of this SourceContact which - * support a specific OperationSet. - * - * @param operationSet the OperationSet the supporting - * ContactDetails of which are to be returned - * @return the ContactDetails of this SourceContact which - * support the specified operationSet - * @see SourceContact#getContactDetails(Class) - */ - public List getContactDetails( - Class operationSet) - { - List contactDetails = new LinkedList(); - - for (ContactDetail contactDetail : getContactDetails()) - { - List> supportedOperationSets - = contactDetail.getSupportedOperationSets(); - - if ((supportedOperationSets != null) - && supportedOperationSets.contains(operationSet)) - contactDetails.add(contactDetail); - } - return contactDetails; - } - - /** - * Returns a list of all ContactDetails corresponding to the given - * category. - * @param category the OperationSet class we're looking for - * @return a list of all ContactDetails corresponding to the given - * category - */ - public List getContactDetails( - ContactDetail.Category category) - { - List contactDetails = new LinkedList(); - - for (ContactDetail contactDetail : getContactDetails()) - { - if(contactDetail != null) - { - ContactDetail.Category detailCategory - = contactDetail.getCategory(); - if (detailCategory != null && detailCategory.equals(category)) - contactDetails.add(contactDetail); - } - } - return contactDetails; - } - - /** - * Gets the ContactSourceService which has created this - * SourceContact. - * - * @return the ContactSourceService which has created this - * SourceContact - * @see SourceContact#getContactSource() - */ - public ContactSourceService getContactSource() - { - return contactSource; - } - - /** - * Gets the display details of this SourceContact. - * - * @return the display details of this SourceContact - * @see SourceContact#getDisplayDetails() - */ - public String getDisplayDetails() - { - return displayDetails; - } - - /** - * Sets the address of the contact. - * - * @param contactAddress the address to set. - */ - public void setContactAddress(String contactAddress) - { - this.contactAddress = contactAddress; - } - - /** - * Sets the display details of this SourceContact. - * - * @param displayDetails the display details of this SourceContact - */ - public String setDisplayDetails(String displayDetails) - { - return this.displayDetails = displayDetails; - } - - /** - * Gets the display name of this SourceContact. - * - * @return the display name of this SourceContact - * @see SourceContact#getDisplayName() - */ - public String getDisplayName() - { - return displayName; - } - - /** - * Sets the display name of this SourceContact. - * - * @param displayName The display name of this SourceContact - */ - public void setDisplayName(String displayName) - { - this.displayName = displayName; - } - - /** - * Gets the image/avatar of this SourceContact. - * - * @return the image/avatar of this SourceContact - * @see SourceContact#getImage() - */ - public byte[] getImage() - { - return image; - } - - /** - * Gets the preferred ContactDetail for a specific - * OperationSet. - * - * @param operationSet the OperationSet to get the preferred - * ContactDetail for - * @return the preferred ContactDetail for the specified - * operationSet - * @see SourceContact#getPreferredContactDetail(Class) - */ - public ContactDetail getPreferredContactDetail( - Class operationSet) - { - List contactDetails = getContactDetails(operationSet); - - return contactDetails.isEmpty() ? null : contactDetails.get(0); - } - - /** - * Sets the image/avatar of this SourceContact. - * - * @param image the image/avatar to be set on this SourceContact - */ - public void setImage(byte[] image) - { - this.image = image; - } - - /** - * Whether the current image returned by @see #getImage() is the one - * provided by the SourceContact by default, or is a one used and obtained - * from external source. - * - * @return whether this is the default image for this SourceContact. - */ - @Override - public boolean isDefaultImage() - { - // in this SourceContact we always show an externally set image or null - return false; - } - - /** - * Returns the status of the source contact. And null if such information - * is not available. - * @return the PresenceStatus representing the state of this source contact. - */ - public PresenceStatus getPresenceStatus() - { - return presenceStatus; - } - - /** - * Sets the status of the source contact. - * - * @param presenceStatus the status of this contact - */ - public void setPresenceStatus(PresenceStatus presenceStatus) - { - this.presenceStatus = presenceStatus; - } - - /** - * Returns the index of this source contact in its parent. - * - * @return the index of this source contact in its parent - */ - public int getIndex() - { - return -1; - } -} +package net.java.sip.communicator.service.contactsource; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * Implements a generic SourceContact for the purposes of the support + * for the OS-specific Address Book. + * + * @author Lyubomir Marinov + */ +public class GenericSourceContact + extends DataObject + implements SourceContact +{ + /** + * The ContactDetails of this SourceContact. + */ + protected final List contactDetails; + + /** + * The ContactSourceService which has created this + * SourceContact. + */ + private final ContactSourceService contactSource; + + /** + * The display name of this SourceContact. + */ + private String displayName; + + /** + * The display details of this contact. + */ + private String displayDetails; + + /** + * The presence status of this contact. + */ + private PresenceStatus presenceStatus; + + /** + * The image/avatar of this SourceContact + */ + private byte[] image; + + /** + * The address of the contact. + */ + private String contactAddress = null; + + /** + * Initializes a new AddrBookSourceContact instance. + * + * @param contactSource the ContactSourceService which is creating + * the new instance + * @param displayName the display name of the new instance + * @param contactDetails the ContactDetails of the new instance + */ + public GenericSourceContact( + ContactSourceService contactSource, + String displayName, + List contactDetails) + { + this.contactSource = contactSource; + this.displayName = displayName; + this.contactDetails = contactDetails; + } + + /** + * Returns the address of the contact. + * + * @return the contact address. + */ + public String getContactAddress() + { + return contactAddress; + } + + /** + * Gets the ContactDetails of this SourceContact. + * + * @return the ContactDetails of this SourceContact + * @see SourceContact#getContactDetails() + */ + public List getContactDetails() + { + return Collections.unmodifiableList(contactDetails); + } + + /** + * Gets the ContactDetails of this SourceContact which + * support a specific OperationSet. + * + * @param operationSet the OperationSet the supporting + * ContactDetails of which are to be returned + * @return the ContactDetails of this SourceContact which + * support the specified operationSet + * @see SourceContact#getContactDetails(Class) + */ + public List getContactDetails( + Class operationSet) + { + List contactDetails = new LinkedList(); + + for (ContactDetail contactDetail : getContactDetails()) + { + List> supportedOperationSets + = contactDetail.getSupportedOperationSets(); + + if ((supportedOperationSets != null) + && supportedOperationSets.contains(operationSet)) + contactDetails.add(contactDetail); + } + return contactDetails; + } + + /** + * Returns a list of all ContactDetails corresponding to the given + * category. + * @param category the OperationSet class we're looking for + * @return a list of all ContactDetails corresponding to the given + * category + */ + public List getContactDetails( + ContactDetail.Category category) + { + List contactDetails = new LinkedList(); + + for (ContactDetail contactDetail : getContactDetails()) + { + if(contactDetail != null) + { + ContactDetail.Category detailCategory + = contactDetail.getCategory(); + if (detailCategory != null && detailCategory.equals(category)) + contactDetails.add(contactDetail); + } + } + return contactDetails; + } + + /** + * Gets the ContactSourceService which has created this + * SourceContact. + * + * @return the ContactSourceService which has created this + * SourceContact + * @see SourceContact#getContactSource() + */ + public ContactSourceService getContactSource() + { + return contactSource; + } + + /** + * Gets the display details of this SourceContact. + * + * @return the display details of this SourceContact + * @see SourceContact#getDisplayDetails() + */ + public String getDisplayDetails() + { + return displayDetails; + } + + /** + * Sets the address of the contact. + * + * @param contactAddress the address to set. + */ + public void setContactAddress(String contactAddress) + { + this.contactAddress = contactAddress; + } + + /** + * Sets the display details of this SourceContact. + * + * @param displayDetails the display details of this SourceContact + */ + public String setDisplayDetails(String displayDetails) + { + return this.displayDetails = displayDetails; + } + + /** + * Gets the display name of this SourceContact. + * + * @return the display name of this SourceContact + * @see SourceContact#getDisplayName() + */ + public String getDisplayName() + { + return displayName; + } + + /** + * Sets the display name of this SourceContact. + * + * @param displayName The display name of this SourceContact + */ + public void setDisplayName(String displayName) + { + this.displayName = displayName; + } + + /** + * Gets the image/avatar of this SourceContact. + * + * @return the image/avatar of this SourceContact + * @see SourceContact#getImage() + */ + public byte[] getImage() + { + return image; + } + + /** + * Gets the preferred ContactDetail for a specific + * OperationSet. + * + * @param operationSet the OperationSet to get the preferred + * ContactDetail for + * @return the preferred ContactDetail for the specified + * operationSet + * @see SourceContact#getPreferredContactDetail(Class) + */ + public ContactDetail getPreferredContactDetail( + Class operationSet) + { + List contactDetails = getContactDetails(operationSet); + + return contactDetails.isEmpty() ? null : contactDetails.get(0); + } + + /** + * Sets the image/avatar of this SourceContact. + * + * @param image the image/avatar to be set on this SourceContact + */ + public void setImage(byte[] image) + { + this.image = image; + } + + /** + * Whether the current image returned by @see #getImage() is the one + * provided by the SourceContact by default, or is a one used and obtained + * from external source. + * + * @return whether this is the default image for this SourceContact. + */ + @Override + public boolean isDefaultImage() + { + // in this SourceContact we always show an externally set image or null + return false; + } + + /** + * Returns the status of the source contact. And null if such information + * is not available. + * @return the PresenceStatus representing the state of this source contact. + */ + public PresenceStatus getPresenceStatus() + { + return presenceStatus; + } + + /** + * Sets the status of the source contact. + * + * @param presenceStatus the status of this contact + */ + public void setPresenceStatus(PresenceStatus presenceStatus) + { + this.presenceStatus = presenceStatus; + } + + /** + * Returns the index of this source contact in its parent. + * + * @return the index of this source contact in its parent + */ + public int getIndex() + { + return -1; + } +} diff --git a/src/net/java/sip/communicator/service/dns/DnssecException.java b/src/net/java/sip/communicator/service/dns/DnssecException.java index bc91146..dc4923e 100644 --- a/src/net/java/sip/communicator/service/dns/DnssecException.java +++ b/src/net/java/sip/communicator/service/dns/DnssecException.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,27 +15,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.dns; - -/** - * Checked DNSSEC exception for code that knows how to deal with it. - * - * @author Ingo Bauersachs - */ -public class DnssecException - extends Exception -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates a new instance of this class. - * @param e the DNSSEC runtime exception to encapsulate. - */ - public DnssecException(DnssecRuntimeException e) - { - super(e); - } -} +package net.java.sip.communicator.service.dns; + +/** + * Checked DNSSEC exception for code that knows how to deal with it. + * + * @author Ingo Bauersachs + */ +public class DnssecException + extends Exception +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Creates a new instance of this class. + * @param e the DNSSEC runtime exception to encapsulate. + */ + public DnssecException(DnssecRuntimeException e) + { + super(e); + } +} diff --git a/src/net/java/sip/communicator/service/dns/DnssecRuntimeException.java b/src/net/java/sip/communicator/service/dns/DnssecRuntimeException.java index 192f9e4..cd948b4 100644 --- a/src/net/java/sip/communicator/service/dns/DnssecRuntimeException.java +++ b/src/net/java/sip/communicator/service/dns/DnssecRuntimeException.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,32 +15,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.dns; - -import java.net.*; - -/** - * Runtime exception that is thrown when a DNSSEC validation failure occurred. - * This is not a checked exception or a derivative of - * {@link UnknownHostException} so that existing code does not retry the lookup - * (potentially in a loop). - * - * @author Ingo Bauersachs - */ -public class DnssecRuntimeException - extends RuntimeException -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates a new instance of this class. - * @param message The reason why this exception is thrown. - */ - public DnssecRuntimeException(String message) - { - super(message); - } -} +package net.java.sip.communicator.service.dns; + +import java.net.*; + +/** + * Runtime exception that is thrown when a DNSSEC validation failure occurred. + * This is not a checked exception or a derivative of + * {@link UnknownHostException} so that existing code does not retry the lookup + * (potentially in a loop). + * + * @author Ingo Bauersachs + */ +public class DnssecRuntimeException + extends RuntimeException +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Creates a new instance of this class. + * @param message The reason why this exception is thrown. + */ + public DnssecRuntimeException(String message) + { + super(message); + } +} diff --git a/src/net/java/sip/communicator/service/gui/AlertUIService.java b/src/net/java/sip/communicator/service/gui/AlertUIService.java index 2843d60..a6055c4 100644 --- a/src/net/java/sip/communicator/service/gui/AlertUIService.java +++ b/src/net/java/sip/communicator/service/gui/AlertUIService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,125 +15,125 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.gui; - -/** - * The AlertUIService is a service that allows to show error messages - * and warnings. - * - * @author Yana Stamcheva - */ -public interface AlertUIService -{ - /** - * Indicates that the OK button is pressed. - */ - public static final int OK_RETURN_CODE = 0; - - /** - * Indicates that the Cancel button is pressed. - */ - public static final int CANCEL_RETURN_CODE = 1; - - /** - * Indicates that the OK button is pressed and the Don't ask check box is - * checked. - */ - public static final int OK_DONT_ASK_CODE = 2; - - /** - * The type of the alert dialog, which displays a warning instead of an - * error. - */ - public static final int WARNING = 1; - - /** - * The type of alert dialog which displays a warning instead of an error. - */ - public static final int ERROR = 0; - - /** - * Shows an alert dialog with the given title and message. - * - * @param title the title of the dialog - * @param message the message to be displayed - */ - public void showAlertDialog(String title, - String message); - - /** - * Shows an alert dialog with the given title message and exception - * corresponding to the error. - * - * @param title the title of the dialog - * @param message the message to be displayed - * @param e the exception corresponding to the error - */ - public void showAlertDialog(String title, - String message, - Throwable e); - - /** - * Shows an alert dialog with the given title, message and type of message. - * - * @param title the title of the error dialog - * @param message the message to be displayed - * @param type the dialog type (warning or error) - */ - public void showAlertDialog(String title, - String message, - int type); - - /** - * Shows an notification pop-up which can be clicked. An error dialog is - * shown when the notification is clicked. - * - * @param title the title of the error dialog and the notification pop-up - * @param message the message to be displayed in the error dialog and the - * pop-up - */ - public void showAlertPopup(String title, String message); - - /** - * Shows an notification pop-up which can be clicked. An error dialog is - * shown when the notification is clicked. - * - * @param title the title of the error dialog and the notification pop-up - * @param message the message to be displayed in the error dialog and the - * pop-up - * @param e the exception that can be shown in the error dialog - */ - public void showAlertPopup(String title, String message, - Throwable e); - - /** - * Shows an notification pop-up which can be clicked. An error dialog is - * shown when the notification is clicked. - * - * @param title the title of the notification pop-up - * @param message the message of the pop-up - * @param errorDialogTitle the title of the error dialog - * @param errorDialogMessage the message of the error dialog - */ - public void showAlertPopup(String title, String message, - String errorDialogTitle, String errorDialogMessage); - - /** - * Shows an notification pop-up which can be clicked. An error dialog is - * shown when the notification is clicked. - * - * @param title the title of the notification pop-up - * @param message the message of the pop-up - * @param errorDialogTitle the title of the error dialog - * @param errorDialogMessage the message of the error dialog - * @param e the exception that can be shown in the error dialog - */ - public void showAlertPopup(String title, String message, - String errorDialogTitle, String errorDialogMessage, Throwable e); - - /** - * Releases the resources acquired by this instance throughout its lifetime - * and removes the listeners. - */ - public void dispose(); -} +package net.java.sip.communicator.service.gui; + +/** + * The AlertUIService is a service that allows to show error messages + * and warnings. + * + * @author Yana Stamcheva + */ +public interface AlertUIService +{ + /** + * Indicates that the OK button is pressed. + */ + public static final int OK_RETURN_CODE = 0; + + /** + * Indicates that the Cancel button is pressed. + */ + public static final int CANCEL_RETURN_CODE = 1; + + /** + * Indicates that the OK button is pressed and the Don't ask check box is + * checked. + */ + public static final int OK_DONT_ASK_CODE = 2; + + /** + * The type of the alert dialog, which displays a warning instead of an + * error. + */ + public static final int WARNING = 1; + + /** + * The type of alert dialog which displays a warning instead of an error. + */ + public static final int ERROR = 0; + + /** + * Shows an alert dialog with the given title and message. + * + * @param title the title of the dialog + * @param message the message to be displayed + */ + public void showAlertDialog(String title, + String message); + + /** + * Shows an alert dialog with the given title message and exception + * corresponding to the error. + * + * @param title the title of the dialog + * @param message the message to be displayed + * @param e the exception corresponding to the error + */ + public void showAlertDialog(String title, + String message, + Throwable e); + + /** + * Shows an alert dialog with the given title, message and type of message. + * + * @param title the title of the error dialog + * @param message the message to be displayed + * @param type the dialog type (warning or error) + */ + public void showAlertDialog(String title, + String message, + int type); + + /** + * Shows an notification pop-up which can be clicked. An error dialog is + * shown when the notification is clicked. + * + * @param title the title of the error dialog and the notification pop-up + * @param message the message to be displayed in the error dialog and the + * pop-up + */ + public void showAlertPopup(String title, String message); + + /** + * Shows an notification pop-up which can be clicked. An error dialog is + * shown when the notification is clicked. + * + * @param title the title of the error dialog and the notification pop-up + * @param message the message to be displayed in the error dialog and the + * pop-up + * @param e the exception that can be shown in the error dialog + */ + public void showAlertPopup(String title, String message, + Throwable e); + + /** + * Shows an notification pop-up which can be clicked. An error dialog is + * shown when the notification is clicked. + * + * @param title the title of the notification pop-up + * @param message the message of the pop-up + * @param errorDialogTitle the title of the error dialog + * @param errorDialogMessage the message of the error dialog + */ + public void showAlertPopup(String title, String message, + String errorDialogTitle, String errorDialogMessage); + + /** + * Shows an notification pop-up which can be clicked. An error dialog is + * shown when the notification is clicked. + * + * @param title the title of the notification pop-up + * @param message the message of the pop-up + * @param errorDialogTitle the title of the error dialog + * @param errorDialogMessage the message of the error dialog + * @param e the exception that can be shown in the error dialog + */ + public void showAlertPopup(String title, String message, + String errorDialogTitle, String errorDialogMessage, Throwable e); + + /** + * Releases the resources acquired by this instance throughout its lifetime + * and removes the listeners. + */ + public void dispose(); +} diff --git a/src/net/java/sip/communicator/service/gui/ChatLinkClickedListener.java b/src/net/java/sip/communicator/service/gui/ChatLinkClickedListener.java index 5d64489..cf7468f 100644 --- a/src/net/java/sip/communicator/service/gui/ChatLinkClickedListener.java +++ b/src/net/java/sip/communicator/service/gui/ChatLinkClickedListener.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,21 +15,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.gui; - -import java.net.*; - -/** - * Event-callback for clicks on links. - * - * @author Daniel Perren - */ -public interface ChatLinkClickedListener -{ - /** - * Callback that is executed when a link was clicked. - * - * @param url The URI of the link that was clicked. - */ - public void chatLinkClicked(URI url); -} +package net.java.sip.communicator.service.gui; + +import java.net.*; + +/** + * Event-callback for clicks on links. + * + * @author Daniel Perren + */ +public interface ChatLinkClickedListener +{ + /** + * Callback that is executed when a link was clicked. + * + * @param url The URI of the link that was clicked. + */ + public void chatLinkClicked(URI url); +} diff --git a/src/net/java/sip/communicator/service/gui/LazyConfigurationForm.java b/src/net/java/sip/communicator/service/gui/LazyConfigurationForm.java index f5db9fa..fe4a66e 100644 --- a/src/net/java/sip/communicator/service/gui/LazyConfigurationForm.java +++ b/src/net/java/sip/communicator/service/gui/LazyConfigurationForm.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,220 +15,220 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.gui; - -import java.lang.reflect.*; - -import net.java.sip.communicator.service.gui.internal.*; -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class LazyConfigurationForm - implements ConfigurationForm -{ - /** - * The ResourceManagementService used to obtain any resources. - */ - private static ResourceManagementService resources; - - /** - * Returns an instance of the ResourceManagementService, which - * could be used to obtain any resources. - * @return an instance of the ResourceManagementService - */ - private static ResourceManagementService getResources() - { - if (resources == null) - resources = - ResourceManagementServiceUtils.getService(GuiServiceActivator - .getBundleContext()); - return resources; - } - - /** - * The form class loader. - */ - private final ClassLoader formClassLoader; - - /** - * The class name of the form. - */ - private final String formClassName; - - /** - * The identifier of the icon. - */ - private final String iconID; - - /** - * The index of the form in the parent container. - */ - private final int index; - - /** - * The title identifier. - */ - private final String titleID; - - /** - * Indicates if this form is advanced. - */ - private final boolean isAdvanced; - - /** - * Creates an instance of LazyConfigurationForm. - * @param formClassName the class name of the configuration form - * @param formClassLoader the class loader - * @param iconID the identifier of the form icon - * @param titleID the identifier of the form title - */ - public LazyConfigurationForm(String formClassName, - ClassLoader formClassLoader, String iconID, String titleID) - { - this(formClassName, formClassLoader, iconID, titleID, -1, false); - } - - /** - * Creates an instance of LazyConfigurationForm. - * @param formClassName the class name of the configuration form - * @param formClassLoader the class loader - * @param iconID the identifier of the form icon - * @param titleID the identifier of the form title - * @param index the index of the form in the parent container - */ - public LazyConfigurationForm(String formClassName, - ClassLoader formClassLoader, String iconID, String titleID, int index) - { - this(formClassName, formClassLoader, iconID, titleID, index, false); - } - - /** - * Creates an instance of LazyConfigurationForm. - * @param formClassName the class name of the configuration form - * @param formClassLoader the class loader - * @param iconID the identifier of the form icon - * @param titleID the identifier of the form title - * @param index the index of the form in the parent container - * @param isAdvanced indicates if the form is advanced configuration form - */ - public LazyConfigurationForm(String formClassName, - ClassLoader formClassLoader, - String iconID, - String titleID, - int index, - boolean isAdvanced) - { - this.formClassName = formClassName; - this.formClassLoader = formClassLoader; - this.iconID = iconID; - this.titleID = titleID; - this.index = index; - this.isAdvanced = isAdvanced; - } - - /** - * Returns the form component. - * @return the form component - */ - public Object getForm() - { - Exception exception; - try - { - return Class - .forName(getFormClassName(), true, getFormClassLoader()) - .newInstance(); - } - catch (ClassNotFoundException ex) - { - exception = ex; - } - catch (IllegalAccessException ex) - { - exception = ex; - } - catch (InstantiationException ex) - { - exception = ex; - } - throw new UndeclaredThrowableException(exception); - } - - /** - * Returns the form class loader. - * @return the form class loader - */ - protected ClassLoader getFormClassLoader() - { - return formClassLoader; - } - - /** - * Returns the form class name. - * @return the form class name - */ - public String getFormClassName() - { - return formClassName; - } - - /** - * Returns the icon of the form. - * @return a byte array containing the icon of the form - */ - public byte[] getIcon() - { - return getResources().getImageInBytes(getIconID()); - } - - /** - * Returns the identifier of the icon. - * @return the identifier of the icon - */ - protected String getIconID() - { - return iconID; - } - - /** - * Returns the index of the form in its parent container. - * @return the index of the form in its parent container - */ - public int getIndex() - { - return index; - } - - /** - * Returns the title of the form. - * @return the title of the form - */ - public String getTitle() - { - return getResources().getI18NString(getTitleID()); - } - - /** - * Returns the identifier of the title of the form. - * @return the identifier of the title of the form - */ - protected String getTitleID() - { - return titleID; - } - - /** - * Indicates if the form is an advanced form. - * @return true to indicate that this is an advanced form, - * otherwise returns false - */ - public boolean isAdvanced() - { - return isAdvanced; - } -} +package net.java.sip.communicator.service.gui; + +import java.lang.reflect.*; + +import net.java.sip.communicator.service.gui.internal.*; +import net.java.sip.communicator.service.resources.*; + +import org.jitsi.service.resources.*; + +/** + * @author Lubomir Marinov + * @author Yana Stamcheva + */ +public class LazyConfigurationForm + implements ConfigurationForm +{ + /** + * The ResourceManagementService used to obtain any resources. + */ + private static ResourceManagementService resources; + + /** + * Returns an instance of the ResourceManagementService, which + * could be used to obtain any resources. + * @return an instance of the ResourceManagementService + */ + private static ResourceManagementService getResources() + { + if (resources == null) + resources = + ResourceManagementServiceUtils.getService(GuiServiceActivator + .getBundleContext()); + return resources; + } + + /** + * The form class loader. + */ + private final ClassLoader formClassLoader; + + /** + * The class name of the form. + */ + private final String formClassName; + + /** + * The identifier of the icon. + */ + private final String iconID; + + /** + * The index of the form in the parent container. + */ + private final int index; + + /** + * The title identifier. + */ + private final String titleID; + + /** + * Indicates if this form is advanced. + */ + private final boolean isAdvanced; + + /** + * Creates an instance of LazyConfigurationForm. + * @param formClassName the class name of the configuration form + * @param formClassLoader the class loader + * @param iconID the identifier of the form icon + * @param titleID the identifier of the form title + */ + public LazyConfigurationForm(String formClassName, + ClassLoader formClassLoader, String iconID, String titleID) + { + this(formClassName, formClassLoader, iconID, titleID, -1, false); + } + + /** + * Creates an instance of LazyConfigurationForm. + * @param formClassName the class name of the configuration form + * @param formClassLoader the class loader + * @param iconID the identifier of the form icon + * @param titleID the identifier of the form title + * @param index the index of the form in the parent container + */ + public LazyConfigurationForm(String formClassName, + ClassLoader formClassLoader, String iconID, String titleID, int index) + { + this(formClassName, formClassLoader, iconID, titleID, index, false); + } + + /** + * Creates an instance of LazyConfigurationForm. + * @param formClassName the class name of the configuration form + * @param formClassLoader the class loader + * @param iconID the identifier of the form icon + * @param titleID the identifier of the form title + * @param index the index of the form in the parent container + * @param isAdvanced indicates if the form is advanced configuration form + */ + public LazyConfigurationForm(String formClassName, + ClassLoader formClassLoader, + String iconID, + String titleID, + int index, + boolean isAdvanced) + { + this.formClassName = formClassName; + this.formClassLoader = formClassLoader; + this.iconID = iconID; + this.titleID = titleID; + this.index = index; + this.isAdvanced = isAdvanced; + } + + /** + * Returns the form component. + * @return the form component + */ + public Object getForm() + { + Exception exception; + try + { + return Class + .forName(getFormClassName(), true, getFormClassLoader()) + .newInstance(); + } + catch (ClassNotFoundException ex) + { + exception = ex; + } + catch (IllegalAccessException ex) + { + exception = ex; + } + catch (InstantiationException ex) + { + exception = ex; + } + throw new UndeclaredThrowableException(exception); + } + + /** + * Returns the form class loader. + * @return the form class loader + */ + protected ClassLoader getFormClassLoader() + { + return formClassLoader; + } + + /** + * Returns the form class name. + * @return the form class name + */ + public String getFormClassName() + { + return formClassName; + } + + /** + * Returns the icon of the form. + * @return a byte array containing the icon of the form + */ + public byte[] getIcon() + { + return getResources().getImageInBytes(getIconID()); + } + + /** + * Returns the identifier of the icon. + * @return the identifier of the icon + */ + protected String getIconID() + { + return iconID; + } + + /** + * Returns the index of the form in its parent container. + * @return the index of the form in its parent container + */ + public int getIndex() + { + return index; + } + + /** + * Returns the title of the form. + * @return the title of the form + */ + public String getTitle() + { + return getResources().getI18NString(getTitleID()); + } + + /** + * Returns the identifier of the title of the form. + * @return the identifier of the title of the form + */ + protected String getTitleID() + { + return titleID; + } + + /** + * Indicates if the form is an advanced form. + * @return true to indicate that this is an advanced form, + * otherwise returns false + */ + public boolean isAdvanced() + { + return isAdvanced; + } +} diff --git a/src/net/java/sip/communicator/service/gui/internal/GuiServiceActivator.java b/src/net/java/sip/communicator/service/gui/internal/GuiServiceActivator.java index 7dfbc37..abfc1bd 100644 --- a/src/net/java/sip/communicator/service/gui/internal/GuiServiceActivator.java +++ b/src/net/java/sip/communicator/service/gui/internal/GuiServiceActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,78 +15,78 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.gui.internal; - -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class GuiServiceActivator - implements BundleActivator -{ - /** - * The BundleContext of the service. - */ - private static BundleContext bundleContext; - - /** - * The ResourceManagementService, which gives access to application - * resources. - */ - private static ResourceManagementService resourceService; - - /** - * Returns the BundleContext. - * - * @return bundle context - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Initialize and start GUI service - * - * @param bundleContext the BundleContext - */ - public void start(BundleContext bundleContext) - { - GuiServiceActivator.bundleContext = bundleContext; - } - - /** - * Stops this bundle. - * - * @param bundleContext the BundleContext - */ - public void stop(BundleContext bundleContext) - { - if (GuiServiceActivator.bundleContext == bundleContext) - GuiServiceActivator.bundleContext = null; - } - - /** - * Returns the ResourceManagementService, through which we will - * access all resources. - * - * @return the ResourceManagementService, through which we will - * access all resources. - */ - public static ResourceManagementService getResources() - { - if (resourceService == null) - { - resourceService - = ServiceUtils.getService( - bundleContext, - ResourceManagementService.class); - } - return resourceService; - } -} +package net.java.sip.communicator.service.gui.internal; + +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * @author Lubomir Marinov + * @author Yana Stamcheva + */ +public class GuiServiceActivator + implements BundleActivator +{ + /** + * The BundleContext of the service. + */ + private static BundleContext bundleContext; + + /** + * The ResourceManagementService, which gives access to application + * resources. + */ + private static ResourceManagementService resourceService; + + /** + * Returns the BundleContext. + * + * @return bundle context + */ + public static BundleContext getBundleContext() + { + return bundleContext; + } + + /** + * Initialize and start GUI service + * + * @param bundleContext the BundleContext + */ + public void start(BundleContext bundleContext) + { + GuiServiceActivator.bundleContext = bundleContext; + } + + /** + * Stops this bundle. + * + * @param bundleContext the BundleContext + */ + public void stop(BundleContext bundleContext) + { + if (GuiServiceActivator.bundleContext == bundleContext) + GuiServiceActivator.bundleContext = null; + } + + /** + * Returns the ResourceManagementService, through which we will + * access all resources. + * + * @return the ResourceManagementService, through which we will + * access all resources. + */ + public static ResourceManagementService getResources() + { + if (resourceService == null) + { + resourceService + = ServiceUtils.getService( + bundleContext, + ResourceManagementService.class); + } + return resourceService; + } +} diff --git a/src/net/java/sip/communicator/service/muc/ChatRoomPresenceStatus.java b/src/net/java/sip/communicator/service/muc/ChatRoomPresenceStatus.java index fa9d244..b0d81a8 100644 --- a/src/net/java/sip/communicator/service/muc/ChatRoomPresenceStatus.java +++ b/src/net/java/sip/communicator/service/muc/ChatRoomPresenceStatus.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,72 +15,72 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.muc; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The chat room statuses. - * - * @author Hristo Terezov - */ -public class ChatRoomPresenceStatus extends PresenceStatus -{ - /** - * An integer above which all values of the status coefficient indicate - * eagerness to communicate - */ - public static final int CHAT_ROOM_ONLINE_THRESHOLD = 86; - - /** - * An integer above which all values of the status coefficient indicate - * eagerness to communicate - */ - public static final int CHAT_ROOM_OFFLINE_THRESHOLD = 87; - - /** - * Indicates that the user is connected and ready to communicate. - */ - public static final String ONLINE_STATUS = "Online"; - - /** - * Indicates that the user is disconnected. - */ - public static final String OFFLINE_STATUS = "Offline"; - - /** - * The Online status. Indicate that the user is able and willing to - * communicate in the chat room. - */ - public static final ChatRoomPresenceStatus CHAT_ROOM_ONLINE - = new ChatRoomPresenceStatus( - 86, - ONLINE_STATUS); - - /** - * The Offline status. Indicates the user does not seem to be connected - * to the chat room. - */ - public static final ChatRoomPresenceStatus CHAT_ROOM_OFFLINE - = new ChatRoomPresenceStatus( - 87, - OFFLINE_STATUS); - - /** - * Creates a status with the specified connectivity coeff and name for the - * chat rooms. - * @param status the connectivity coefficient for the specified status - * @param statusName String - */ - protected ChatRoomPresenceStatus(int status, String statusName) - { - super(status, statusName); - } - - @Override - public boolean isOnline() - { - return getStatus() == CHAT_ROOM_ONLINE_THRESHOLD; - } - -} +package net.java.sip.communicator.service.muc; + +import net.java.sip.communicator.service.protocol.*; + +/** + * The chat room statuses. + * + * @author Hristo Terezov + */ +public class ChatRoomPresenceStatus extends PresenceStatus +{ + /** + * An integer above which all values of the status coefficient indicate + * eagerness to communicate + */ + public static final int CHAT_ROOM_ONLINE_THRESHOLD = 86; + + /** + * An integer above which all values of the status coefficient indicate + * eagerness to communicate + */ + public static final int CHAT_ROOM_OFFLINE_THRESHOLD = 87; + + /** + * Indicates that the user is connected and ready to communicate. + */ + public static final String ONLINE_STATUS = "Online"; + + /** + * Indicates that the user is disconnected. + */ + public static final String OFFLINE_STATUS = "Offline"; + + /** + * The Online status. Indicate that the user is able and willing to + * communicate in the chat room. + */ + public static final ChatRoomPresenceStatus CHAT_ROOM_ONLINE + = new ChatRoomPresenceStatus( + 86, + ONLINE_STATUS); + + /** + * The Offline status. Indicates the user does not seem to be connected + * to the chat room. + */ + public static final ChatRoomPresenceStatus CHAT_ROOM_OFFLINE + = new ChatRoomPresenceStatus( + 87, + OFFLINE_STATUS); + + /** + * Creates a status with the specified connectivity coeff and name for the + * chat rooms. + * @param status the connectivity coefficient for the specified status + * @param statusName String + */ + protected ChatRoomPresenceStatus(int status, String statusName) + { + super(status, statusName); + } + + @Override + public boolean isOnline() + { + return getStatus() == CHAT_ROOM_ONLINE_THRESHOLD; + } + +} diff --git a/src/net/java/sip/communicator/service/muc/MUCService.java b/src/net/java/sip/communicator/service/muc/MUCService.java index 856d122..15d57a3 100644 --- a/src/net/java/sip/communicator/service/muc/MUCService.java +++ b/src/net/java/sip/communicator/service/muc/MUCService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,398 +15,398 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.muc; - -import java.util.*; - -import net.java.sip.communicator.service.contactsource.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * The MUC service provides interface for the chat rooms. It connects the GUI - * with the protcol. - * - * @author Hristo Terezov - */ -public abstract class MUCService -{ - /** - * The configuration property to disable - */ - public static final String DISABLED_PROPERTY - = "net.java.sip.communicator.impl.muc.MUC_SERVICE_DISABLED"; - - /** - * Key for auto-open configuration entry. - */ - private static String AUTO_OPEN_CONFIG_KEY = "openAutomatically"; - - /** - * The value for chat room configuration property to open automatically on - * activity - */ - public static String OPEN_ON_ACTIVITY = "on_activity"; - - /** - * The value for chat room configuration property to open automatically on - * message - */ - public static String OPEN_ON_MESSAGE = "on_message"; - - /** - * The value for chat room configuration property to open automatically on - * important messages. - */ - public static String OPEN_ON_IMPORTANT_MESSAGE = "on_important_message"; - - /** - * The default for chat room auto-open behaviour. - */ - public static String DEFAULT_AUTO_OPEN_BEHAVIOUR = OPEN_ON_MESSAGE; - - /** - * Map for the auto open configuration values and their text representation - */ - public static Map autoOpenConfigValuesTexts - = new HashMap(); - - static - { - autoOpenConfigValuesTexts.put(OPEN_ON_ACTIVITY, - "service.gui.OPEN_ON_ACTIVITY"); - autoOpenConfigValuesTexts.put(OPEN_ON_MESSAGE, - "service.gui.OPEN_ON_MESSAGE"); - autoOpenConfigValuesTexts.put(OPEN_ON_IMPORTANT_MESSAGE, - "service.gui.OPEN_ON_IMPORTANT_MESSAGE"); - } - - /** - * Sets chat room open automatically property - * @param pps the provider - * @param chatRoomId the chat room id - * @param value the new value for the property - */ - public static void setChatRoomAutoOpenOption( - ProtocolProviderService pps, - String chatRoomId, - String value) - { - ConfigurationUtils.updateChatRoomProperty( - pps, - chatRoomId, AUTO_OPEN_CONFIG_KEY, value); - } - - /** - * Returns the value of the chat room open automatically property - * @param pps the provider - * @param chatRoomId the chat room id - * @return the value of the chat room open automatically property - */ - public static String getChatRoomAutoOpenOption( - ProtocolProviderService pps, - String chatRoomId) - { - return ConfigurationUtils.getChatRoomProperty( - pps, - chatRoomId, AUTO_OPEN_CONFIG_KEY); - } - - /** - * Fires a ChatRoomListChangedEvent event. - * - * @param chatRoomWrapper the chat room. - * @param eventID the id of the event. - */ - public abstract void fireChatRoomListChangedEvent( - ChatRoomWrapper chatRoomWrapper, int eventID); - - /** - * Joins the given chat room with the given password and manages all the - * exceptions that could occur during the join process. - * - * @param chatRoomWrapper the chat room to join. - * @param nickName the nickname we choose for the given chat room. - * @param password the password. - * @param subject the subject which will be set to the room after the user - * join successful. - */ - public abstract void joinChatRoom( ChatRoomWrapper chatRoomWrapper, - String nickName, byte[] password, String subject); - - /** - * Creates a chat room, by specifying the chat room name, the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param roomName the name of the room - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param persistent is the room persistent - * @return the ChatRoomWrapper corresponding to the created room - */ - public abstract ChatRoomWrapper createChatRoom(String roomName, - ProtocolProviderService protocolProvider, Collection contacts, - String reason, boolean persistent); - - - - /** - * Creates a private chat room, by specifying the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param persistent is the room persistent - * @return the ChatRoomWrapper corresponding to the created room - */ - public abstract ChatRoomWrapper createPrivateChatRoom( - ProtocolProviderService protocolProvider, Collection contacts, - String reason, boolean persistent); - - - /** - * Creates a chat room, by specifying the chat room name, the parent - * protocol provider and eventually, the contacts invited to participate in - * this chat room. - * - * @param roomName the name of the room - * @param protocolProvider the parent protocol provider. - * @param contacts the contacts invited when creating the chat room. - * @param reason - * @param join whether we should join the room after creating it. - * @param persistent whether the newly created room will be persistent. - * @param isPrivate whether the room will be private or public. - * @return the ChatRoomWrapper corresponding to the created room or - * null if the protocol failed to create the chat room - */ - public abstract ChatRoomWrapper createChatRoom(String roomName, - ProtocolProviderService protocolProvider, Collection contacts, - String reason, boolean join, boolean persistent, boolean isPrivate); - - /** - * Joins the room with the given name though the given chat room provider. - * - * @param chatRoomName the name of the room to join. - * @param chatRoomProvider the chat room provider to join through. - */ - public abstract void joinChatRoom( String chatRoomName, - ChatRoomProviderWrapper chatRoomProvider); - - /** - * Returns existing chat rooms for the given chatRoomProvider. - * @param chatRoomProvider the ChatRoomProviderWrapper, which - * chat rooms we're looking for - * @return existing chat rooms for the given chatRoomProvider - */ - public abstract List getExistingChatRooms( - ChatRoomProviderWrapper chatRoomProvider); - - - /** - * Called to accept an incoming invitation. Adds the invitation chat room - * to the list of chat rooms and joins it. - * - * @param invitation the invitation to accept. - */ - public abstract void acceptInvitation(ChatRoomInvitation invitation); - - /** - * Rejects the given invitation with the specified reason. - * - * @param multiUserChatOpSet the operation set to use for rejecting the - * invitation - * @param invitation the invitation to reject - * @param reason the reason for the rejection - */ - public abstract void rejectInvitation( OperationSetMultiUserChat multiUserChatOpSet, - ChatRoomInvitation invitation, - String reason); - - /** - * Determines whether a specific ChatRoom is private i.e. - * represents a one-to-one conversation which is not a channel. Since the - * interface {@link ChatRoom} does not expose the private property, an - * heuristic is used as a workaround: (1) a system ChatRoom is - * obviously not private and (2) a ChatRoom is private if it - * has only one ChatRoomMember who is not the local user. - * - * @param chatRoom - * the ChatRoom to be determined as private or not - * @return true if the specified ChatRoom is private; - * otherwise, false - */ - public static boolean isPrivate(ChatRoom chatRoom) - { - if (!chatRoom.isSystem() - && chatRoom.isJoined() - && (chatRoom.getMembersCount() == 1)) - { - String nickname = chatRoom.getUserNickname(); - - if (nickname != null) - { - for (ChatRoomMember member : chatRoom.getMembers()) - if (nickname.equals(member.getName())) - return false; - return true; - } - } - return false; - } - - /** - * Leaves the given chat room. - * - * @param chatRoomWrapper the chat room to leave. - * @return ChatRoomWrapper instance associated with the chat room. - */ - public abstract ChatRoomWrapper leaveChatRoom(ChatRoomWrapper chatRoomWrapper); - - /** - * Finds ChatRoomWrapper instance associated with the given source - * contact. - * @param contact the contact. - * @return ChatRoomWrapper instance associated with the given - * source contact. - */ - public abstract ChatRoomWrapper findChatRoomWrapperFromSourceContact( - SourceContact contact); - - /** - * Searches for chat room wrapper in chat room list by chat room. - * - * @param chatRoom the chat room. - * @param create if true and the chat room wrapper is not found new - * chatRoomWrapper is created. - * @return found chat room wrapper or the created chat room wrapper. - */ - public abstract ChatRoomWrapper getChatRoomWrapperByChatRoom( - ChatRoom chatRoom, boolean create); - - /** - * Returns the multi user chat operation set for the given protocol provider. - * - * @param protocolProvider The protocol provider for which the multi user - * chat operation set is about. - * @return OperationSetMultiUserChat The telephony operation - * set for the given protocol provider. - */ - public static OperationSetMultiUserChat getMultiUserChatOpSet( - ProtocolProviderService protocolProvider) - { - OperationSet opSet - = protocolProvider.getOperationSet(OperationSetMultiUserChat.class); - - return (opSet instanceof OperationSetMultiUserChat) - ? (OperationSetMultiUserChat) opSet - : null; - } - - /** - * Finds the ChatRoomWrapper instance associated with the - * chat room. - * @param chatRoomID the id of the chat room. - * @param pps the provider of the chat room. - * @return the ChatRoomWrapper instance. - */ - public abstract ChatRoomWrapper findChatRoomWrapperFromChatRoomID( - String chatRoomID, - ProtocolProviderService pps); - - /** - * Goes through the locally stored chat rooms list and for each - * {@link ChatRoomWrapper} tries to find the corresponding server stored - * {@link ChatRoom} in the specified operation set. Joins automatically all - * found chat rooms. - * - * @param protocolProvider the protocol provider for the account to - * synchronize - * @param opSet the multi user chat operation set, which give us access to - * chat room server - */ - public abstract void synchronizeOpSetWithLocalContactList( - ProtocolProviderService protocolProvider, - final OperationSetMultiUserChat opSet); - - /** - * Returns an iterator to the list of chat room providers. - * - * @return an iterator to the list of chat room providers. - */ - public abstract Iterator getChatRoomProviders(); - - /** - * Removes the given ChatRoom from the list of all chat rooms. - * - * @param chatRoomWrapper the ChatRoomWrapper to remove - */ - public abstract void removeChatRoom(ChatRoomWrapper chatRoomWrapper); - - /** - * Adds a ChatRoomProviderWrapperListener to the listener list. - * - * @param listener the ChatRoomProviderWrapperListener to be added - */ - public abstract void addChatRoomProviderWrapperListener( - ChatRoomProviderWrapperListener listener); - - /** - * Removes the ChatRoomProviderWrapperListener to the listener list. - * - * @param listener the ChatRoomProviderWrapperListener to be removed - */ - public abstract void removeChatRoomProviderWrapperListener( - ChatRoomProviderWrapperListener listener); - - /** - * Returns the ChatRoomProviderWrapper that correspond to the - * given ProtocolProviderService. If the list doesn't contain a - * corresponding wrapper - returns null. - * - * @param protocolProvider the protocol provider that we're looking for - * @return the ChatRoomProvider object corresponding to - * the given ProtocolProviderService - */ - public abstract ChatRoomProviderWrapper findServerWrapperFromProvider( - ProtocolProviderService protocolProvider); - - /** - * Returns the ChatRoomWrapper that correspond to the given - * ChatRoom. If the list of chat rooms doesn't contain a - * corresponding wrapper - returns null. - * - * @param chatRoom the ChatRoom that we're looking for - * @return the ChatRoomWrapper object corresponding to the given - * ChatRoom - */ - public abstract ChatRoomWrapper findChatRoomWrapperFromChatRoom( - ChatRoom chatRoom); - - /** - * Opens a chat window for the chat room. - * - * @param room the chat room. - */ - public abstract void openChatRoom(ChatRoomWrapper room); - - /** - * Returns instance of the ServerChatRoomContactSourceService - * contact source. - * @return instance of the ServerChatRoomContactSourceService - * contact source. - */ - public abstract ContactSourceService - getServerChatRoomsContactSourceForProvider(ChatRoomProviderWrapper pps); - - /** - * Returns true if the contact is ChatRoomSourceContact - * - * @param contact the contact - * @return true if the contact is ChatRoomSourceContact - */ - public abstract boolean isMUCSourceContact(SourceContact contact); -} +package net.java.sip.communicator.service.muc; + +import java.util.*; + +import net.java.sip.communicator.service.contactsource.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The MUC service provides interface for the chat rooms. It connects the GUI + * with the protcol. + * + * @author Hristo Terezov + */ +public abstract class MUCService +{ + /** + * The configuration property to disable + */ + public static final String DISABLED_PROPERTY + = "net.java.sip.communicator.impl.muc.MUC_SERVICE_DISABLED"; + + /** + * Key for auto-open configuration entry. + */ + private static String AUTO_OPEN_CONFIG_KEY = "openAutomatically"; + + /** + * The value for chat room configuration property to open automatically on + * activity + */ + public static String OPEN_ON_ACTIVITY = "on_activity"; + + /** + * The value for chat room configuration property to open automatically on + * message + */ + public static String OPEN_ON_MESSAGE = "on_message"; + + /** + * The value for chat room configuration property to open automatically on + * important messages. + */ + public static String OPEN_ON_IMPORTANT_MESSAGE = "on_important_message"; + + /** + * The default for chat room auto-open behaviour. + */ + public static String DEFAULT_AUTO_OPEN_BEHAVIOUR = OPEN_ON_MESSAGE; + + /** + * Map for the auto open configuration values and their text representation + */ + public static Map autoOpenConfigValuesTexts + = new HashMap(); + + static + { + autoOpenConfigValuesTexts.put(OPEN_ON_ACTIVITY, + "service.gui.OPEN_ON_ACTIVITY"); + autoOpenConfigValuesTexts.put(OPEN_ON_MESSAGE, + "service.gui.OPEN_ON_MESSAGE"); + autoOpenConfigValuesTexts.put(OPEN_ON_IMPORTANT_MESSAGE, + "service.gui.OPEN_ON_IMPORTANT_MESSAGE"); + } + + /** + * Sets chat room open automatically property + * @param pps the provider + * @param chatRoomId the chat room id + * @param value the new value for the property + */ + public static void setChatRoomAutoOpenOption( + ProtocolProviderService pps, + String chatRoomId, + String value) + { + ConfigurationUtils.updateChatRoomProperty( + pps, + chatRoomId, AUTO_OPEN_CONFIG_KEY, value); + } + + /** + * Returns the value of the chat room open automatically property + * @param pps the provider + * @param chatRoomId the chat room id + * @return the value of the chat room open automatically property + */ + public static String getChatRoomAutoOpenOption( + ProtocolProviderService pps, + String chatRoomId) + { + return ConfigurationUtils.getChatRoomProperty( + pps, + chatRoomId, AUTO_OPEN_CONFIG_KEY); + } + + /** + * Fires a ChatRoomListChangedEvent event. + * + * @param chatRoomWrapper the chat room. + * @param eventID the id of the event. + */ + public abstract void fireChatRoomListChangedEvent( + ChatRoomWrapper chatRoomWrapper, int eventID); + + /** + * Joins the given chat room with the given password and manages all the + * exceptions that could occur during the join process. + * + * @param chatRoomWrapper the chat room to join. + * @param nickName the nickname we choose for the given chat room. + * @param password the password. + * @param subject the subject which will be set to the room after the user + * join successful. + */ + public abstract void joinChatRoom( ChatRoomWrapper chatRoomWrapper, + String nickName, byte[] password, String subject); + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param persistent is the room persistent + * @return the ChatRoomWrapper corresponding to the created room + */ + public abstract ChatRoomWrapper createChatRoom(String roomName, + ProtocolProviderService protocolProvider, Collection contacts, + String reason, boolean persistent); + + + + /** + * Creates a private chat room, by specifying the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param persistent is the room persistent + * @return the ChatRoomWrapper corresponding to the created room + */ + public abstract ChatRoomWrapper createPrivateChatRoom( + ProtocolProviderService protocolProvider, Collection contacts, + String reason, boolean persistent); + + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @param reason + * @param join whether we should join the room after creating it. + * @param persistent whether the newly created room will be persistent. + * @param isPrivate whether the room will be private or public. + * @return the ChatRoomWrapper corresponding to the created room or + * null if the protocol failed to create the chat room + */ + public abstract ChatRoomWrapper createChatRoom(String roomName, + ProtocolProviderService protocolProvider, Collection contacts, + String reason, boolean join, boolean persistent, boolean isPrivate); + + /** + * Joins the room with the given name though the given chat room provider. + * + * @param chatRoomName the name of the room to join. + * @param chatRoomProvider the chat room provider to join through. + */ + public abstract void joinChatRoom( String chatRoomName, + ChatRoomProviderWrapper chatRoomProvider); + + /** + * Returns existing chat rooms for the given chatRoomProvider. + * @param chatRoomProvider the ChatRoomProviderWrapper, which + * chat rooms we're looking for + * @return existing chat rooms for the given chatRoomProvider + */ + public abstract List getExistingChatRooms( + ChatRoomProviderWrapper chatRoomProvider); + + + /** + * Called to accept an incoming invitation. Adds the invitation chat room + * to the list of chat rooms and joins it. + * + * @param invitation the invitation to accept. + */ + public abstract void acceptInvitation(ChatRoomInvitation invitation); + + /** + * Rejects the given invitation with the specified reason. + * + * @param multiUserChatOpSet the operation set to use for rejecting the + * invitation + * @param invitation the invitation to reject + * @param reason the reason for the rejection + */ + public abstract void rejectInvitation( OperationSetMultiUserChat multiUserChatOpSet, + ChatRoomInvitation invitation, + String reason); + + /** + * Determines whether a specific ChatRoom is private i.e. + * represents a one-to-one conversation which is not a channel. Since the + * interface {@link ChatRoom} does not expose the private property, an + * heuristic is used as a workaround: (1) a system ChatRoom is + * obviously not private and (2) a ChatRoom is private if it + * has only one ChatRoomMember who is not the local user. + * + * @param chatRoom + * the ChatRoom to be determined as private or not + * @return true if the specified ChatRoom is private; + * otherwise, false + */ + public static boolean isPrivate(ChatRoom chatRoom) + { + if (!chatRoom.isSystem() + && chatRoom.isJoined() + && (chatRoom.getMembersCount() == 1)) + { + String nickname = chatRoom.getUserNickname(); + + if (nickname != null) + { + for (ChatRoomMember member : chatRoom.getMembers()) + if (nickname.equals(member.getName())) + return false; + return true; + } + } + return false; + } + + /** + * Leaves the given chat room. + * + * @param chatRoomWrapper the chat room to leave. + * @return ChatRoomWrapper instance associated with the chat room. + */ + public abstract ChatRoomWrapper leaveChatRoom(ChatRoomWrapper chatRoomWrapper); + + /** + * Finds ChatRoomWrapper instance associated with the given source + * contact. + * @param contact the contact. + * @return ChatRoomWrapper instance associated with the given + * source contact. + */ + public abstract ChatRoomWrapper findChatRoomWrapperFromSourceContact( + SourceContact contact); + + /** + * Searches for chat room wrapper in chat room list by chat room. + * + * @param chatRoom the chat room. + * @param create if true and the chat room wrapper is not found new + * chatRoomWrapper is created. + * @return found chat room wrapper or the created chat room wrapper. + */ + public abstract ChatRoomWrapper getChatRoomWrapperByChatRoom( + ChatRoom chatRoom, boolean create); + + /** + * Returns the multi user chat operation set for the given protocol provider. + * + * @param protocolProvider The protocol provider for which the multi user + * chat operation set is about. + * @return OperationSetMultiUserChat The telephony operation + * set for the given protocol provider. + */ + public static OperationSetMultiUserChat getMultiUserChatOpSet( + ProtocolProviderService protocolProvider) + { + OperationSet opSet + = protocolProvider.getOperationSet(OperationSetMultiUserChat.class); + + return (opSet instanceof OperationSetMultiUserChat) + ? (OperationSetMultiUserChat) opSet + : null; + } + + /** + * Finds the ChatRoomWrapper instance associated with the + * chat room. + * @param chatRoomID the id of the chat room. + * @param pps the provider of the chat room. + * @return the ChatRoomWrapper instance. + */ + public abstract ChatRoomWrapper findChatRoomWrapperFromChatRoomID( + String chatRoomID, + ProtocolProviderService pps); + + /** + * Goes through the locally stored chat rooms list and for each + * {@link ChatRoomWrapper} tries to find the corresponding server stored + * {@link ChatRoom} in the specified operation set. Joins automatically all + * found chat rooms. + * + * @param protocolProvider the protocol provider for the account to + * synchronize + * @param opSet the multi user chat operation set, which give us access to + * chat room server + */ + public abstract void synchronizeOpSetWithLocalContactList( + ProtocolProviderService protocolProvider, + final OperationSetMultiUserChat opSet); + + /** + * Returns an iterator to the list of chat room providers. + * + * @return an iterator to the list of chat room providers. + */ + public abstract Iterator getChatRoomProviders(); + + /** + * Removes the given ChatRoom from the list of all chat rooms. + * + * @param chatRoomWrapper the ChatRoomWrapper to remove + */ + public abstract void removeChatRoom(ChatRoomWrapper chatRoomWrapper); + + /** + * Adds a ChatRoomProviderWrapperListener to the listener list. + * + * @param listener the ChatRoomProviderWrapperListener to be added + */ + public abstract void addChatRoomProviderWrapperListener( + ChatRoomProviderWrapperListener listener); + + /** + * Removes the ChatRoomProviderWrapperListener to the listener list. + * + * @param listener the ChatRoomProviderWrapperListener to be removed + */ + public abstract void removeChatRoomProviderWrapperListener( + ChatRoomProviderWrapperListener listener); + + /** + * Returns the ChatRoomProviderWrapper that correspond to the + * given ProtocolProviderService. If the list doesn't contain a + * corresponding wrapper - returns null. + * + * @param protocolProvider the protocol provider that we're looking for + * @return the ChatRoomProvider object corresponding to + * the given ProtocolProviderService + */ + public abstract ChatRoomProviderWrapper findServerWrapperFromProvider( + ProtocolProviderService protocolProvider); + + /** + * Returns the ChatRoomWrapper that correspond to the given + * ChatRoom. If the list of chat rooms doesn't contain a + * corresponding wrapper - returns null. + * + * @param chatRoom the ChatRoom that we're looking for + * @return the ChatRoomWrapper object corresponding to the given + * ChatRoom + */ + public abstract ChatRoomWrapper findChatRoomWrapperFromChatRoom( + ChatRoom chatRoom); + + /** + * Opens a chat window for the chat room. + * + * @param room the chat room. + */ + public abstract void openChatRoom(ChatRoomWrapper room); + + /** + * Returns instance of the ServerChatRoomContactSourceService + * contact source. + * @return instance of the ServerChatRoomContactSourceService + * contact source. + */ + public abstract ContactSourceService + getServerChatRoomsContactSourceForProvider(ChatRoomProviderWrapper pps); + + /** + * Returns true if the contact is ChatRoomSourceContact + * + * @param contact the contact + * @return true if the contact is ChatRoomSourceContact + */ + public abstract boolean isMUCSourceContact(SourceContact contact); +} diff --git a/src/net/java/sip/communicator/service/notification/CommandNotificationAction.java b/src/net/java/sip/communicator/service/notification/CommandNotificationAction.java index ffe8d10..dd502e4 100644 --- a/src/net/java/sip/communicator/service/notification/CommandNotificationAction.java +++ b/src/net/java/sip/communicator/service/notification/CommandNotificationAction.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,39 +15,39 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.notification; - -/** - * An implementation of the CommandNotificationHandler interface. - * - * @author Yana Stamcheva - */ -public class CommandNotificationAction - extends NotificationAction -{ - private String commandDescriptor; - - /** - * Creates an instance of CommandNotification by - * specifying the commandDescriptor, which will point us to the - * command to execute. - * - * @param commandDescriptor a String that should point us to the command to - * execute - */ - public CommandNotificationAction(String commandDescriptor) - { - super(NotificationAction.ACTION_COMMAND); - this.commandDescriptor = commandDescriptor; - } - - /** - * Returns the command descriptor. - * - * @return the command descriptor - */ - public String getDescriptor() - { - return commandDescriptor; - } -} +package net.java.sip.communicator.service.notification; + +/** + * An implementation of the CommandNotificationHandler interface. + * + * @author Yana Stamcheva + */ +public class CommandNotificationAction + extends NotificationAction +{ + private String commandDescriptor; + + /** + * Creates an instance of CommandNotification by + * specifying the commandDescriptor, which will point us to the + * command to execute. + * + * @param commandDescriptor a String that should point us to the command to + * execute + */ + public CommandNotificationAction(String commandDescriptor) + { + super(NotificationAction.ACTION_COMMAND); + this.commandDescriptor = commandDescriptor; + } + + /** + * Returns the command descriptor. + * + * @return the command descriptor + */ + public String getDescriptor() + { + return commandDescriptor; + } +} diff --git a/src/net/java/sip/communicator/service/notification/NotificationAction.java b/src/net/java/sip/communicator/service/notification/NotificationAction.java index bb8b156..73b285f 100644 --- a/src/net/java/sip/communicator/service/notification/NotificationAction.java +++ b/src/net/java/sip/communicator/service/notification/NotificationAction.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,98 +15,98 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.notification; - -/** - * Base class for actions of a notification. - * - * @author Ingo Bauersachs - */ -public abstract class NotificationAction -{ - /** - * The sound action type indicates that a sound would be played, when a - * notification is fired. - */ - public static final String ACTION_SOUND = "SoundAction"; - - /** - * The popup message action type indicates that a window (or a systray - * popup), containing the corresponding notification message would be poped - * up, when a notification is fired. - */ - public static final String ACTION_POPUP_MESSAGE = "PopupMessageAction"; - - /** - * The log message action type indicates that a message would be logged, - * when a notification is fired. - */ - public static final String ACTION_LOG_MESSAGE = "LogMessageAction"; - - /** - * The command action type indicates that a command would be executed, - * when a notification is fired. - */ - public static final String ACTION_COMMAND = "CommandAction"; - - /** - * The vibrate action type indicates that the device will vibrate, - * when a notification is fired. - */ - public static final String ACTION_VIBRATE = "VibrateAction"; - - /** - * Indicates if this handler is enabled. - */ - private boolean isEnabled = true; - - /** - * The action type name. - */ - private String actionType; - - /** - * Creates a new instance of this class. - * @param actionType The action type name. - */ - protected NotificationAction(String actionType) - { - this.actionType = actionType; - } - - /** - * Return the action type name. - * @return the action type name. - */ - public String getActionType() - { - return actionType; - } - - /** - * Returns TRUE if this notification action handler is enabled and FALSE - * otherwise. While the notification handler for the sound action type is - * disabled no sounds will be played when the fireNotification - * method is called. - * - * @return TRUE if this notification action handler is enabled and FALSE - * otherwise - */ - public boolean isEnabled() - { - return isEnabled; - } - - /** - * Enables or disables this notification handler. While the notification - * handler for the sound action type is disabled no sounds will be played - * when the fireNotification method is called. - * - * @param isEnabled TRUE to enable this notification handler, FALSE to - * disable it. - */ - public void setEnabled(boolean isEnabled) - { - this.isEnabled = isEnabled; - } -} +package net.java.sip.communicator.service.notification; + +/** + * Base class for actions of a notification. + * + * @author Ingo Bauersachs + */ +public abstract class NotificationAction +{ + /** + * The sound action type indicates that a sound would be played, when a + * notification is fired. + */ + public static final String ACTION_SOUND = "SoundAction"; + + /** + * The popup message action type indicates that a window (or a systray + * popup), containing the corresponding notification message would be poped + * up, when a notification is fired. + */ + public static final String ACTION_POPUP_MESSAGE = "PopupMessageAction"; + + /** + * The log message action type indicates that a message would be logged, + * when a notification is fired. + */ + public static final String ACTION_LOG_MESSAGE = "LogMessageAction"; + + /** + * The command action type indicates that a command would be executed, + * when a notification is fired. + */ + public static final String ACTION_COMMAND = "CommandAction"; + + /** + * The vibrate action type indicates that the device will vibrate, + * when a notification is fired. + */ + public static final String ACTION_VIBRATE = "VibrateAction"; + + /** + * Indicates if this handler is enabled. + */ + private boolean isEnabled = true; + + /** + * The action type name. + */ + private String actionType; + + /** + * Creates a new instance of this class. + * @param actionType The action type name. + */ + protected NotificationAction(String actionType) + { + this.actionType = actionType; + } + + /** + * Return the action type name. + * @return the action type name. + */ + public String getActionType() + { + return actionType; + } + + /** + * Returns TRUE if this notification action handler is enabled and FALSE + * otherwise. While the notification handler for the sound action type is + * disabled no sounds will be played when the fireNotification + * method is called. + * + * @return TRUE if this notification action handler is enabled and FALSE + * otherwise + */ + public boolean isEnabled() + { + return isEnabled; + } + + /** + * Enables or disables this notification handler. While the notification + * handler for the sound action type is disabled no sounds will be played + * when the fireNotification method is called. + * + * @param isEnabled TRUE to enable this notification handler, FALSE to + * disable it. + */ + public void setEnabled(boolean isEnabled) + { + this.isEnabled = isEnabled; + } +} diff --git a/src/net/java/sip/communicator/service/notification/NotificationData.java b/src/net/java/sip/communicator/service/notification/NotificationData.java index 21c8fba..dd2bc8f 100644 --- a/src/net/java/sip/communicator/service/notification/NotificationData.java +++ b/src/net/java/sip/communicator/service/notification/NotificationData.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,151 +15,151 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.notification; - -import java.util.*; - -/** - * Object to cache fired notifications before all handler implementations are - * ready registered. - * - * @author Ingo Bauersachs - */ -public class NotificationData -{ - /** - * The name/key of the NotificationData extra which is provided to - * {@link CommandNotificationHandler#execute(CommandNotificationAction, - * Map)} i.e. a Map<String,String> which is known by the - * (argument) name cmdargs. - */ - public static final String COMMAND_NOTIFICATION_HANDLER_CMDARGS_EXTRA - = "CommandNotificationHandler.cmdargs"; - - /** - * The name/key of the NotificationData extra which is provided to - * {@link PopupMessageNotificationHandler#popupMessage( - * PopupMessageNotificationAction, String, String, byte[], Object)} i.e. an - * Object which is known by the (argument) name tag. - */ - public static final String POPUP_MESSAGE_HANDLER_TAG_EXTRA - = "PopupMessageNotificationHandler.tag"; - - /** - * The name/key of the NotificationData extra which is provided to - * {@link SoundNotificationHandler} i.e. a Callable<Boolean> - * which is known as the condition which determines whether looping sounds - * are to continue playing. - */ - public static final String SOUND_NOTIFICATION_HANDLER_LOOP_CONDITION_EXTRA - = "SoundNotificationHandler.loopCondition"; - - private final String eventType; - - /** - * The {@link NotificationHandler}-specific extras provided to this - * instance. The keys are among the XXX_EXTRA constants defined by - * the NotificationData class. - */ - private final Map extras; - - private final byte[] icon; - private final String message; - private final String title; - - /** - * Creates a new instance of this class. - * - * @param eventType the type of the event that we'd like to fire a - * notification for. - * @param title the title of the given message - * @param message the message to use if and where appropriate (e.g. with - * systray or log notification.) - * @param icon the icon to show in the notification if and where appropriate - * @param extras additional/extra {@link NotificationHandler}-specific data - * to be provided by the new instance to the various - * NotificationHandlers - */ - NotificationData( - String eventType, - String title, - String message, - byte[] icon, - Map extras) - { - this.eventType = eventType; - this.title = title; - this.message = message; - this.icon = icon; - this.extras = extras; - } - - /** - * Gets the type of the event that we'd like to fire a notification for - * - * @return the eventType - */ - public String getEventType() - { - return eventType; - } - - /** - * Gets the {@link NotificationHandler}-specific extras provided to this - * instance. - * - * @return the NotificationHandler-specific extras provided to this - * instance. The keys are among the XXX_EXTRA constants defined by - * the NotificationData class - */ - Map getExtras() - { - return Collections.unmodifiableMap(extras); - } - - /** - * Gets the {@link NotificationHandler}-specific extra provided to this - * instance associated with a specific key. - * - * @param key the key whose associated NotificationHandler-specific - * extra is to be returned. Well known keys are defined by the - * NotificationData class as the XXX_EXTRA constants. - * @return the NotificationHandler-specific extra provided to this - * instance associated with the specified key - */ - public Object getExtra(String key) - { - return (extras == null) ? null : extras.get(key); - } - - /** - * Gets the icon to show in the notification if and where appropriate. - * - * @return the icon - */ - byte[] getIcon() - { - return icon; - } - - /** - * Gets the message to use if and where appropriate (e.g. with systray or - * log notification). - * - * @return the message - */ - String getMessage() - { - return message; - } - - /** - * Gets the title of the given message. - * - * @return the title - */ - String getTitle() - { - return title; - } -} +package net.java.sip.communicator.service.notification; + +import java.util.*; + +/** + * Object to cache fired notifications before all handler implementations are + * ready registered. + * + * @author Ingo Bauersachs + */ +public class NotificationData +{ + /** + * The name/key of the NotificationData extra which is provided to + * {@link CommandNotificationHandler#execute(CommandNotificationAction, + * Map)} i.e. a Map<String,String> which is known by the + * (argument) name cmdargs. + */ + public static final String COMMAND_NOTIFICATION_HANDLER_CMDARGS_EXTRA + = "CommandNotificationHandler.cmdargs"; + + /** + * The name/key of the NotificationData extra which is provided to + * {@link PopupMessageNotificationHandler#popupMessage( + * PopupMessageNotificationAction, String, String, byte[], Object)} i.e. an + * Object which is known by the (argument) name tag. + */ + public static final String POPUP_MESSAGE_HANDLER_TAG_EXTRA + = "PopupMessageNotificationHandler.tag"; + + /** + * The name/key of the NotificationData extra which is provided to + * {@link SoundNotificationHandler} i.e. a Callable<Boolean> + * which is known as the condition which determines whether looping sounds + * are to continue playing. + */ + public static final String SOUND_NOTIFICATION_HANDLER_LOOP_CONDITION_EXTRA + = "SoundNotificationHandler.loopCondition"; + + private final String eventType; + + /** + * The {@link NotificationHandler}-specific extras provided to this + * instance. The keys are among the XXX_EXTRA constants defined by + * the NotificationData class. + */ + private final Map extras; + + private final byte[] icon; + private final String message; + private final String title; + + /** + * Creates a new instance of this class. + * + * @param eventType the type of the event that we'd like to fire a + * notification for. + * @param title the title of the given message + * @param message the message to use if and where appropriate (e.g. with + * systray or log notification.) + * @param icon the icon to show in the notification if and where appropriate + * @param extras additional/extra {@link NotificationHandler}-specific data + * to be provided by the new instance to the various + * NotificationHandlers + */ + NotificationData( + String eventType, + String title, + String message, + byte[] icon, + Map extras) + { + this.eventType = eventType; + this.title = title; + this.message = message; + this.icon = icon; + this.extras = extras; + } + + /** + * Gets the type of the event that we'd like to fire a notification for + * + * @return the eventType + */ + public String getEventType() + { + return eventType; + } + + /** + * Gets the {@link NotificationHandler}-specific extras provided to this + * instance. + * + * @return the NotificationHandler-specific extras provided to this + * instance. The keys are among the XXX_EXTRA constants defined by + * the NotificationData class + */ + Map getExtras() + { + return Collections.unmodifiableMap(extras); + } + + /** + * Gets the {@link NotificationHandler}-specific extra provided to this + * instance associated with a specific key. + * + * @param key the key whose associated NotificationHandler-specific + * extra is to be returned. Well known keys are defined by the + * NotificationData class as the XXX_EXTRA constants. + * @return the NotificationHandler-specific extra provided to this + * instance associated with the specified key + */ + public Object getExtra(String key) + { + return (extras == null) ? null : extras.get(key); + } + + /** + * Gets the icon to show in the notification if and where appropriate. + * + * @return the icon + */ + byte[] getIcon() + { + return icon; + } + + /** + * Gets the message to use if and where appropriate (e.g. with systray or + * log notification). + * + * @return the message + */ + String getMessage() + { + return message; + } + + /** + * Gets the title of the given message. + * + * @return the title + */ + String getTitle() + { + return title; + } +} diff --git a/src/net/java/sip/communicator/service/notification/PopupMessageNotificationAction.java b/src/net/java/sip/communicator/service/notification/PopupMessageNotificationAction.java index 244945f..395249c 100644 --- a/src/net/java/sip/communicator/service/notification/PopupMessageNotificationAction.java +++ b/src/net/java/sip/communicator/service/notification/PopupMessageNotificationAction.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,108 +15,108 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.notification; - -/** - * An implementation of the PopupMessageNotificationHandler interface. - * - * @author Yana Stamcheva - */ -public class PopupMessageNotificationAction - extends NotificationAction -{ - private String defaultMessage; - - /** - * Suggested timeout in ms for hiding the popup if not clicked by the user. - */ - private long timeout = -1; - - /** - * Group name used to group notifications on Android. - */ - private String groupName; - - /** - * Creates an instance of PopupMessageNotificationHandlerImpl by - * specifying the default message to use if no message is specified. - * - * @param defaultMessage the default message to use if no message is - * specified - */ - public PopupMessageNotificationAction(String defaultMessage) - { - super(NotificationAction.ACTION_POPUP_MESSAGE); - this.defaultMessage = defaultMessage; - } - - /** - * Creates an instance of PopupMessageNotificationHandlerImpl by - * specifying the default message to use if no message is specified. - * - * @param defaultMessage the default message to use if no message is - * specified - * @param timeout suggested timeout in ms for hiding the popup if not - * clicked by the user, -1 for infinity - */ - public PopupMessageNotificationAction(String defaultMessage, long timeout) - { - this(defaultMessage); - this.timeout = timeout; - } - - /** - * Creates an instance of PopupMessageNotificationHandlerImpl by - * specifying the default message to use if no message is specified. - * - * @param defaultMessage the default message to use if no message is - * specified - * @param timeout suggested timeout in ms for hiding the popup if not - * clicked by the user, -1 for infinity - * @param groupName name of the group that will be used for merging popups - */ - public PopupMessageNotificationAction(String defaultMessage, long timeout, - String groupName) - { - this(defaultMessage, timeout); - this.groupName = groupName; - } - - /** - * Return the default message to use if no message is specified. - * - * @return the default message to use if no message is specified. - */ - public String getDefaultMessage() - { - return defaultMessage; - } - - /** - * Returns suggested timeout value in ms for hiding the popup if not clicked - * by the user. - * @return timeout value in ms for hiding the popup, -1 for infinity. - */ - public long getTimeout() - { - return timeout; - } - - /** - * Sets the name of the group that will be used for merging popups. - * @param groupName name of popup group to set. - */ - public void setGroupName(String groupName) - { - this.groupName = groupName; - } - - /** - * Returns name of popup group that will be used for merging notifications. - * @return name of popup group that will be used for merging notifications. - */ - public String getGroupName() - { - return groupName; - } -} +package net.java.sip.communicator.service.notification; + +/** + * An implementation of the PopupMessageNotificationHandler interface. + * + * @author Yana Stamcheva + */ +public class PopupMessageNotificationAction + extends NotificationAction +{ + private String defaultMessage; + + /** + * Suggested timeout in ms for hiding the popup if not clicked by the user. + */ + private long timeout = -1; + + /** + * Group name used to group notifications on Android. + */ + private String groupName; + + /** + * Creates an instance of PopupMessageNotificationHandlerImpl by + * specifying the default message to use if no message is specified. + * + * @param defaultMessage the default message to use if no message is + * specified + */ + public PopupMessageNotificationAction(String defaultMessage) + { + super(NotificationAction.ACTION_POPUP_MESSAGE); + this.defaultMessage = defaultMessage; + } + + /** + * Creates an instance of PopupMessageNotificationHandlerImpl by + * specifying the default message to use if no message is specified. + * + * @param defaultMessage the default message to use if no message is + * specified + * @param timeout suggested timeout in ms for hiding the popup if not + * clicked by the user, -1 for infinity + */ + public PopupMessageNotificationAction(String defaultMessage, long timeout) + { + this(defaultMessage); + this.timeout = timeout; + } + + /** + * Creates an instance of PopupMessageNotificationHandlerImpl by + * specifying the default message to use if no message is specified. + * + * @param defaultMessage the default message to use if no message is + * specified + * @param timeout suggested timeout in ms for hiding the popup if not + * clicked by the user, -1 for infinity + * @param groupName name of the group that will be used for merging popups + */ + public PopupMessageNotificationAction(String defaultMessage, long timeout, + String groupName) + { + this(defaultMessage, timeout); + this.groupName = groupName; + } + + /** + * Return the default message to use if no message is specified. + * + * @return the default message to use if no message is specified. + */ + public String getDefaultMessage() + { + return defaultMessage; + } + + /** + * Returns suggested timeout value in ms for hiding the popup if not clicked + * by the user. + * @return timeout value in ms for hiding the popup, -1 for infinity. + */ + public long getTimeout() + { + return timeout; + } + + /** + * Sets the name of the group that will be used for merging popups. + * @param groupName name of popup group to set. + */ + public void setGroupName(String groupName) + { + this.groupName = groupName; + } + + /** + * Returns name of popup group that will be used for merging notifications. + * @return name of popup group that will be used for merging notifications. + */ + public String getGroupName() + { + return groupName; + } +} diff --git a/src/net/java/sip/communicator/service/notification/SoundNotificationAction.java b/src/net/java/sip/communicator/service/notification/SoundNotificationAction.java index b633fb3..159b15c 100644 --- a/src/net/java/sip/communicator/service/notification/SoundNotificationAction.java +++ b/src/net/java/sip/communicator/service/notification/SoundNotificationAction.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,180 +15,180 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.notification; - -/** - * An implementation of the SoundNotificationHandlerImpl interface. - * - * @author Yana Stamcheva - */ -public class SoundNotificationAction - extends NotificationAction -{ - /** - * Interval of milliseconds to wait before repeating the sound. -1 means no - * repetition. - */ - private int loopInterval; - - /** - * the descriptor pointing to the sound to be played. - */ - private String soundFileDescriptor; - - /** - * The boolean telling if this sound is to be played on notification device. - */ - private boolean isSoundNotificationEnabled; - - /** - * Is sound to be played on playback device. - */ - private boolean isSoundPlaybackEnabled; - - /** - * Is sound to be played on pc speaker device. - */ - private boolean isSoundPCSpeakerEnabled; - - /** - * Creates an instance of SoundNotification by - * specifying the sound file descriptor and the loop interval. - * By default is enabling simulation output to notification and - * playback device. - * - * @param soundDescriptor the sound file descriptor - * @param loopInterval the loop interval - */ - public SoundNotificationAction( String soundDescriptor, - int loopInterval) - { - this(soundDescriptor, loopInterval, - false, - false, - false); - } - - /** - * Creates an instance of SoundNotification by - * specifying the sound file descriptor and the loop interval. - * - * @param soundDescriptor the sound file descriptor - * @param loopInterval the loop interval - * @param isSoundNotificationEnabled True if this sound is activated. False Otherwise. - * @param isSoundPlaybackEnabled True if this sound is activated. False Otherwise. - * @param isSoundPCSpeakerEnabled True if this sound is activated. False Otherwise. - */ - public SoundNotificationAction( String soundDescriptor, - int loopInterval, - boolean isSoundNotificationEnabled, - boolean isSoundPlaybackEnabled, - boolean isSoundPCSpeakerEnabled) - { - super(NotificationAction.ACTION_SOUND); - this.soundFileDescriptor = soundDescriptor; - this.loopInterval = loopInterval; - this.isSoundNotificationEnabled = isSoundNotificationEnabled; - this.isSoundPlaybackEnabled = isSoundPlaybackEnabled; - this.isSoundPCSpeakerEnabled = isSoundPCSpeakerEnabled; - } - - /** - * Returns the loop interval. This is the interval of milliseconds to wait - * before repeating the sound, when playing a sound in loop. By default this - * method returns -1. - * - * @return the loop interval - */ - public int getLoopInterval() - { - return loopInterval; - } - - /** - * Changes the loop interval. This is the interval of milliseconds to wait - * before repeating the sound, when playing a sound in loop. - * - * @return the loop interval - */ - public void setLoopInterval(int loopInterval) - { - this.loopInterval = loopInterval; - } - - /** - * Returns the descriptor pointing to the sound to be played. - * - * @return the descriptor pointing to the sound to be played. - */ - public String getDescriptor() - { - return soundFileDescriptor; - } - - /** - * Returns if this sound is to be played on notification device. - * - * @return True if this sound is played on notification device. - * False Otherwise. - */ - public boolean isSoundNotificationEnabled() - { - return isSoundNotificationEnabled; - } - - /** - * Returns if this sound is to be played on playback device. - * - * @return True if this sound is played on playback device. - * False Otherwise. - */ - public boolean isSoundPlaybackEnabled() - { - return isSoundPlaybackEnabled; - } - - /** - * Returns if this sound is to be played on pc speaker device. - * - * @return True if this sound is played on pc speaker device. - * False Otherwise. - */ - public boolean isSoundPCSpeakerEnabled() - { - return isSoundPCSpeakerEnabled; - } - - /** - * Enables or disables this sound for notification device. - * - * @param isSoundEnabled True if this sound is played on notification - * device. False Otherwise. - */ - public void setSoundNotificationEnabled(boolean isSoundEnabled) - { - this.isSoundNotificationEnabled = isSoundEnabled; - } - - /** - * Enables or disables this sound for playback device. - * - * @param isSoundEnabled True if this sound is played on playback - * device. False Otherwise. - */ - public void setSoundPlaybackEnabled(boolean isSoundEnabled) - { - this.isSoundPlaybackEnabled = isSoundEnabled; - } - - /** - * Enables or disables this sound for pc speaker device. - * - * @param isSoundEnabled True if this sound is played on speaker - * device. False Otherwise. - */ - public void setSoundPCSpeakerEnabled(boolean isSoundEnabled) - { - this.isSoundPCSpeakerEnabled = isSoundEnabled; - } -} +package net.java.sip.communicator.service.notification; + +/** + * An implementation of the SoundNotificationHandlerImpl interface. + * + * @author Yana Stamcheva + */ +public class SoundNotificationAction + extends NotificationAction +{ + /** + * Interval of milliseconds to wait before repeating the sound. -1 means no + * repetition. + */ + private int loopInterval; + + /** + * the descriptor pointing to the sound to be played. + */ + private String soundFileDescriptor; + + /** + * The boolean telling if this sound is to be played on notification device. + */ + private boolean isSoundNotificationEnabled; + + /** + * Is sound to be played on playback device. + */ + private boolean isSoundPlaybackEnabled; + + /** + * Is sound to be played on pc speaker device. + */ + private boolean isSoundPCSpeakerEnabled; + + /** + * Creates an instance of SoundNotification by + * specifying the sound file descriptor and the loop interval. + * By default is enabling simulation output to notification and + * playback device. + * + * @param soundDescriptor the sound file descriptor + * @param loopInterval the loop interval + */ + public SoundNotificationAction( String soundDescriptor, + int loopInterval) + { + this(soundDescriptor, loopInterval, + false, + false, + false); + } + + /** + * Creates an instance of SoundNotification by + * specifying the sound file descriptor and the loop interval. + * + * @param soundDescriptor the sound file descriptor + * @param loopInterval the loop interval + * @param isSoundNotificationEnabled True if this sound is activated. False Otherwise. + * @param isSoundPlaybackEnabled True if this sound is activated. False Otherwise. + * @param isSoundPCSpeakerEnabled True if this sound is activated. False Otherwise. + */ + public SoundNotificationAction( String soundDescriptor, + int loopInterval, + boolean isSoundNotificationEnabled, + boolean isSoundPlaybackEnabled, + boolean isSoundPCSpeakerEnabled) + { + super(NotificationAction.ACTION_SOUND); + this.soundFileDescriptor = soundDescriptor; + this.loopInterval = loopInterval; + this.isSoundNotificationEnabled = isSoundNotificationEnabled; + this.isSoundPlaybackEnabled = isSoundPlaybackEnabled; + this.isSoundPCSpeakerEnabled = isSoundPCSpeakerEnabled; + } + + /** + * Returns the loop interval. This is the interval of milliseconds to wait + * before repeating the sound, when playing a sound in loop. By default this + * method returns -1. + * + * @return the loop interval + */ + public int getLoopInterval() + { + return loopInterval; + } + + /** + * Changes the loop interval. This is the interval of milliseconds to wait + * before repeating the sound, when playing a sound in loop. + * + * @return the loop interval + */ + public void setLoopInterval(int loopInterval) + { + this.loopInterval = loopInterval; + } + + /** + * Returns the descriptor pointing to the sound to be played. + * + * @return the descriptor pointing to the sound to be played. + */ + public String getDescriptor() + { + return soundFileDescriptor; + } + + /** + * Returns if this sound is to be played on notification device. + * + * @return True if this sound is played on notification device. + * False Otherwise. + */ + public boolean isSoundNotificationEnabled() + { + return isSoundNotificationEnabled; + } + + /** + * Returns if this sound is to be played on playback device. + * + * @return True if this sound is played on playback device. + * False Otherwise. + */ + public boolean isSoundPlaybackEnabled() + { + return isSoundPlaybackEnabled; + } + + /** + * Returns if this sound is to be played on pc speaker device. + * + * @return True if this sound is played on pc speaker device. + * False Otherwise. + */ + public boolean isSoundPCSpeakerEnabled() + { + return isSoundPCSpeakerEnabled; + } + + /** + * Enables or disables this sound for notification device. + * + * @param isSoundEnabled True if this sound is played on notification + * device. False Otherwise. + */ + public void setSoundNotificationEnabled(boolean isSoundEnabled) + { + this.isSoundNotificationEnabled = isSoundEnabled; + } + + /** + * Enables or disables this sound for playback device. + * + * @param isSoundEnabled True if this sound is played on playback + * device. False Otherwise. + */ + public void setSoundPlaybackEnabled(boolean isSoundEnabled) + { + this.isSoundPlaybackEnabled = isSoundEnabled; + } + + /** + * Enables or disables this sound for pc speaker device. + * + * @param isSoundEnabled True if this sound is played on speaker + * device. False Otherwise. + */ + public void setSoundPCSpeakerEnabled(boolean isSoundEnabled) + { + this.isSoundPCSpeakerEnabled = isSoundEnabled; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/AccountManagerUtils.java b/src/net/java/sip/communicator/service/protocol/AccountManagerUtils.java index 5b64e06..1400a2d 100644 --- a/src/net/java/sip/communicator/service/protocol/AccountManagerUtils.java +++ b/src/net/java/sip/communicator/service/protocol/AccountManagerUtils.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,168 +15,168 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.event.*; - -import org.osgi.framework.*; - -/** - * Provides utilities to aid the manipulation of {@link AccountManager}. - * - * @author Lyubomir Marinov - */ -public final class AccountManagerUtils -{ - private static AccountManager getAccountManager(BundleContext bundleContext) - { - return - bundleContext.getService( - bundleContext.getServiceReference(AccountManager.class)); - } - - /** - * Starts a specific Bundle and waits for the - * AccountManager available in a specific - * BundleContext to load the stored accounts of a - * ProtocolProviderFactory with a specific protocol name. - * - * @param bundleContextWithAccountManager - * the BundleContext in which an - * AccountManager service is registered - * @param bundleToStart - * the Bundle to be started - * @param protocolNameToWait - * the protocol name of a ProtocolProviderFactory to - * wait the end of the loading of the stored accounts for - * @throws BundleException - * @throws InterruptedException - * if any thread interrupted the current thread before or while - * the current thread was waiting for the loading of the stored - * accounts - */ - public static void startBundleAndWaitStoredAccountsLoaded( - BundleContext bundleContextWithAccountManager, - final Bundle bundleToStart, - final String protocolNameToWait) - throws BundleException, - InterruptedException - { - AccountManager accountManager - = getAccountManager(bundleContextWithAccountManager); - final boolean[] storedAccountsAreLoaded = new boolean[1]; - AccountManagerListener listener = new AccountManagerListener() - { - public void handleAccountManagerEvent(AccountManagerEvent event) - { - if (AccountManagerEvent.STORED_ACCOUNTS_LOADED - != event.getType()) - return; - - ProtocolProviderFactory factory = event.getFactory(); - - /* - * If the event is for a factory with a protocol name other than - * protocolNameToWait, it's not the one we're waiting for. - */ - if ((factory != null) - && !protocolNameToWait - .equals(factory.getProtocolName())) - return; - - /* - * If the event if for a factory which is no longer registered, - * then it's not the one we're waiting for because we're waiting - * for the specified bundle to start and register a factory. - */ - if (factory != null) - { - BundleContext bundleContext - = bundleToStart.getBundleContext(); - - /* - * If the specified bundle still hasn't started, the event - * cannot be the one we're waiting for. - */ - if (bundleContext == null) - return; - - Collection> factoryRefs; - - try - { - factoryRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class, - "(" - + ProtocolProviderFactory.PROTOCOL - + "=" - + protocolNameToWait - + ")"); - } - catch (InvalidSyntaxException isex) - { - /* - * Not likely so ignore it and assume the event is for - * a valid factory. - */ - factoryRefs = null; - } - if ((factoryRefs != null) && !factoryRefs.isEmpty()) - { - boolean factoryIsRegistered = false; - - for (ServiceReference factoryRef - : factoryRefs) - { - if (factory == bundleContext.getService(factoryRef)) - { - factoryIsRegistered = true; - break; - } - } - if (!factoryIsRegistered) - return; - } - } - - synchronized (storedAccountsAreLoaded) - { - storedAccountsAreLoaded[0] = true; - storedAccountsAreLoaded.notify(); - } - } - }; - - accountManager.addListener(listener); - try - { - bundleToStart.start(); - - while (true) - { - synchronized (storedAccountsAreLoaded) - { - if (storedAccountsAreLoaded[0]) - { - break; - } - storedAccountsAreLoaded.wait(); - } - } - } - finally - { - accountManager.removeListener(listener); - } - } - - /** - * Prevents the creation of AccountManagerUtils instances. - */ - private AccountManagerUtils() - { - } -} +package net.java.sip.communicator.service.protocol; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.event.*; + +import org.osgi.framework.*; + +/** + * Provides utilities to aid the manipulation of {@link AccountManager}. + * + * @author Lyubomir Marinov + */ +public final class AccountManagerUtils +{ + private static AccountManager getAccountManager(BundleContext bundleContext) + { + return + bundleContext.getService( + bundleContext.getServiceReference(AccountManager.class)); + } + + /** + * Starts a specific Bundle and waits for the + * AccountManager available in a specific + * BundleContext to load the stored accounts of a + * ProtocolProviderFactory with a specific protocol name. + * + * @param bundleContextWithAccountManager + * the BundleContext in which an + * AccountManager service is registered + * @param bundleToStart + * the Bundle to be started + * @param protocolNameToWait + * the protocol name of a ProtocolProviderFactory to + * wait the end of the loading of the stored accounts for + * @throws BundleException + * @throws InterruptedException + * if any thread interrupted the current thread before or while + * the current thread was waiting for the loading of the stored + * accounts + */ + public static void startBundleAndWaitStoredAccountsLoaded( + BundleContext bundleContextWithAccountManager, + final Bundle bundleToStart, + final String protocolNameToWait) + throws BundleException, + InterruptedException + { + AccountManager accountManager + = getAccountManager(bundleContextWithAccountManager); + final boolean[] storedAccountsAreLoaded = new boolean[1]; + AccountManagerListener listener = new AccountManagerListener() + { + public void handleAccountManagerEvent(AccountManagerEvent event) + { + if (AccountManagerEvent.STORED_ACCOUNTS_LOADED + != event.getType()) + return; + + ProtocolProviderFactory factory = event.getFactory(); + + /* + * If the event is for a factory with a protocol name other than + * protocolNameToWait, it's not the one we're waiting for. + */ + if ((factory != null) + && !protocolNameToWait + .equals(factory.getProtocolName())) + return; + + /* + * If the event if for a factory which is no longer registered, + * then it's not the one we're waiting for because we're waiting + * for the specified bundle to start and register a factory. + */ + if (factory != null) + { + BundleContext bundleContext + = bundleToStart.getBundleContext(); + + /* + * If the specified bundle still hasn't started, the event + * cannot be the one we're waiting for. + */ + if (bundleContext == null) + return; + + Collection> factoryRefs; + + try + { + factoryRefs + = bundleContext.getServiceReferences( + ProtocolProviderFactory.class, + "(" + + ProtocolProviderFactory.PROTOCOL + + "=" + + protocolNameToWait + + ")"); + } + catch (InvalidSyntaxException isex) + { + /* + * Not likely so ignore it and assume the event is for + * a valid factory. + */ + factoryRefs = null; + } + if ((factoryRefs != null) && !factoryRefs.isEmpty()) + { + boolean factoryIsRegistered = false; + + for (ServiceReference factoryRef + : factoryRefs) + { + if (factory == bundleContext.getService(factoryRef)) + { + factoryIsRegistered = true; + break; + } + } + if (!factoryIsRegistered) + return; + } + } + + synchronized (storedAccountsAreLoaded) + { + storedAccountsAreLoaded[0] = true; + storedAccountsAreLoaded.notify(); + } + } + }; + + accountManager.addListener(listener); + try + { + bundleToStart.start(); + + while (true) + { + synchronized (storedAccountsAreLoaded) + { + if (storedAccountsAreLoaded[0]) + { + break; + } + storedAccountsAreLoaded.wait(); + } + } + } + finally + { + accountManager.removeListener(listener); + } + } + + /** + * Prevents the creation of AccountManagerUtils instances. + */ + private AccountManagerUtils() + { + } +} diff --git a/src/net/java/sip/communicator/service/protocol/CallConference.java b/src/net/java/sip/communicator/service/protocol/CallConference.java index 890b0cb..b6752cd 100644 --- a/src/net/java/sip/communicator/service/protocol/CallConference.java +++ b/src/net/java/sip/communicator/service/protocol/CallConference.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,931 +15,931 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.event.*; - -import org.jitsi.util.event.*; - -/** - * Represents the telephony conference-related state of a Call. - * Multiple Call instances share a single CallConference - * instance when the former are into a telephony conference i.e. the local - * peer/user is the conference focus. CallConference is - * protocol-agnostic and thus enables cross-protocol conferences. Since a - * non-conference Call may be converted into a conference Call - * at any time, every Call instance maintains a CallConference - * instance regardless of whether the Call in question is participating - * in a telephony conference. - * - * @author Lyubomir Marinov - */ -public class CallConference - extends PropertyChangeNotifier -{ - /** - * The name of the CallConference property which specifies the list - * of Calls participating in a telephony conference. A change in - * the value of the property is delivered in the form of a - * PropertyChangeEvent which has its oldValue or - * newValue set to the Call which has been removed or - * added to the list of Calls participating in the telephony - * conference. - */ - public static final String CALLS = "calls"; - - /** - * Gets the number of CallPeers associated with the Calls - * participating in the telephony conference-related state of a specific - * Call. - * - * @param call the Call for which the number of CallPeers - * associated with the Calls participating in its associated - * telephony conference-related state - * @return the number of CallPeers associated with the - * Calls participating in the telephony conference-related state - * of the specified Call - */ - public static int getCallPeerCount(Call call) - { - CallConference conference = call.getConference(); - - /* - * A Call instance is supposed to always maintain a CallConference - * instance. Anyway, if it turns out that it is not the case, we will - * consider the Call as a representation of a telephony conference. - */ - return - (conference == null) - ? call.getCallPeerCount() - : conference.getCallPeerCount(); - } - - /** - * Gets a list of the CallPeers associated with the Calls - * participating in the telephony conference in which a specific - * Call is participating. - * - * @param call the Call which specifies the telephony conference - * the CallPeers of which are to be retrieved - * @return a list of the CallPeers associated with the - * Calls participating in the telephony conference in which the - * specified call is participating - */ - public static List getCallPeers(Call call) - { - CallConference conference = call.getConference(); - List callPeers = new ArrayList(); - - if (conference == null) - { - Iterator callPeerIt = call.getCallPeers(); - - while (callPeerIt.hasNext()) - callPeers.add(callPeerIt.next()); - } - else - conference.getCallPeers(callPeers); - return callPeers; - } - - /** - * Gets the list of Calls participating in the telephony conference - * in which a specific Call is participating. - * - * @param call the Call which participates in the telephony - * conference the list of participating Calls of which is to be - * returned - * @return the list of Calls participating in the telephony - * conference in which the specified call is participating - */ - public static List getCalls(Call call) - { - CallConference conference = call.getConference(); - List calls; - - if (conference == null) - calls = Collections.emptyList(); - else - calls = conference.getCalls(); - return calls; - } - - /** - * Determines whether a CallConference is to report the local - * peer/user as a conference focus judging by a specific list of - * Calls. - * - * @param calls the list of Call which are to be judged whether - * the local peer/user that they represent is to be considered as a - * conference focus - * @return true if the local peer/user represented by the specified - * calls is judged to be a conference focus; otherwise, - * false - */ - private static boolean isConferenceFocus(List calls) - { - int callCount = calls.size(); - boolean conferenceFocus; - - if (callCount < 1) - conferenceFocus = false; - else if (callCount > 1) - conferenceFocus = true; - else - conferenceFocus = (calls.get(0).getCallPeerCount() > 1); - return conferenceFocus; - } - - /** - * The CallChangeListener which listens to changes in the - * Calls participating in this telephony conference. - */ - private final CallChangeListener callChangeListener - = new CallChangeListener() - { - @Override - public void callPeerAdded(CallPeerEvent ev) - { - CallConference.this.onCallPeerEvent(ev); - } - - @Override - public void callPeerRemoved(CallPeerEvent ev) - { - CallConference.this.onCallPeerEvent(ev); - } - - @Override - public void callStateChanged(CallChangeEvent ev) - { - CallConference.this.callStateChanged(ev); - } - }; - - /** - * The list of CallChangeListeners added to the Calls - * participating in this telephony conference via - * {@link #addCallChangeListener(CallChangeListener)}. - */ - private final List callChangeListeners - = new LinkedList(); - - /** - * The CallPeerConferenceListener which listens to the - * CallPeers associated with the Calls participating in - * this telephony conference. - */ - private final CallPeerConferenceListener callPeerConferenceListener - = new CallPeerConferenceAdapter() - { - /** - * {@inheritDoc} - * - * Invokes - * {@link CallConference#onCallPeerConferenceEvent( - * CallPeerConferenceEvent)}. - */ - @Override - protected void onCallPeerConferenceEvent(CallPeerConferenceEvent ev) - { - CallConference.this.onCallPeerConferenceEvent(ev); - } - - /** - * {@inheritDoc} - * - * Invokes - * {@link CallConference#onCallPeerConferenceEvent( - * CallPeerConferenceEvent)}. - */ - @Override - public void conferenceMemberErrorReceived( - CallPeerConferenceEvent ev) - { - CallConference.this.onCallPeerConferenceEvent(ev); - } - }; - - /** - * The list of CallPeerConferenceListeners added to the - * CallPeers associated with the CallPeers participating - * in this telephony conference via - * {@link #addCallPeerConferenceListener}. - */ - private final List callPeerConferenceListeners - = new LinkedList(); - - /** - * The synchronization root/Object which protects the access to - * {@link #immutableCalls} and {@link #mutableCalls}. - */ - private final Object callsSyncRoot = new Object(); - - /** - * The indicator which determines whether the local peer represented by this - * instance and the Calls participating in it is acting as a - * conference focus. The SIP protocol, for example, will add the - * "isfocus" parameter to the Contact headers of its outgoing - * signaling if true. - */ - private boolean conferenceFocus = false; - - /** - * The list of Calls participating in this telephony conference as - * an immutable List which can be exposed out of this instance - * without the need to make a copy. In other words, it is an unmodifiable - * view of {@link #mutableCalls}. - */ - private List immutableCalls; - - /** - * The indicator which determines whether the telephony conference - * represented by this instance is utilizing the Jitsi Videobridge - * server-side telephony conferencing technology. - */ - private final boolean jitsiVideobridge; - - /** - * The list of Calls participating in this telephony conference as - * a mutable List which should not be exposed out of this instance. - */ - private List mutableCalls; - - /** - * Initializes a new CallConference instance. - */ - public CallConference() - { - this(false); - } - - /** - * Initializes a new CallConference instance which is to optionally - * utilize the Jitsi Videobridge server-side telephony conferencing - * technology. - * - * @param jitsiVideobridge true if the telephony conference - * represented by the new instance is to utilize the Jitsi Videobridge - * server-side telephony conferencing technology; otherwise, false - */ - public CallConference(boolean jitsiVideobridge) - { - this.jitsiVideobridge = jitsiVideobridge; - - mutableCalls = new ArrayList(); - immutableCalls = Collections.unmodifiableList(mutableCalls); - } - - /** - * Adds a specific Call to the list of Calls participating - * in this telephony conference. - * - * @param call the Call to add to the list of Calls - * participating in this telephony conference - * @return true if the list of Calls participating in this - * telephony conference changed as a result of the method call; otherwise, - * false - * @throws NullPointerException if call is null - */ - boolean addCall(Call call) - { - if (call == null) - throw new NullPointerException("call"); - - synchronized (callsSyncRoot) - { - if (mutableCalls.contains(call)) - return false; - - /* - * Implement the List of Calls participating in this telephony - * conference as a copy-on-write storage in order to optimize the - * getCalls method which is likely to be executed much more often - * than the addCall and removeCall methods. - */ - List newMutableCalls = new ArrayList(mutableCalls); - - if (newMutableCalls.add(call)) - { - mutableCalls = newMutableCalls; - immutableCalls = Collections.unmodifiableList(mutableCalls); - } - else - return false; - } - - callAdded(call); - return true; - } - - /** - * Adds a CallChangeListener to the Calls participating in - * this telephony conference. The method is a convenience that takes on the - * responsibility of tracking the Calls that get added/removed - * to/from this telephony conference. - * - * @param listener the CallChangeListner to be added to the - * Calls participating in this telephony conference - * @throws NullPointerException if listener is null - */ - public void addCallChangeListener(CallChangeListener listener) - { - if (listener == null) - throw new NullPointerException("listener"); - else - { - synchronized (callChangeListeners) - { - if (!callChangeListeners.contains(listener)) - callChangeListeners.add(listener); - } - } - } - - /** - * Adds {@link #callPeerConferenceListener} to the CallPeers - * associated with a specific Call. - * - * @param call the Call to whose associated CallPeers - * callPeerConferenceListener is to be added - */ - private void addCallPeerConferenceListener(Call call) - { - Iterator callPeerIter = call.getCallPeers(); - - while (callPeerIter.hasNext()) - { - callPeerIter.next().addCallPeerConferenceListener( - callPeerConferenceListener); - } - } - - /** - * Adds a CallPeerConferenceListener to the CallPeers - * associated with the Calls participating in this telephony - * conference. The method is a convenience that takes on the responsibility - * of tracking the Calls that get added/removed to/from this - * telephony conference and the CallPeer that get added/removed - * to/from these Calls. - * - * @param listener the CallPeerConferenceListener to be added to - * the CallPeers associated with the Calls participating - * in this telephony conference - * @throws NullPointerException if listener is null - */ - public void addCallPeerConferenceListener( - CallPeerConferenceListener listener) - { - if (listener == null) - throw new NullPointerException("listener"); - else - { - synchronized (callPeerConferenceListeners) - { - if (!callPeerConferenceListeners.contains(listener)) - callPeerConferenceListeners.add(listener); - } - } - } - - /** - * Notifies this CallConference that a specific Call has - * been added to the list of Calls participating in this telephony - * conference. - * - * @param call the Call which has been added to the list of - * Calls participating in this telephony conference - */ - protected void callAdded(Call call) - { - call.addCallChangeListener(callChangeListener); - addCallPeerConferenceListener(call); - - /* - * Update the conferenceFocus state. Because the public - * setConferenceFocus method allows forcing a specific value on the - * state in question and because it does not sound right to have the - * adding of a Call set conferenceFocus to false, only update it if the - * new conferenceFocus value is true, - */ - boolean conferenceFocus = isConferenceFocus(getCalls()); - - if (conferenceFocus) - setConferenceFocus(conferenceFocus); - - firePropertyChange(CALLS, null, call); - } - - /** - * Notifies this CallConference that a specific Call has - * been removed from the list of Calls participating in this - * telephony conference. - * - * @param call the Call which has been removed from the list of - * Calls participating in this telephony conference - */ - protected void callRemoved(Call call) - { - call.removeCallChangeListener(callChangeListener); - removeCallPeerConferenceListener(call); - - /* - * Update the conferenceFocus state. Following the line of thinking - * expressed in the callAdded method, only update it if the new - * conferenceFocus value is false. - */ - boolean conferenceFocus = isConferenceFocus(getCalls()); - - if (!conferenceFocus) - setConferenceFocus(conferenceFocus); - - firePropertyChange(CALLS, call, null); - } - - /** - * Notifies this telephony conference that the CallState of a - * Call has changed. - * - * @param ev a CallChangeEvent which specifies the Call - * which had its CallState changed and the old and new - * CallStates of that Call - */ - private void callStateChanged(CallChangeEvent ev) - { - Call call = ev.getSourceCall(); - - if (containsCall(call)) - { - try - { - // Forward the CallChangeEvent to the callChangeListeners. - for (CallChangeListener l : getCallChangeListeners()) - l.callStateChanged(ev); - } - finally - { - if (CallChangeEvent.CALL_STATE_CHANGE - .equals(ev.getPropertyName()) - && CallState.CALL_ENDED.equals(ev.getNewValue())) - { - /* - * Should not be vital because Call will remove itself. - * Anyway, do it for the sake of completeness. - */ - removeCall(call); - } - } - } - } - - /** - * Notifies this CallConference that the value of its - * conferenceFocus property has changed from a specific old value - * to a specific new value. - * - * @param oldValue the value of the conferenceFocus property of - * this instance before the change - * @param newValue the value of the conferenceFocus property of - * this instance after the change - */ - protected void conferenceFocusChanged(boolean oldValue, boolean newValue) - { - firePropertyChange(Call.CONFERENCE_FOCUS, oldValue, newValue); - } - - /** - * Determines whether a specific Call is participating in this - * telephony conference. - * - * @param call the Call which is to be checked whether it is - * participating in this telephony conference - * @return true if the specified call is participating in - * this telephony conference - */ - public boolean containsCall(Call call) - { - synchronized (callsSyncRoot) - { - return mutableCalls.contains(call); - } - } - - /** - * Gets the list of CallChangeListeners added to the Calls - * participating in this telephony conference via - * {@link #addCallChangeListener(CallChangeListener)}. - * - * @return the list of CallChangeListeners added to the - * Calls participating in this telephony conference via - * {@link #addCallChangeListener(CallChangeListener)} - */ - private CallChangeListener[] getCallChangeListeners() - { - synchronized (callChangeListeners) - { - return - callChangeListeners.toArray( - new CallChangeListener[callChangeListeners.size()]); - } - } - - /** - * Gets the number of Calls that are participating in this - * telephony conference. - * - * @return the number of Calls that are participating in this - * telephony conference - */ - public int getCallCount() - { - synchronized (callsSyncRoot) - { - return mutableCalls.size(); - } - } - - /** - * Gets the list of CallPeerConferenceListeners added to the - * CallPeers associated with the Calls participating in - * this telephony conference via - * {@link #addCallPeerConferenceListener(CallPeerConferenceListener)}. - * - * @return the list of CallPeerConferenceListeners added to the - * CallPeers associated with the Calls participating in - * this telephony conference via - * {@link #addCallPeerConferenceListener(CallPeerConferenceListener)} - */ - private CallPeerConferenceListener[] getCallPeerConferenceListeners() - { - synchronized (callPeerConferenceListeners) - { - return - callPeerConferenceListeners.toArray( - new CallPeerConferenceListener[ - callPeerConferenceListeners.size()]); - } - } - - /** - * Gets the number of CallPeers associated with the Calls - * participating in this telephony conference. - * - * @return the number of CallPeers associated with the - * Calls participating in this telephony conference - */ - public int getCallPeerCount() - { - int callPeerCount = 0; - - for (Call call : getCalls()) - callPeerCount += call.getCallPeerCount(); - return callPeerCount; - } - - /** - * Gets a list of the CallPeers associated with the Calls - * participating in this telephony conference. - * - * @return a list of the CallPeers associated with the - * Calls participating in this telephony conference - */ - public List getCallPeers() - { - List callPeers = new ArrayList(); - - getCallPeers(callPeers); - return callPeers; - } - - /** - * Adds the CallPeers associated with the Calls - * participating in this telephony conference into a specific List. - * - * @param callPeers a List into which the CallPeers - * associated with the Calls participating in this telephony - * conference are to be added - */ - protected void getCallPeers(List callPeers) - { - for (Call call : getCalls()) - { - Iterator callPeerIt = call.getCallPeers(); - - while (callPeerIt.hasNext()) - callPeers.add(callPeerIt.next()); - } - } - - /** - * Gets the list of Call participating in this telephony - * conference. - * - * @return the list of Calls participating in this telephony - * conference. An empty array of Call element type is returned if - * there are no Calls in this telephony conference-related state. - */ - public List getCalls() - { - synchronized (callsSyncRoot) - { - return immutableCalls; - } - } - - /** - * Determines whether the local peer/user associated with this instance and - * represented by the Calls participating into it is acting as a - * conference focus. - * - * @return true if the local peer/user associated by this instance - * is acting as a conference focus; otherwise, false - */ - public boolean isConferenceFocus() - { - return conferenceFocus; - } - - /** - * Determines whether the current state of this instance suggests that the - * telephony conference it represents has ended. Iterates over the - * Calls participating in this telephony conference and looks for a - * Call which is not in the {@link CallState#CALL_ENDED} state. - * - * @return true if the current state of this instance suggests that - * the telephony conference it represents has ended; otherwise, - * false - */ - public boolean isEnded() - { - for (Call call : getCalls()) - { - if (!CallState.CALL_ENDED.equals(call.getCallState())) - return false; - } - return true; - } - - /** - * Determines whether the telephony conference represented by this instance - * is utilizing the Jitsi Videobridge server-side telephony conferencing - * technology. - * - * @return true if the telephony conference represented by this - * instance is utilizing the Jitsi Videobridge server-side telephony - * conferencing technology - */ - public boolean isJitsiVideobridge() - { - return jitsiVideobridge; - } - - /** - * Notifies this telephony conference that a - * CallPeerConferenceEvent was fired by a CallPeer - * associated with a Call participating in this telephony - * conference. Forwards the specified CallPeerConferenceEvent to - * {@link #callPeerConferenceListeners}. - * - * @param ev the CallPeerConferenceEvent which was fired - */ - private void onCallPeerConferenceEvent(CallPeerConferenceEvent ev) - { - int eventID = ev.getEventID(); - - for (CallPeerConferenceListener l : getCallPeerConferenceListeners()) - { - switch (eventID) - { - case CallPeerConferenceEvent.CONFERENCE_FOCUS_CHANGED: - l.conferenceFocusChanged(ev); - break; - case CallPeerConferenceEvent.CONFERENCE_MEMBER_ADDED: - l.conferenceMemberAdded(ev); - break; - case CallPeerConferenceEvent.CONFERENCE_MEMBER_REMOVED: - l.conferenceMemberRemoved(ev); - break; - case CallPeerConferenceEvent.CONFERENCE_MEMBER_ERROR_RECEIVED: - l.conferenceMemberErrorReceived(ev); - break; - default: - throw new UnsupportedOperationException( - "Unsupported CallPeerConferenceEvent eventID."); - } - } - } - - /** - * Notifies this telephony conference about a specific - * CallPeerEvent i.e. that a CallPeer was either added to - * or removed from a Call. - * - * @param ev a CallPeerEvent which specifies the CallPeer - * which was added or removed and the Call to which it was added or - * from which is was removed - */ - private void onCallPeerEvent(CallPeerEvent ev) - { - Call call = ev.getSourceCall(); - - if (containsCall(call)) - { - /* - * Update the conferenceFocus state. Following the line of thinking - * expressed in the callAdded and callRemoved methods, only update - * it if the new conferenceFocus value is in accord with the - * expectations. - */ - int eventID = ev.getEventID(); - boolean conferenceFocus = isConferenceFocus(getCalls()); - - switch (eventID) - { - case CallPeerEvent.CALL_PEER_ADDED: - if (conferenceFocus) - setConferenceFocus(conferenceFocus); - break; - case CallPeerEvent.CALL_PEER_REMOVED: - if (!conferenceFocus) - setConferenceFocus(conferenceFocus); - break; - default: - /* - * We're interested in the adding and removing of CallPeers - * only. - */ - break; - } - - try - { - // Forward the CallPeerEvent to the callChangeListeners. - for (CallChangeListener l : getCallChangeListeners()) - { - switch (eventID) - { - case CallPeerEvent.CALL_PEER_ADDED: - l.callPeerAdded(ev); - break; - case CallPeerEvent.CALL_PEER_REMOVED: - l.callPeerRemoved(ev); - break; - default: - break; - } - } - } - finally - { - /* - * Add/remove the callPeerConferenceListener to/from the source - * CallPeer (for the purposes of the - * addCallPeerConferenceListener method of this CallConference). - */ - CallPeer callPeer = ev.getSourceCallPeer(); - - switch (eventID) - { - case CallPeerEvent.CALL_PEER_ADDED: - callPeer.addCallPeerConferenceListener( - callPeerConferenceListener); - break; - case CallPeerEvent.CALL_PEER_REMOVED: - callPeer.removeCallPeerConferenceListener( - callPeerConferenceListener); - break; - default: - break; - } - } - } - } - - /** - * Removes a specific Call from the list of Calls - * participating in this telephony conference. - * - * @param call the Call to remove from the list of Calls - * participating in this telephony conference - * @return true if the list of Calls participating in this - * telephony conference changed as a result of the method call; otherwise, - * false - */ - boolean removeCall(Call call) - { - if (call == null) - return false; - - synchronized (callsSyncRoot) - { - if (!mutableCalls.contains(call)) - return false; - - /* - * Implement the List of Calls participating in this telephony - * conference as a copy-on-write storage in order to optimize the - * getCalls method which is likely to be executed much more often - * than the addCall and removeCall methods. - */ - List newMutableCalls = new ArrayList(mutableCalls); - - if (newMutableCalls.remove(call)) - { - mutableCalls = newMutableCalls; - immutableCalls = Collections.unmodifiableList(mutableCalls); - } - else - return false; - } - - callRemoved(call); - return true; - } - - /** - * Removes a CallChangeListener from the Calls - * participating in this telephony conference. - * - * @param listener the CallChangeListener to be removed from the - * Calls participating in this telephony conference - * @see #addCallChangeListener(CallChangeListener) - */ - public void removeCallChangeListener(CallChangeListener listener) - { - if (listener != null) - { - synchronized (callChangeListeners) - { - callChangeListeners.remove(listener); - } - } - } - - /** - * Removes {@link #callPeerConferenceListener} from the CallPeers - * associated with a specific Call. - * - * @param call the Call from whose associated CallPeers - * callPeerConferenceListener is to be removed - */ - private void removeCallPeerConferenceListener(Call call) - { - Iterator callPeerIter = call.getCallPeers(); - - while (callPeerIter.hasNext()) - { - callPeerIter.next().removeCallPeerConferenceListener( - callPeerConferenceListener); - } - } - - /** - * Removes a CallPeerConferenceListener from the CallPeers - * associated with the Calls participating in this telephony - * conference. - * - * @param listener the CallPeerConferenceListener to be removed - * from the CallPeers associated with the Calls - * participating in this telephony conference - * @see #addCallPeerConferenceListener(CallPeerConferenceListener) - */ - public void removeCallPeerConferenceListener( - CallPeerConferenceListener listener) - { - if (listener != null) - { - synchronized (callPeerConferenceListeners) - { - callPeerConferenceListeners.remove(listener); - } - } - } - - /** - * Sets the indicator which determines whether the local peer represented by - * this instance and the Calls participating in it is acting as a - * conference focus (and thus may, for example, need to send the - * corresponding parameters in its outgoing signaling). - * - * @param conferenceFocus true if the local peer represented by - * this instance and the Calls participating in it is to act as a - * conference focus; otherwise, false - */ - public void setConferenceFocus(boolean conferenceFocus) - { - if (this.conferenceFocus != conferenceFocus) - { - boolean oldValue = isConferenceFocus(); - - this.conferenceFocus = conferenceFocus; - - boolean newValue = isConferenceFocus(); - - if (oldValue != newValue) - conferenceFocusChanged(oldValue, newValue); - } - } -} +package net.java.sip.communicator.service.protocol; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.event.*; + +import org.jitsi.util.event.*; + +/** + * Represents the telephony conference-related state of a Call. + * Multiple Call instances share a single CallConference + * instance when the former are into a telephony conference i.e. the local + * peer/user is the conference focus. CallConference is + * protocol-agnostic and thus enables cross-protocol conferences. Since a + * non-conference Call may be converted into a conference Call + * at any time, every Call instance maintains a CallConference + * instance regardless of whether the Call in question is participating + * in a telephony conference. + * + * @author Lyubomir Marinov + */ +public class CallConference + extends PropertyChangeNotifier +{ + /** + * The name of the CallConference property which specifies the list + * of Calls participating in a telephony conference. A change in + * the value of the property is delivered in the form of a + * PropertyChangeEvent which has its oldValue or + * newValue set to the Call which has been removed or + * added to the list of Calls participating in the telephony + * conference. + */ + public static final String CALLS = "calls"; + + /** + * Gets the number of CallPeers associated with the Calls + * participating in the telephony conference-related state of a specific + * Call. + * + * @param call the Call for which the number of CallPeers + * associated with the Calls participating in its associated + * telephony conference-related state + * @return the number of CallPeers associated with the + * Calls participating in the telephony conference-related state + * of the specified Call + */ + public static int getCallPeerCount(Call call) + { + CallConference conference = call.getConference(); + + /* + * A Call instance is supposed to always maintain a CallConference + * instance. Anyway, if it turns out that it is not the case, we will + * consider the Call as a representation of a telephony conference. + */ + return + (conference == null) + ? call.getCallPeerCount() + : conference.getCallPeerCount(); + } + + /** + * Gets a list of the CallPeers associated with the Calls + * participating in the telephony conference in which a specific + * Call is participating. + * + * @param call the Call which specifies the telephony conference + * the CallPeers of which are to be retrieved + * @return a list of the CallPeers associated with the + * Calls participating in the telephony conference in which the + * specified call is participating + */ + public static List getCallPeers(Call call) + { + CallConference conference = call.getConference(); + List callPeers = new ArrayList(); + + if (conference == null) + { + Iterator callPeerIt = call.getCallPeers(); + + while (callPeerIt.hasNext()) + callPeers.add(callPeerIt.next()); + } + else + conference.getCallPeers(callPeers); + return callPeers; + } + + /** + * Gets the list of Calls participating in the telephony conference + * in which a specific Call is participating. + * + * @param call the Call which participates in the telephony + * conference the list of participating Calls of which is to be + * returned + * @return the list of Calls participating in the telephony + * conference in which the specified call is participating + */ + public static List getCalls(Call call) + { + CallConference conference = call.getConference(); + List calls; + + if (conference == null) + calls = Collections.emptyList(); + else + calls = conference.getCalls(); + return calls; + } + + /** + * Determines whether a CallConference is to report the local + * peer/user as a conference focus judging by a specific list of + * Calls. + * + * @param calls the list of Call which are to be judged whether + * the local peer/user that they represent is to be considered as a + * conference focus + * @return true if the local peer/user represented by the specified + * calls is judged to be a conference focus; otherwise, + * false + */ + private static boolean isConferenceFocus(List calls) + { + int callCount = calls.size(); + boolean conferenceFocus; + + if (callCount < 1) + conferenceFocus = false; + else if (callCount > 1) + conferenceFocus = true; + else + conferenceFocus = (calls.get(0).getCallPeerCount() > 1); + return conferenceFocus; + } + + /** + * The CallChangeListener which listens to changes in the + * Calls participating in this telephony conference. + */ + private final CallChangeListener callChangeListener + = new CallChangeListener() + { + @Override + public void callPeerAdded(CallPeerEvent ev) + { + CallConference.this.onCallPeerEvent(ev); + } + + @Override + public void callPeerRemoved(CallPeerEvent ev) + { + CallConference.this.onCallPeerEvent(ev); + } + + @Override + public void callStateChanged(CallChangeEvent ev) + { + CallConference.this.callStateChanged(ev); + } + }; + + /** + * The list of CallChangeListeners added to the Calls + * participating in this telephony conference via + * {@link #addCallChangeListener(CallChangeListener)}. + */ + private final List callChangeListeners + = new LinkedList(); + + /** + * The CallPeerConferenceListener which listens to the + * CallPeers associated with the Calls participating in + * this telephony conference. + */ + private final CallPeerConferenceListener callPeerConferenceListener + = new CallPeerConferenceAdapter() + { + /** + * {@inheritDoc} + * + * Invokes + * {@link CallConference#onCallPeerConferenceEvent( + * CallPeerConferenceEvent)}. + */ + @Override + protected void onCallPeerConferenceEvent(CallPeerConferenceEvent ev) + { + CallConference.this.onCallPeerConferenceEvent(ev); + } + + /** + * {@inheritDoc} + * + * Invokes + * {@link CallConference#onCallPeerConferenceEvent( + * CallPeerConferenceEvent)}. + */ + @Override + public void conferenceMemberErrorReceived( + CallPeerConferenceEvent ev) + { + CallConference.this.onCallPeerConferenceEvent(ev); + } + }; + + /** + * The list of CallPeerConferenceListeners added to the + * CallPeers associated with the CallPeers participating + * in this telephony conference via + * {@link #addCallPeerConferenceListener}. + */ + private final List callPeerConferenceListeners + = new LinkedList(); + + /** + * The synchronization root/Object which protects the access to + * {@link #immutableCalls} and {@link #mutableCalls}. + */ + private final Object callsSyncRoot = new Object(); + + /** + * The indicator which determines whether the local peer represented by this + * instance and the Calls participating in it is acting as a + * conference focus. The SIP protocol, for example, will add the + * "isfocus" parameter to the Contact headers of its outgoing + * signaling if true. + */ + private boolean conferenceFocus = false; + + /** + * The list of Calls participating in this telephony conference as + * an immutable List which can be exposed out of this instance + * without the need to make a copy. In other words, it is an unmodifiable + * view of {@link #mutableCalls}. + */ + private List immutableCalls; + + /** + * The indicator which determines whether the telephony conference + * represented by this instance is utilizing the Jitsi Videobridge + * server-side telephony conferencing technology. + */ + private final boolean jitsiVideobridge; + + /** + * The list of Calls participating in this telephony conference as + * a mutable List which should not be exposed out of this instance. + */ + private List mutableCalls; + + /** + * Initializes a new CallConference instance. + */ + public CallConference() + { + this(false); + } + + /** + * Initializes a new CallConference instance which is to optionally + * utilize the Jitsi Videobridge server-side telephony conferencing + * technology. + * + * @param jitsiVideobridge true if the telephony conference + * represented by the new instance is to utilize the Jitsi Videobridge + * server-side telephony conferencing technology; otherwise, false + */ + public CallConference(boolean jitsiVideobridge) + { + this.jitsiVideobridge = jitsiVideobridge; + + mutableCalls = new ArrayList(); + immutableCalls = Collections.unmodifiableList(mutableCalls); + } + + /** + * Adds a specific Call to the list of Calls participating + * in this telephony conference. + * + * @param call the Call to add to the list of Calls + * participating in this telephony conference + * @return true if the list of Calls participating in this + * telephony conference changed as a result of the method call; otherwise, + * false + * @throws NullPointerException if call is null + */ + boolean addCall(Call call) + { + if (call == null) + throw new NullPointerException("call"); + + synchronized (callsSyncRoot) + { + if (mutableCalls.contains(call)) + return false; + + /* + * Implement the List of Calls participating in this telephony + * conference as a copy-on-write storage in order to optimize the + * getCalls method which is likely to be executed much more often + * than the addCall and removeCall methods. + */ + List newMutableCalls = new ArrayList(mutableCalls); + + if (newMutableCalls.add(call)) + { + mutableCalls = newMutableCalls; + immutableCalls = Collections.unmodifiableList(mutableCalls); + } + else + return false; + } + + callAdded(call); + return true; + } + + /** + * Adds a CallChangeListener to the Calls participating in + * this telephony conference. The method is a convenience that takes on the + * responsibility of tracking the Calls that get added/removed + * to/from this telephony conference. + * + * @param listener the CallChangeListner to be added to the + * Calls participating in this telephony conference + * @throws NullPointerException if listener is null + */ + public void addCallChangeListener(CallChangeListener listener) + { + if (listener == null) + throw new NullPointerException("listener"); + else + { + synchronized (callChangeListeners) + { + if (!callChangeListeners.contains(listener)) + callChangeListeners.add(listener); + } + } + } + + /** + * Adds {@link #callPeerConferenceListener} to the CallPeers + * associated with a specific Call. + * + * @param call the Call to whose associated CallPeers + * callPeerConferenceListener is to be added + */ + private void addCallPeerConferenceListener(Call call) + { + Iterator callPeerIter = call.getCallPeers(); + + while (callPeerIter.hasNext()) + { + callPeerIter.next().addCallPeerConferenceListener( + callPeerConferenceListener); + } + } + + /** + * Adds a CallPeerConferenceListener to the CallPeers + * associated with the Calls participating in this telephony + * conference. The method is a convenience that takes on the responsibility + * of tracking the Calls that get added/removed to/from this + * telephony conference and the CallPeer that get added/removed + * to/from these Calls. + * + * @param listener the CallPeerConferenceListener to be added to + * the CallPeers associated with the Calls participating + * in this telephony conference + * @throws NullPointerException if listener is null + */ + public void addCallPeerConferenceListener( + CallPeerConferenceListener listener) + { + if (listener == null) + throw new NullPointerException("listener"); + else + { + synchronized (callPeerConferenceListeners) + { + if (!callPeerConferenceListeners.contains(listener)) + callPeerConferenceListeners.add(listener); + } + } + } + + /** + * Notifies this CallConference that a specific Call has + * been added to the list of Calls participating in this telephony + * conference. + * + * @param call the Call which has been added to the list of + * Calls participating in this telephony conference + */ + protected void callAdded(Call call) + { + call.addCallChangeListener(callChangeListener); + addCallPeerConferenceListener(call); + + /* + * Update the conferenceFocus state. Because the public + * setConferenceFocus method allows forcing a specific value on the + * state in question and because it does not sound right to have the + * adding of a Call set conferenceFocus to false, only update it if the + * new conferenceFocus value is true, + */ + boolean conferenceFocus = isConferenceFocus(getCalls()); + + if (conferenceFocus) + setConferenceFocus(conferenceFocus); + + firePropertyChange(CALLS, null, call); + } + + /** + * Notifies this CallConference that a specific Call has + * been removed from the list of Calls participating in this + * telephony conference. + * + * @param call the Call which has been removed from the list of + * Calls participating in this telephony conference + */ + protected void callRemoved(Call call) + { + call.removeCallChangeListener(callChangeListener); + removeCallPeerConferenceListener(call); + + /* + * Update the conferenceFocus state. Following the line of thinking + * expressed in the callAdded method, only update it if the new + * conferenceFocus value is false. + */ + boolean conferenceFocus = isConferenceFocus(getCalls()); + + if (!conferenceFocus) + setConferenceFocus(conferenceFocus); + + firePropertyChange(CALLS, call, null); + } + + /** + * Notifies this telephony conference that the CallState of a + * Call has changed. + * + * @param ev a CallChangeEvent which specifies the Call + * which had its CallState changed and the old and new + * CallStates of that Call + */ + private void callStateChanged(CallChangeEvent ev) + { + Call call = ev.getSourceCall(); + + if (containsCall(call)) + { + try + { + // Forward the CallChangeEvent to the callChangeListeners. + for (CallChangeListener l : getCallChangeListeners()) + l.callStateChanged(ev); + } + finally + { + if (CallChangeEvent.CALL_STATE_CHANGE + .equals(ev.getPropertyName()) + && CallState.CALL_ENDED.equals(ev.getNewValue())) + { + /* + * Should not be vital because Call will remove itself. + * Anyway, do it for the sake of completeness. + */ + removeCall(call); + } + } + } + } + + /** + * Notifies this CallConference that the value of its + * conferenceFocus property has changed from a specific old value + * to a specific new value. + * + * @param oldValue the value of the conferenceFocus property of + * this instance before the change + * @param newValue the value of the conferenceFocus property of + * this instance after the change + */ + protected void conferenceFocusChanged(boolean oldValue, boolean newValue) + { + firePropertyChange(Call.CONFERENCE_FOCUS, oldValue, newValue); + } + + /** + * Determines whether a specific Call is participating in this + * telephony conference. + * + * @param call the Call which is to be checked whether it is + * participating in this telephony conference + * @return true if the specified call is participating in + * this telephony conference + */ + public boolean containsCall(Call call) + { + synchronized (callsSyncRoot) + { + return mutableCalls.contains(call); + } + } + + /** + * Gets the list of CallChangeListeners added to the Calls + * participating in this telephony conference via + * {@link #addCallChangeListener(CallChangeListener)}. + * + * @return the list of CallChangeListeners added to the + * Calls participating in this telephony conference via + * {@link #addCallChangeListener(CallChangeListener)} + */ + private CallChangeListener[] getCallChangeListeners() + { + synchronized (callChangeListeners) + { + return + callChangeListeners.toArray( + new CallChangeListener[callChangeListeners.size()]); + } + } + + /** + * Gets the number of Calls that are participating in this + * telephony conference. + * + * @return the number of Calls that are participating in this + * telephony conference + */ + public int getCallCount() + { + synchronized (callsSyncRoot) + { + return mutableCalls.size(); + } + } + + /** + * Gets the list of CallPeerConferenceListeners added to the + * CallPeers associated with the Calls participating in + * this telephony conference via + * {@link #addCallPeerConferenceListener(CallPeerConferenceListener)}. + * + * @return the list of CallPeerConferenceListeners added to the + * CallPeers associated with the Calls participating in + * this telephony conference via + * {@link #addCallPeerConferenceListener(CallPeerConferenceListener)} + */ + private CallPeerConferenceListener[] getCallPeerConferenceListeners() + { + synchronized (callPeerConferenceListeners) + { + return + callPeerConferenceListeners.toArray( + new CallPeerConferenceListener[ + callPeerConferenceListeners.size()]); + } + } + + /** + * Gets the number of CallPeers associated with the Calls + * participating in this telephony conference. + * + * @return the number of CallPeers associated with the + * Calls participating in this telephony conference + */ + public int getCallPeerCount() + { + int callPeerCount = 0; + + for (Call call : getCalls()) + callPeerCount += call.getCallPeerCount(); + return callPeerCount; + } + + /** + * Gets a list of the CallPeers associated with the Calls + * participating in this telephony conference. + * + * @return a list of the CallPeers associated with the + * Calls participating in this telephony conference + */ + public List getCallPeers() + { + List callPeers = new ArrayList(); + + getCallPeers(callPeers); + return callPeers; + } + + /** + * Adds the CallPeers associated with the Calls + * participating in this telephony conference into a specific List. + * + * @param callPeers a List into which the CallPeers + * associated with the Calls participating in this telephony + * conference are to be added + */ + protected void getCallPeers(List callPeers) + { + for (Call call : getCalls()) + { + Iterator callPeerIt = call.getCallPeers(); + + while (callPeerIt.hasNext()) + callPeers.add(callPeerIt.next()); + } + } + + /** + * Gets the list of Call participating in this telephony + * conference. + * + * @return the list of Calls participating in this telephony + * conference. An empty array of Call element type is returned if + * there are no Calls in this telephony conference-related state. + */ + public List getCalls() + { + synchronized (callsSyncRoot) + { + return immutableCalls; + } + } + + /** + * Determines whether the local peer/user associated with this instance and + * represented by the Calls participating into it is acting as a + * conference focus. + * + * @return true if the local peer/user associated by this instance + * is acting as a conference focus; otherwise, false + */ + public boolean isConferenceFocus() + { + return conferenceFocus; + } + + /** + * Determines whether the current state of this instance suggests that the + * telephony conference it represents has ended. Iterates over the + * Calls participating in this telephony conference and looks for a + * Call which is not in the {@link CallState#CALL_ENDED} state. + * + * @return true if the current state of this instance suggests that + * the telephony conference it represents has ended; otherwise, + * false + */ + public boolean isEnded() + { + for (Call call : getCalls()) + { + if (!CallState.CALL_ENDED.equals(call.getCallState())) + return false; + } + return true; + } + + /** + * Determines whether the telephony conference represented by this instance + * is utilizing the Jitsi Videobridge server-side telephony conferencing + * technology. + * + * @return true if the telephony conference represented by this + * instance is utilizing the Jitsi Videobridge server-side telephony + * conferencing technology + */ + public boolean isJitsiVideobridge() + { + return jitsiVideobridge; + } + + /** + * Notifies this telephony conference that a + * CallPeerConferenceEvent was fired by a CallPeer + * associated with a Call participating in this telephony + * conference. Forwards the specified CallPeerConferenceEvent to + * {@link #callPeerConferenceListeners}. + * + * @param ev the CallPeerConferenceEvent which was fired + */ + private void onCallPeerConferenceEvent(CallPeerConferenceEvent ev) + { + int eventID = ev.getEventID(); + + for (CallPeerConferenceListener l : getCallPeerConferenceListeners()) + { + switch (eventID) + { + case CallPeerConferenceEvent.CONFERENCE_FOCUS_CHANGED: + l.conferenceFocusChanged(ev); + break; + case CallPeerConferenceEvent.CONFERENCE_MEMBER_ADDED: + l.conferenceMemberAdded(ev); + break; + case CallPeerConferenceEvent.CONFERENCE_MEMBER_REMOVED: + l.conferenceMemberRemoved(ev); + break; + case CallPeerConferenceEvent.CONFERENCE_MEMBER_ERROR_RECEIVED: + l.conferenceMemberErrorReceived(ev); + break; + default: + throw new UnsupportedOperationException( + "Unsupported CallPeerConferenceEvent eventID."); + } + } + } + + /** + * Notifies this telephony conference about a specific + * CallPeerEvent i.e. that a CallPeer was either added to + * or removed from a Call. + * + * @param ev a CallPeerEvent which specifies the CallPeer + * which was added or removed and the Call to which it was added or + * from which is was removed + */ + private void onCallPeerEvent(CallPeerEvent ev) + { + Call call = ev.getSourceCall(); + + if (containsCall(call)) + { + /* + * Update the conferenceFocus state. Following the line of thinking + * expressed in the callAdded and callRemoved methods, only update + * it if the new conferenceFocus value is in accord with the + * expectations. + */ + int eventID = ev.getEventID(); + boolean conferenceFocus = isConferenceFocus(getCalls()); + + switch (eventID) + { + case CallPeerEvent.CALL_PEER_ADDED: + if (conferenceFocus) + setConferenceFocus(conferenceFocus); + break; + case CallPeerEvent.CALL_PEER_REMOVED: + if (!conferenceFocus) + setConferenceFocus(conferenceFocus); + break; + default: + /* + * We're interested in the adding and removing of CallPeers + * only. + */ + break; + } + + try + { + // Forward the CallPeerEvent to the callChangeListeners. + for (CallChangeListener l : getCallChangeListeners()) + { + switch (eventID) + { + case CallPeerEvent.CALL_PEER_ADDED: + l.callPeerAdded(ev); + break; + case CallPeerEvent.CALL_PEER_REMOVED: + l.callPeerRemoved(ev); + break; + default: + break; + } + } + } + finally + { + /* + * Add/remove the callPeerConferenceListener to/from the source + * CallPeer (for the purposes of the + * addCallPeerConferenceListener method of this CallConference). + */ + CallPeer callPeer = ev.getSourceCallPeer(); + + switch (eventID) + { + case CallPeerEvent.CALL_PEER_ADDED: + callPeer.addCallPeerConferenceListener( + callPeerConferenceListener); + break; + case CallPeerEvent.CALL_PEER_REMOVED: + callPeer.removeCallPeerConferenceListener( + callPeerConferenceListener); + break; + default: + break; + } + } + } + } + + /** + * Removes a specific Call from the list of Calls + * participating in this telephony conference. + * + * @param call the Call to remove from the list of Calls + * participating in this telephony conference + * @return true if the list of Calls participating in this + * telephony conference changed as a result of the method call; otherwise, + * false + */ + boolean removeCall(Call call) + { + if (call == null) + return false; + + synchronized (callsSyncRoot) + { + if (!mutableCalls.contains(call)) + return false; + + /* + * Implement the List of Calls participating in this telephony + * conference as a copy-on-write storage in order to optimize the + * getCalls method which is likely to be executed much more often + * than the addCall and removeCall methods. + */ + List newMutableCalls = new ArrayList(mutableCalls); + + if (newMutableCalls.remove(call)) + { + mutableCalls = newMutableCalls; + immutableCalls = Collections.unmodifiableList(mutableCalls); + } + else + return false; + } + + callRemoved(call); + return true; + } + + /** + * Removes a CallChangeListener from the Calls + * participating in this telephony conference. + * + * @param listener the CallChangeListener to be removed from the + * Calls participating in this telephony conference + * @see #addCallChangeListener(CallChangeListener) + */ + public void removeCallChangeListener(CallChangeListener listener) + { + if (listener != null) + { + synchronized (callChangeListeners) + { + callChangeListeners.remove(listener); + } + } + } + + /** + * Removes {@link #callPeerConferenceListener} from the CallPeers + * associated with a specific Call. + * + * @param call the Call from whose associated CallPeers + * callPeerConferenceListener is to be removed + */ + private void removeCallPeerConferenceListener(Call call) + { + Iterator callPeerIter = call.getCallPeers(); + + while (callPeerIter.hasNext()) + { + callPeerIter.next().removeCallPeerConferenceListener( + callPeerConferenceListener); + } + } + + /** + * Removes a CallPeerConferenceListener from the CallPeers + * associated with the Calls participating in this telephony + * conference. + * + * @param listener the CallPeerConferenceListener to be removed + * from the CallPeers associated with the Calls + * participating in this telephony conference + * @see #addCallPeerConferenceListener(CallPeerConferenceListener) + */ + public void removeCallPeerConferenceListener( + CallPeerConferenceListener listener) + { + if (listener != null) + { + synchronized (callPeerConferenceListeners) + { + callPeerConferenceListeners.remove(listener); + } + } + } + + /** + * Sets the indicator which determines whether the local peer represented by + * this instance and the Calls participating in it is acting as a + * conference focus (and thus may, for example, need to send the + * corresponding parameters in its outgoing signaling). + * + * @param conferenceFocus true if the local peer represented by + * this instance and the Calls participating in it is to act as a + * conference focus; otherwise, false + */ + public void setConferenceFocus(boolean conferenceFocus) + { + if (this.conferenceFocus != conferenceFocus) + { + boolean oldValue = isConferenceFocus(); + + this.conferenceFocus = conferenceFocus; + + boolean newValue = isConferenceFocus(); + + if (oldValue != newValue) + conferenceFocusChanged(oldValue, newValue); + } + } +} diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetSecureSDesTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetSecureSDesTelephony.java index e0c75fd..f336de1 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetSecureSDesTelephony.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetSecureSDesTelephony.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,15 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -/** - * Marker interface to indicate that a protocol supports SDES encryption. - * - * @author Ingo Bauersachs - */ -public interface OperationSetSecureSDesTelephony - extends OperationSetSecureTelephony -{ - -} +package net.java.sip.communicator.service.protocol; + +/** + * Marker interface to indicate that a protocol supports SDES encryption. + * + * @author Ingo Bauersachs + */ +public interface OperationSetSecureSDesTelephony + extends OperationSetSecureTelephony +{ + +} diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetSecureZrtpTelephony.java b/src/net/java/sip/communicator/service/protocol/OperationSetSecureZrtpTelephony.java index 7213af4..eb5dcdd 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetSecureZrtpTelephony.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetSecureZrtpTelephony.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,15 +15,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -/** - * Marker interface to indicate that a protocol supports ZRTP encryption. - * - * @author Ingo Bauersachs - */ -public interface OperationSetSecureZrtpTelephony - extends OperationSetSecureTelephony -{ - -} +package net.java.sip.communicator.service.protocol; + +/** + * Marker interface to indicate that a protocol supports ZRTP encryption. + * + * @author Ingo Bauersachs + */ +public interface OperationSetSecureZrtpTelephony + extends OperationSetSecureTelephony +{ + +} diff --git a/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java b/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java index df71e0c..fa93ce1 100644 --- a/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java +++ b/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,49 +15,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -/** - * Implements PhoneNumberI18nService which aids the parsing, formatting - * and validating of international phone numbers. - * - * @author Lyubomir Marinov - * @author Vincent Lucas - * @author Damian Minkov - */ -public interface PhoneNumberI18nService -{ - /** - * Normalizes a String which may be a phone number or a identifier - * by removing useless characters and, if necessary, replacing the alpahe - * characters in corresponding dial pad numbers. - * - * @param possibleNumber a String which may represents a phone - * number or an identifier to normalize. - * - * @return a String which is a normalized form of the specified - * possibleNumber. - */ - public String normalize(String possibleNumber); - - /** - * Determines whether two String phone numbers match. - * - * @param aPhoneNumber a String which represents a phone number to - * match to bPhoneNumber - * @param bPhoneNumber a String which represents a phone number to - * match to aPhoneNumber - * @return true if the specified Strings match as phone - * numbers; otherwise, false - */ - public boolean phoneNumbersMatch(String aPhoneNumber, String bPhoneNumber); - - /** - * Indicates if the given string is possibly a phone number. - * - * @param possibleNumber the string to be verified - * @return true if the possibleNumber is a phone number, - * false - otherwise - */ - public boolean isPhoneNumber(String possibleNumber); -} +package net.java.sip.communicator.service.protocol; + +/** + * Implements PhoneNumberI18nService which aids the parsing, formatting + * and validating of international phone numbers. + * + * @author Lyubomir Marinov + * @author Vincent Lucas + * @author Damian Minkov + */ +public interface PhoneNumberI18nService +{ + /** + * Normalizes a String which may be a phone number or a identifier + * by removing useless characters and, if necessary, replacing the alpahe + * characters in corresponding dial pad numbers. + * + * @param possibleNumber a String which may represents a phone + * number or an identifier to normalize. + * + * @return a String which is a normalized form of the specified + * possibleNumber. + */ + public String normalize(String possibleNumber); + + /** + * Determines whether two String phone numbers match. + * + * @param aPhoneNumber a String which represents a phone number to + * match to bPhoneNumber + * @param bPhoneNumber a String which represents a phone number to + * match to aPhoneNumber + * @return true if the specified Strings match as phone + * numbers; otherwise, false + */ + public boolean phoneNumbersMatch(String aPhoneNumber, String bPhoneNumber); + + /** + * Indicates if the given string is possibly a phone number. + * + * @param possibleNumber the string to be verified + * @return true if the possibleNumber is a phone number, + * false - otherwise + */ + public boolean isPhoneNumber(String possibleNumber); +} diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderActivator.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderActivator.java index 60cdf5c..a9d7c7c 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderActivator.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderActivator.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,295 +15,295 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -import net.java.sip.communicator.service.calendar.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -import java.util.*; - -/** - * Implements BundleActivator for the purposes of - * protocol.jar/protocol.provider.manifest.mf and in order to register and start - * services independent of the specifics of a particular protocol. - * - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class ProtocolProviderActivator - implements BundleActivator -{ - /** - * The object used for logging. - */ - private final static Logger logger - = Logger.getLogger(ProtocolProviderActivator.class); - - /** - * The ServiceRegistration of the AccountManager - * implementation registered as a service by this activator and cached so - * that the service in question can be properly disposed of upon stopping - * this activator. - */ - private ServiceRegistration accountManagerServiceRegistration; - - /** - * The account manager. - */ - private static AccountManager accountManager; - - /** - * The BundleContext of the one and only - * ProtocolProviderActivator instance which is currently - * started. - */ - private static BundleContext bundleContext; - - /** - * The ConfigurationService used by the classes in the bundle - * represented by ProtocolProviderActivator. - */ - private static ConfigurationService configurationService; - - /** - * The resource service through which we obtain localized strings. - */ - private static ResourceManagementService resourceService; - - /** - * The calendar service instance. - */ - private static CalendarService calendarService; - - /** - * The SingleCallInProgressPolicy making sure that the - * Calls accessible in the BundleContext of this - * activator will obey to the rule that a new Call should put - * the other existing Calls on hold. - */ - private SingleCallInProgressPolicy singleCallInProgressPolicy; - - /** - * Gets the ConfigurationService to be used by the classes in - * the bundle represented by ProtocolProviderActivator. - * - * @return the ConfigurationService to be used by the classes - * in the bundle represented by - * ProtocolProviderActivator - */ - public static ConfigurationService getConfigurationService() - { - if (configurationService == null) - { - configurationService - = (ConfigurationService) - bundleContext.getService( - bundleContext.getServiceReference( - ConfigurationService.class.getName())); - } - return configurationService; - } - - /** - * Gets the ResourceManagementService to be used by the classes - * in the bundle represented by ProtocolProviderActivator. - * - * @return the ResourceManagementService to be used by the - * classes in the bundle represented by - * ProtocolProviderActivator - */ - public static ResourceManagementService getResourceService() - { - if (resourceService == null) - { - resourceService - = (ResourceManagementService) - bundleContext.getService( - bundleContext.getServiceReference( - ResourceManagementService.class.getName())); - } - return resourceService; - } - - /** - * Gets the CalendarService to be used by the classes - * in the bundle represented by ProtocolProviderActivator. - * - * @return the CalendarService to be used by the - * classes in the bundle represented by - * ProtocolProviderActivator - */ - public static CalendarService getCalendarService() - { - if (calendarService == null) - { - ServiceReference serviceReference - = bundleContext.getServiceReference( - CalendarService.class.getName()); - if(serviceReference == null) - return null; - calendarService - = (CalendarService) - bundleContext.getService(serviceReference); - } - return calendarService; - } - - /** - * Returns a ProtocolProviderFactory for a given protocol - * provider. - * @param protocolName the name of the protocol, which factory we're - * looking for - * @return a ProtocolProviderFactory for a given protocol - * provider - */ - public static ProtocolProviderFactory getProtocolProviderFactory( - String protocolName) - { - String osgiFilter - = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; - ProtocolProviderFactory protocolProviderFactory = null; - - try - { - ServiceReference[] serRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), - osgiFilter); - - if ((serRefs != null) && (serRefs.length != 0)) - { - protocolProviderFactory - = (ProtocolProviderFactory) - bundleContext.getService(serRefs[0]); - } - } - catch (InvalidSyntaxException ex) - { - if (logger.isInfoEnabled()) - logger.info("ProtocolProviderActivator : " + ex); - } - - return protocolProviderFactory; - } - - /** - * Registers a new AccountManagerImpl instance as an - * AccountManager service and starts a new - * SingleCallInProgressPolicy instance to ensure that only one - * of the Calls accessible in the BundleContext - * in which this activator is to execute will be in progress and the others - * will automatically be put on hold. - * - * @param bundleContext the BundleContext in which the bundle - * activation represented by this BundleActivator - * executes - */ - public void start(BundleContext bundleContext) - { - ProtocolProviderActivator.bundleContext = bundleContext; - - accountManager = new AccountManager(bundleContext); - accountManagerServiceRegistration = - bundleContext.registerService(AccountManager.class.getName(), - accountManager, null); - if(logger.isTraceEnabled()) - { - logger.trace("ProtocolProviderActivator will create " - + "SingleCallInProgressPolicy instance."); - } - - singleCallInProgressPolicy = - new SingleCallInProgressPolicy(bundleContext); - } - - /** - * Unregisters the AccountManagerImpl instance registered as an - * AccountManager service in {@link #start(BundleContext)} and - * stops the SingleCallInProgressPolicy started there as well. - * - * @param bundleContext the BundleContext in which the bundle - * activation represented by this BundleActivator - * executes - */ - public void stop(BundleContext bundleContext) - { - if (accountManagerServiceRegistration != null) - { - accountManagerServiceRegistration.unregister(); - accountManagerServiceRegistration = null; - accountManager = null; - } - - if (singleCallInProgressPolicy != null) - { - singleCallInProgressPolicy.dispose(); - singleCallInProgressPolicy = null; - } - - if (bundleContext.equals(ProtocolProviderActivator.bundleContext)) - ProtocolProviderActivator.bundleContext = null; - - configurationService = null; - resourceService = null; - } - - /** - * Returns all protocol providers currently registered. - * @return all protocol providers currently registered. - */ - public static List - getProtocolProviders() - { - ServiceReference[] serRefs = null; - try - { - // get all registered provider factories - serRefs = bundleContext.getServiceReferences( - ProtocolProviderService.class.getName(), - null); - } - catch (InvalidSyntaxException e) - { - logger.error("ProtocolProviderActivator : " + e); - } - - List - providersList = new ArrayList(); - - if (serRefs != null) - { - for (ServiceReference serRef : serRefs) - { - ProtocolProviderService pp - = (ProtocolProviderService)bundleContext.getService(serRef); - - providersList.add(pp); - } - } - return providersList; - } - - /** - * Get the AccountManager of the protocol. - * - * @return AccountManager of the protocol - */ - public static AccountManager getAccountManager() - { - return accountManager; - } - - /** - * Returns OSGI bundle context. - * @return OSGI bundle context. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } -} +package net.java.sip.communicator.service.protocol; + +import net.java.sip.communicator.service.calendar.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +import java.util.*; + +/** + * Implements BundleActivator for the purposes of + * protocol.jar/protocol.provider.manifest.mf and in order to register and start + * services independent of the specifics of a particular protocol. + * + * @author Lubomir Marinov + * @author Yana Stamcheva + */ +public class ProtocolProviderActivator + implements BundleActivator +{ + /** + * The object used for logging. + */ + private final static Logger logger + = Logger.getLogger(ProtocolProviderActivator.class); + + /** + * The ServiceRegistration of the AccountManager + * implementation registered as a service by this activator and cached so + * that the service in question can be properly disposed of upon stopping + * this activator. + */ + private ServiceRegistration accountManagerServiceRegistration; + + /** + * The account manager. + */ + private static AccountManager accountManager; + + /** + * The BundleContext of the one and only + * ProtocolProviderActivator instance which is currently + * started. + */ + private static BundleContext bundleContext; + + /** + * The ConfigurationService used by the classes in the bundle + * represented by ProtocolProviderActivator. + */ + private static ConfigurationService configurationService; + + /** + * The resource service through which we obtain localized strings. + */ + private static ResourceManagementService resourceService; + + /** + * The calendar service instance. + */ + private static CalendarService calendarService; + + /** + * The SingleCallInProgressPolicy making sure that the + * Calls accessible in the BundleContext of this + * activator will obey to the rule that a new Call should put + * the other existing Calls on hold. + */ + private SingleCallInProgressPolicy singleCallInProgressPolicy; + + /** + * Gets the ConfigurationService to be used by the classes in + * the bundle represented by ProtocolProviderActivator. + * + * @return the ConfigurationService to be used by the classes + * in the bundle represented by + * ProtocolProviderActivator + */ + public static ConfigurationService getConfigurationService() + { + if (configurationService == null) + { + configurationService + = (ConfigurationService) + bundleContext.getService( + bundleContext.getServiceReference( + ConfigurationService.class.getName())); + } + return configurationService; + } + + /** + * Gets the ResourceManagementService to be used by the classes + * in the bundle represented by ProtocolProviderActivator. + * + * @return the ResourceManagementService to be used by the + * classes in the bundle represented by + * ProtocolProviderActivator + */ + public static ResourceManagementService getResourceService() + { + if (resourceService == null) + { + resourceService + = (ResourceManagementService) + bundleContext.getService( + bundleContext.getServiceReference( + ResourceManagementService.class.getName())); + } + return resourceService; + } + + /** + * Gets the CalendarService to be used by the classes + * in the bundle represented by ProtocolProviderActivator. + * + * @return the CalendarService to be used by the + * classes in the bundle represented by + * ProtocolProviderActivator + */ + public static CalendarService getCalendarService() + { + if (calendarService == null) + { + ServiceReference serviceReference + = bundleContext.getServiceReference( + CalendarService.class.getName()); + if(serviceReference == null) + return null; + calendarService + = (CalendarService) + bundleContext.getService(serviceReference); + } + return calendarService; + } + + /** + * Returns a ProtocolProviderFactory for a given protocol + * provider. + * @param protocolName the name of the protocol, which factory we're + * looking for + * @return a ProtocolProviderFactory for a given protocol + * provider + */ + public static ProtocolProviderFactory getProtocolProviderFactory( + String protocolName) + { + String osgiFilter + = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; + ProtocolProviderFactory protocolProviderFactory = null; + + try + { + ServiceReference[] serRefs + = bundleContext.getServiceReferences( + ProtocolProviderFactory.class.getName(), + osgiFilter); + + if ((serRefs != null) && (serRefs.length != 0)) + { + protocolProviderFactory + = (ProtocolProviderFactory) + bundleContext.getService(serRefs[0]); + } + } + catch (InvalidSyntaxException ex) + { + if (logger.isInfoEnabled()) + logger.info("ProtocolProviderActivator : " + ex); + } + + return protocolProviderFactory; + } + + /** + * Registers a new AccountManagerImpl instance as an + * AccountManager service and starts a new + * SingleCallInProgressPolicy instance to ensure that only one + * of the Calls accessible in the BundleContext + * in which this activator is to execute will be in progress and the others + * will automatically be put on hold. + * + * @param bundleContext the BundleContext in which the bundle + * activation represented by this BundleActivator + * executes + */ + public void start(BundleContext bundleContext) + { + ProtocolProviderActivator.bundleContext = bundleContext; + + accountManager = new AccountManager(bundleContext); + accountManagerServiceRegistration = + bundleContext.registerService(AccountManager.class.getName(), + accountManager, null); + if(logger.isTraceEnabled()) + { + logger.trace("ProtocolProviderActivator will create " + + "SingleCallInProgressPolicy instance."); + } + + singleCallInProgressPolicy = + new SingleCallInProgressPolicy(bundleContext); + } + + /** + * Unregisters the AccountManagerImpl instance registered as an + * AccountManager service in {@link #start(BundleContext)} and + * stops the SingleCallInProgressPolicy started there as well. + * + * @param bundleContext the BundleContext in which the bundle + * activation represented by this BundleActivator + * executes + */ + public void stop(BundleContext bundleContext) + { + if (accountManagerServiceRegistration != null) + { + accountManagerServiceRegistration.unregister(); + accountManagerServiceRegistration = null; + accountManager = null; + } + + if (singleCallInProgressPolicy != null) + { + singleCallInProgressPolicy.dispose(); + singleCallInProgressPolicy = null; + } + + if (bundleContext.equals(ProtocolProviderActivator.bundleContext)) + ProtocolProviderActivator.bundleContext = null; + + configurationService = null; + resourceService = null; + } + + /** + * Returns all protocol providers currently registered. + * @return all protocol providers currently registered. + */ + public static List + getProtocolProviders() + { + ServiceReference[] serRefs = null; + try + { + // get all registered provider factories + serRefs = bundleContext.getServiceReferences( + ProtocolProviderService.class.getName(), + null); + } + catch (InvalidSyntaxException e) + { + logger.error("ProtocolProviderActivator : " + e); + } + + List + providersList = new ArrayList(); + + if (serRefs != null) + { + for (ServiceReference serRef : serRefs) + { + ProtocolProviderService pp + = (ProtocolProviderService)bundleContext.getService(serRef); + + providersList.add(pp); + } + } + return providersList; + } + + /** + * Get the AccountManager of the protocol. + * + * @return AccountManager of the protocol + */ + public static AccountManager getAccountManager() + { + return accountManager; + } + + /** + * Returns OSGI bundle context. + * @return OSGI bundle context. + */ + public static BundleContext getBundleContext() + { + return bundleContext; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java index 7e8b9c8..2efdc29 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1302 +15,1302 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol; - -import java.lang.reflect.*; -import java.util.*; - -import net.java.sip.communicator.service.credentialsstorage.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * The ProtocolProviderFactory is what actually creates instances of a - * ProtocolProviderService implementation. A provider factory would register, - * persistently store, and remove when necessary, ProtocolProviders. The way - * things are in the SIP Communicator, a user account is represented (in a 1:1 - * relationship) by an AccountID and a ProtocolProvider. In other words - one - * would have as many protocol providers installed in a given moment as they - * would user account registered through the various services. - * - * @author Emil Ivov - * @author Lubomir Marinov - */ -public abstract class ProtocolProviderFactory -{ - /** - * The Logger used by the ProtocolProviderFactory class - * and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(ProtocolProviderFactory.class); - - /** - * Then name of a property which represents a password. - */ - public static final String PASSWORD = "PASSWORD"; - - /** - * The name of a property representing the name of the protocol for an - * ProtocolProviderFactory. - */ - public static final String PROTOCOL = "PROTOCOL_NAME"; - - /** - * The name of a property representing the path to protocol icons. - */ - public static final String PROTOCOL_ICON_PATH = "PROTOCOL_ICON_PATH"; - - /** - * The name of a property representing the path to the account icon to - * be used in the user interface, when the protocol provider service is not - * available. - */ - public static final String ACCOUNT_ICON_PATH = "ACCOUNT_ICON_PATH"; - - /** - * The name of a property which represents the AccountID of a - * ProtocolProvider and that, together with a password is used to login - * on the protocol network.. - */ - public static final String USER_ID = "USER_ID"; - - /** - * The name that should be displayed to others when we are calling or - * writing them. - */ - public static final String DISPLAY_NAME = "DISPLAY_NAME"; - - /** - * The name that should be displayed to the user on call via and chat via - * lists. - */ - public static final String ACCOUNT_DISPLAY_NAME = "ACCOUNT_DISPLAY_NAME"; - - /** - * The name of the property under which we store protocol AccountID-s. - */ - public static final String ACCOUNT_UID = "ACCOUNT_UID"; - - /** - * The name of the property under which we store protocol the address of - * a protocol centric entity (any protocol server). - */ - public static final String SERVER_ADDRESS = "SERVER_ADDRESS"; - - /** - * The name of the property under which we store the number of the port - * where the server stored against the SERVER_ADDRESS property is expecting - * connections to be made via this protocol. - */ - public static final String SERVER_PORT = "SERVER_PORT"; - - /** - * The name of the property under which we store the name of the transport - * protocol that needs to be used to access the server. - */ - public static final String SERVER_TRANSPORT = "SERVER_TRANSPORT"; - - /** - * The name of the property under which we store protocol the address of - * a protocol proxy. - */ - public static final String PROXY_ADDRESS = "PROXY_ADDRESS"; - - /** - * The name of the property under which we store the number of the port - * where the proxy stored against the PROXY_ADDRESS property is expecting - * connections to be made via this protocol. - */ - public static final String PROXY_PORT = "PROXY_PORT"; - - /** - * The name of the property which defines whether proxy is auto configured - * by the protocol by using known methods such as specific DNS queries. - */ - public static final String PROXY_AUTO_CONFIG = "PROXY_AUTO_CONFIG"; - - /** - * The property indicating the preferred UDP and TCP - * port to bind to for clear communications. - */ - public static final String PREFERRED_CLEAR_PORT_PROPERTY_NAME - = "net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT"; - - /** - * The property indicating the preferred TLS (TCP) - * port to bind to for secure communications. - */ - public static final String PREFERRED_SECURE_PORT_PROPERTY_NAME - = "net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT"; - - /** - * The name of the property under which we store the the type of the proxy - * stored against the PROXY_ADDRESS property. Exact type values depend on - * protocols and among them are socks4, socks5, http and possibly others. - */ - public static final String PROXY_TYPE = "PROXY_TYPE"; - - /** - * The name of the property under which we store the the username for the - * proxy stored against the PROXY_ADDRESS property. - */ - public static final String PROXY_USERNAME = "PROXY_USERNAME"; - - /** - * The name of the property under which we store the the authorization name - * for the proxy stored against the PROXY_ADDRESS property. - */ - public static final String AUTHORIZATION_NAME = "AUTHORIZATION_NAME"; - - /** - * The name of the property under which we store the password for the proxy - * stored against the PROXY_ADDRESS property. - */ - public static final String PROXY_PASSWORD = "PROXY_PASSWORD"; - - /** - * The name of the property under which we store the name of the transport - * protocol that needs to be used to access the proxy. - */ - public static final String PROXY_TRANSPORT = "PROXY_TRANSPORT"; - - /** - * The name of the property that indicates whether loose routing should be - * forced for all traffic in an account, rather than routing through an - * outbound proxy which is the default for Jitsi. - */ - public static final String FORCE_PROXY_BYPASS = "FORCE_PROXY_BYPASS"; - - /** - * The name of the property that indicates whether the client must - * be registered with a registrar when making outgoing calls. - */ - public static final String MUST_REGISTER_TO_CALL = "MUST_REGISTER_TO_CALL"; - - /** - * The name of the property under which we store the user preference for a - * transport protocol to use (i.e. tcp or udp). - */ - public static final String PREFERRED_TRANSPORT = "PREFERRED_TRANSPORT"; - - /** - * The name of the property under which we store whether we generate - * resource values or we just use the stored one. - */ - public static final String AUTO_GENERATE_RESOURCE = "AUTO_GENERATE_RESOURCE"; - - /** - * The name of the property under which we store resources such as the - * jabber resource property. - */ - public static final String RESOURCE = "RESOURCE"; - - /** - * The name of the property under which we store resource priority. - */ - public static final String RESOURCE_PRIORITY = "RESOURCE_PRIORITY"; - - /** - * The name of the property which defines that the call is encrypted by - * default - */ - public static final String DEFAULT_ENCRYPTION = "DEFAULT_ENCRYPTION"; - - /** - * The name of the property that indicates the encryption protocols for this - * account. - */ - public static final String ENCRYPTION_PROTOCOL = "ENCRYPTION_PROTOCOL"; - - /** - * The name of the property that indicates the status (enabed or disabled) - * encryption protocols for this account. - */ - public static final String ENCRYPTION_PROTOCOL_STATUS - = "ENCRYPTION_PROTOCOL_STATUS"; - - /** - * The name of the property which defines if to include the ZRTP attribute - * to SIP/SDP - */ - public static final String DEFAULT_SIPZRTP_ATTRIBUTE = - "DEFAULT_SIPZRTP_ATTRIBUTE"; - - /** - * The name of the property which defines the ID of the client TLS - * certificate configuration entry. - */ - public static final String CLIENT_TLS_CERTIFICATE = - "CLIENT_TLS_CERTIFICATE"; - - /** - * The name of the property under which we store the boolean value - * indicating if the user name should be automatically changed if the - * specified name already exists. This property is meant to be used by IRC - * implementations. - */ - public static final String AUTO_CHANGE_USER_NAME = "AUTO_CHANGE_USER_NAME"; - - /** - * The name of the property under which we store the boolean value - * indicating if a password is required. Initially this property is meant to - * be used by IRC implementations. - */ - public static final String NO_PASSWORD_REQUIRED = "NO_PASSWORD_REQUIRED"; - - /** - * The name of the property under which we store if the presence is enabled. - */ - public static final String IS_PRESENCE_ENABLED = "IS_PRESENCE_ENABLED"; - - /** - * The name of the property under which we store if the p2p mode for SIMPLE - * should be forced. - */ - public static final String FORCE_P2P_MODE = "FORCE_P2P_MODE"; - - /** - * The name of the property under which we store the offline contact polling - * period for SIMPLE. - */ - public static final String POLLING_PERIOD = "POLLING_PERIOD"; - - /** - * The name of the property under which we store the chosen default - * subscription expiration value for SIMPLE. - */ - public static final String SUBSCRIPTION_EXPIRATION - = "SUBSCRIPTION_EXPIRATION"; - - /** - * Indicates if the server address has been validated. - */ - public static final String SERVER_ADDRESS_VALIDATED - = "SERVER_ADDRESS_VALIDATED"; - - /** - * Indicates if the server settings are over - */ - public static final String IS_SERVER_OVERRIDDEN - = "IS_SERVER_OVERRIDDEN"; - /** - * Indicates if the proxy address has been validated. - */ - public static final String PROXY_ADDRESS_VALIDATED - = "PROXY_ADDRESS_VALIDATED"; - - /** - * Indicates the search strategy chosen for the DICT protocole. - */ - public static final String STRATEGY = "STRATEGY"; - - /** - * Indicates a protocol that would not be shown in the user interface as an - * account. - */ - public static final String IS_PROTOCOL_HIDDEN = "IS_PROTOCOL_HIDDEN"; - - /** - * Indicates if the given account is the preferred account. - */ - public static final String IS_PREFERRED_PROTOCOL = "IS_PREFERRED_PROTOCOL"; - - /** - * The name of the property that would indicate if a given account is - * currently enabled or disabled. - */ - public static final String IS_ACCOUNT_DISABLED = "IS_ACCOUNT_DISABLED"; - - /** - * The name of the property that would indicate if a given account - * configuration form is currently hidden. - */ - public static final String IS_ACCOUNT_CONFIG_HIDDEN = "IS_CONFIG_HIDDEN"; - - /** - * The name of the property that would indicate if a given account - * status menu is currently hidden. - */ - public static final String IS_ACCOUNT_STATUS_MENU_HIDDEN = - "IS_STATUS_MENU_HIDDEN"; - - /** - * The name of the property that would indicate if a given account - * configuration is read only. - */ - public static final String IS_ACCOUNT_READ_ONLY = "IS_READ_ONLY"; - - /** - * The name of the property that would indicate if a given account - * groups are readonly, values can be all or a comma separated - * group names including root. - */ - public static final String ACCOUNT_READ_ONLY_GROUPS = "READ_ONLY_GROUPS"; - - /** - * Indicates if ICE should be used. - */ - public static final String IS_USE_ICE = "ICE_ENABLED"; - - /** - * Indicates if STUN server should be automatically discovered. - */ - public static final String AUTO_DISCOVER_STUN = "AUTO_DISCOVER_STUN"; - - /** - * Indicates if default STUN server would be used if no other STUN/TURN - * server are available. - */ - public static final String USE_DEFAULT_STUN_SERVER - = "USE_DEFAULT_STUN_SERVER"; - - /** - * The name of the boolean account property which indicates whether Jitsi - * Videobridge is to be used, if available and supported, for conference - * calls. - */ - public static final String USE_JITSI_VIDEO_BRIDGE - = "USE_JITSI_VIDEO_BRIDGE"; - - /** - * The property name prefix for all stun server properties. We generally use - * this prefix in conjunction with an index which is how we store multiple - * servers. - */ - public static final String STUN_PREFIX = "STUN"; - - /** - * The base property name for address of additional STUN servers specified. - */ - public static final String STUN_ADDRESS = "ADDRESS"; - - /** - * The base property name for port of additional STUN servers specified. - */ - public static final String STUN_PORT = "PORT"; - - /** - * The base property name for username of additional STUN servers specified. - */ - public static final String STUN_USERNAME = "USERNAME"; - - /** - * The base property name for password of additional STUN servers specified. - */ - public static final String STUN_PASSWORD = "PASSWORD"; - - /** - * The base property name for the turn supported property of additional - * STUN servers specified. - */ - public static final String STUN_IS_TURN_SUPPORTED = "IS_TURN_SUPPORTED"; - - /** - * Indicates if JingleNodes should be used with ICE. - */ - public static final String IS_USE_JINGLE_NODES = "JINGLE_NODES_ENABLED"; - - /** - * Indicates if JingleNodes should be used with ICE. - */ - public static final String AUTO_DISCOVER_JINGLE_NODES - = "AUTO_DISCOVER_JINGLE_NODES"; - - /** - * Indicates if JingleNodes should use buddies to search for nodes. - */ - public static final String JINGLE_NODES_SEARCH_BUDDIES - = "JINGLE_NODES_SEARCH_BUDDIES"; - - /** - * Indicates if UPnP should be used with ICE. - */ - public static final String IS_USE_UPNP = "UPNP_ENABLED"; - - /** - * Indicates if we allow non-TLS connection. - */ - public static final String IS_ALLOW_NON_SECURE = "ALLOW_NON_SECURE"; - - /** - * Enable notifications for new voicemail messages. - */ - public static final String VOICEMAIL_ENABLED = "VOICEMAIL_ENABLED"; - - /** - * Address used to reach voicemail box, by services able to - * subscribe for voicemail new messages notifications. - */ - public static final String VOICEMAIL_URI = "VOICEMAIL_URI"; - - /** - * Address used to call to hear your messages stored on the server - * for your voicemail. - */ - public static final String VOICEMAIL_CHECK_URI = "VOICEMAIL_CHECK_URI"; - - /** - * Indicates if calling is disabled for a certain account. - */ - public static final String IS_CALLING_DISABLED_FOR_ACCOUNT - = "CALLING_DISABLED"; - - /** - * Indicates if desktop streaming/sharing is disabled for a certain account. - */ - public static final String IS_DESKTOP_STREAMING_DISABLED - = "DESKTOP_STREAMING_DISABLED"; - - /** - * Indicates if desktop remote control is disabled for a certain account. - */ - public static final String IS_DESKTOP_REMOTE_CONTROL_DISABLED - = "DESKTOP_REMOTE_CONTROL_DISABLED"; - - /** - * The sms default server address. - */ - public static final String SMS_SERVER_ADDRESS = "SMS_SERVER_ADDRESS"; - - /** - * Keep-alive method used by the protocol. - */ - public static final String KEEP_ALIVE_METHOD = "KEEP_ALIVE_METHOD"; - - /** - * The interval for keep-alives if any. - */ - public static final String KEEP_ALIVE_INTERVAL = "KEEP_ALIVE_INTERVAL"; - - /** - * The name of the property holding DTMF method. - */ - public static final String DTMF_METHOD = "DTMF_METHOD"; - - /** - * The minimal DTMF tone duration. - */ - public static final String DTMF_MINIMAL_TONE_DURATION - = "DTMF_MINIMAL_TONE_DURATION"; - - /** - * Paranoia mode when turned on requires all calls to be secure and - * indicated as such. - */ - public static final String MODE_PARANOIA = "MODE_PARANOIA"; - - /** - * The name of the "override encodings" property - */ - public static final String OVERRIDE_ENCODINGS = "OVERRIDE_ENCODINGS"; - - /** - * The prefix used to store account encoding properties - */ - public static final String ENCODING_PROP_PREFIX = "Encodings"; - - /** - * An account property to provide a connected account to check for - * its status. Used when the current provider need to reject calls - * but is missing presence operation set and need to check other - * provider for status. - */ - public static final String CUSAX_PROVIDER_ACCOUNT_PROP - = "cusax.XMPP_ACCOUNT_ID"; - - /** - * The BundleContext containing (or to contain) the service - * registration of this factory. - */ - private final BundleContext bundleContext; - - /** - * The name of the protocol this factory registers its - * ProtocolProviderServices with and to be placed in the - * properties of the accounts created by this factory. - */ - private final String protocolName; - - /** - * The table that we store our accounts in. - *

    - * TODO Synchronize the access to the field which may in turn be better - * achieved by also hiding it from protected into private access. - *

    - */ - protected final Map> - registeredAccounts - = new HashMap>(); - - /** - * The name of the property that indicates the AVP type. - *
      - *
    • {@link #SAVP_OFF}
    • - *
    • {@link #SAVP_MANDATORY}
    • - *
    • {@link #SAVP_OPTIONAL}
    • - *
    - */ - public static final String SAVP_OPTION = "SAVP_OPTION"; - - /** - * Always use RTP/AVP - */ - public static final int SAVP_OFF = 0; - - /** - * Always use RTP/SAVP - */ - public static final int SAVP_MANDATORY = 1; - - /** - * Sends two media description, with RTP/SAVP being first. - */ - public static final int SAVP_OPTIONAL = 2; - - /** - * The name of the property that defines the enabled SDES cipher suites. - * Enabled suites are listed as CSV by their RFC name. - */ - public static final String SDES_CIPHER_SUITES = "SDES_CIPHER_SUITES"; - - /** - * The name of the property that defines the enabled/disabled state of - * message carbons. - */ - public static final String IS_CARBON_DISABLED = "CARBON_DISABLED"; - - /** - * Creates a new ProtocolProviderFactory. - * - * @param bundleContext the bundle context reference of the service - * @param protocolName the name of the protocol - */ - protected ProtocolProviderFactory(BundleContext bundleContext, - String protocolName) - { - this.bundleContext = bundleContext; - this.protocolName = protocolName; - } - - /** - * Gets the BundleContext containing (or to contain) the - * service registration of this factory. - * - * @return the BundleContext containing (or to contain) the - * service registration of this factory - */ - public BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Initializes and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. Note that account - * registration is persistent and accounts that are registered during - * a particular sip-communicator session would be automatically reloaded - * during all following sessions until they are removed through the - * removeAccount method. - * - * @param userID the user identifier uniquely representing the newly - * created account within the protocol namespace. - * @param accountProperties a set of protocol (or implementation) specific - * properties defining the new account. - * @return the AccountID of the newly created account. - * @throws java.lang.IllegalArgumentException if userID does not correspond - * to an identifier in the context of the underlying protocol or if - * accountProperties does not contain a complete set of account installation - * properties. - * @throws java.lang.IllegalStateException if the account has already been - * installed. - * @throws java.lang.NullPointerException if any of the arguments is null. - */ - public abstract AccountID installAccount(String userID, - Map accountProperties) - throws IllegalArgumentException, - IllegalStateException, - NullPointerException; - - - /** - * Modifies the account corresponding to the specified accountID. This - * method is meant to be used to change properties of already existing - * accounts. Note that if the given accountID doesn't correspond to any - * registered account this method would do nothing. - * - * @param protocolProvider the protocol provider service corresponding to - * the modified account. - * @param accountProperties a set of protocol (or implementation) specific - * properties defining the new account. - * - * @throws java.lang.NullPointerException if any of the arguments is null. - */ - public abstract void modifyAccount( - ProtocolProviderService protocolProvider, - Map accountProperties) - throws NullPointerException; - - /** - * Returns a copy of the list containing the AccountIDs of all - * accounts currently registered in this protocol provider. - * @return a copy of the list containing the AccountIDs of all - * accounts currently registered in this protocol provider. - */ - public ArrayList getRegisteredAccounts() - { - synchronized (registeredAccounts) - { - return new ArrayList(registeredAccounts.keySet()); - } - } - - /** - * Returns the ServiceReference for the protocol provider corresponding to - * the specified accountID or null if the accountID is unknown. - * @param accountID the accountID of the protocol provider we'd like to get - * @return a ServiceReference object to the protocol provider with the - * specified account id and null if the account id is unknown to the - * provider factory. - */ - public ServiceReference getProviderForAccount( - AccountID accountID) - { - ServiceRegistration registration; - - synchronized (registeredAccounts) - { - registration = registeredAccounts.get(accountID); - } - - try - { - if (registration != null) - return registration.getReference(); - } - catch (IllegalStateException ise) - { - synchronized (registeredAccounts) - { - registeredAccounts.remove(accountID); - } - } - - return null; - } - - /** - * Removes the specified account from the list of accounts that this - * provider factory is handling. If the specified accountID is unknown to - * the ProtocolProviderFactory, the call has no effect and false is - * returned. This method is persistent in nature and once called the account - * corresponding to the specified ID will not be loaded during future runs - * of the project. - * - * @param accountID the ID of the account to remove. - * @return true if an account with the specified ID existed and was removed - * and false otherwise. - */ - public boolean uninstallAccount(AccountID accountID) - { - // Unregister the protocol provider. - ServiceReference serRef - = getProviderForAccount(accountID); - - boolean wasAccountExisting = false; - - // If the protocol provider service is registered, first unregister the - // service. - if (serRef != null) - { - BundleContext bundleContext = getBundleContext(); - ProtocolProviderService protocolProvider - = bundleContext.getService(serRef); - - try - { - protocolProvider.unregister(); - } - catch (OperationFailedException ex) - { - logger.error( - "Failed to unregister protocol provider for account: " - + accountID + " caused by: " + ex); - } - } - - ServiceRegistration registration; - - synchronized (registeredAccounts) - { - registration = registeredAccounts.remove(accountID); - } - - // first remove the stored account so when PP is unregistered we can - // distinguish between deleted or just disabled account - wasAccountExisting = removeStoredAccount(accountID); - - if (registration != null) - { - // Kill the service. - registration.unregister(); - } - - return wasAccountExisting; - } - - /** - * The method stores the specified account in the configuration service - * under the package name of the source factory. The restore and remove - * account methods are to be used to obtain access to and control the stored - * accounts. - *

    - * In order to store all account properties, the method would create an - * entry in the configuration service corresponding (beginning with) the - * sourceFactory's package name and add to it a unique identifier - * (e.g. the current miliseconds.) - *

    - * - * @param accountID the AccountID corresponding to the account that we would - * like to store. - */ - protected void storeAccount(AccountID accountID) - { - this.storeAccount(accountID, true); - } - - /** - * The method stores the specified account in the configuration service - * under the package name of the source factory. The restore and remove - * account methods are to be used to obtain access to and control the stored - * accounts. - *

    - * In order to store all account properties, the method would create an - * entry in the configuration service corresponding (beginning with) the - * sourceFactory's package name and add to it a unique identifier - * (e.g. the current miliseconds.) - *

    - * - * @param accountID the AccountID corresponding to the account that we would - * like to store. - * @param isModification if false there must be no such already - * loaded account, it true ist modification of an existing account. - * Usually we use this method with false in method installAccount - * and with true or the overridden method in method - * modifyAccount. - */ - protected void storeAccount(AccountID accountID, boolean isModification) - { - if(!isModification - && getAccountManager().getStoredAccounts().contains(accountID)) - { - throw new IllegalStateException( - "An account for id " + accountID.getUserID() - + " was already loaded!"); - } - - try - { - getAccountManager().storeAccount(this, accountID); - } - catch (OperationFailedException ofex) - { - throw new UndeclaredThrowableException(ofex); - } - } - - /** - * Saves the password for the specified account after scrambling it a bit so - * that it is not visible from first sight. (The method remains highly - * insecure). - * - * @param accountID the AccountID for the account whose password we're - * storing - * @param password the password itself - * - * @throws IllegalArgumentException if no account corresponding to - * accountID has been previously stored - */ - public void storePassword(AccountID accountID, String password) - throws IllegalArgumentException - { - try - { - storePassword(getBundleContext(), accountID, password); - } - catch (OperationFailedException ofex) - { - throw new UndeclaredThrowableException(ofex); - } - } - - /** - * Saves the password for the specified account after scrambling it a bit - * so that it is not visible from first sight (Method remains highly - * insecure). - *

    - * TODO Delegate the implementation to {@link AccountManager} because it - * knows the format in which the password (among the other account - * properties) is to be saved. - *

    - * - * @param bundleContext a currently valid bundle context. - * @param accountID the AccountID of the account whose password is - * to be stored - * @param password the password to be stored - * - * @throws IllegalArgumentException if no account corresponding to - * accountID has been previously stored. - * @throws OperationFailedException if anything goes wrong while storing the - * specified password - */ - protected void storePassword(BundleContext bundleContext, - AccountID accountID, - String password) - throws IllegalArgumentException, - OperationFailedException - { - String accountPrefix - = findAccountPrefix( - bundleContext, - accountID, - getFactoryImplPackageName()); - - if (accountPrefix == null) - { - throw - new IllegalArgumentException( - "No previous records found for account ID: " - + accountID.getAccountUniqueID() - + " in package" - + getFactoryImplPackageName()); - } - - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - - if (!credentialsStorage.storePassword(accountPrefix, password)) - { - throw - new OperationFailedException( - "CredentialsStorageService failed to storePassword", - OperationFailedException.GENERAL_ERROR); - } - - // Update password property also in the AccountID - // to prevent it from being removed during account reload - // in some cases. - accountID.setPassword(password); - - } - - /** - * Returns the password last saved for the specified account. - * - * @param accountID the AccountID for the account whose password we're - * looking for - * - * @return a String containing the password for the specified accountID - */ - public String loadPassword(AccountID accountID) - { - return loadPassword(getBundleContext(), accountID); - } - - /** - * Returns the password last saved for the specified account. - *

    - * TODO Delegate the implementation to {@link AccountManager} because it - * knows the format in which the password (among the other account - * properties) was saved. - *

    - * - * @param bundleContext a currently valid bundle context. - * @param accountID the AccountID for the account whose password we're - * looking for.. - * - * @return a String containing the password for the specified accountID. - */ - protected String loadPassword(BundleContext bundleContext, - AccountID accountID) - { - String accountPrefix = findAccountPrefix( - bundleContext, accountID, getFactoryImplPackageName()); - - if (accountPrefix == null) - return null; - - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - - return credentialsStorage.loadPassword(accountPrefix); - } - - /** - * Initializes and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. This method has a persistent - * effect. Once created the resulting account will remain installed until - * removed through the uninstallAccount method. - * - * @param accountProperties a set of protocol (or implementation) specific - * properties defining the new account. - * @return the AccountID of the newly loaded account - */ - public AccountID loadAccount(Map accountProperties) - { - AccountID accountID = createAccount(accountProperties); - - loadAccount(accountID); - - return accountID; - } - - /** - * Creates a protocol provider for the given accountID and - * registers it in the bundle context. This method has a persistent - * effect. Once created the resulting account will remain installed until - * removed through the uninstallAccount method. - * - * @param accountID the account identifier - * @return true if the account with the given accountID is - * successfully loaded, otherwise returns false - */ - public boolean loadAccount(AccountID accountID) - { - // Need to obtain the original user id property, instead of calling - // accountID.getUserID(), because this method could return a modified - // version of the user id property. - String userID - = accountID.getAccountPropertyString( - ProtocolProviderFactory.USER_ID); - - ProtocolProviderService service = createService(userID, accountID); - - Dictionary properties = new Hashtable(); - properties.put(PROTOCOL, protocolName); - properties.put(USER_ID, userID); - - ServiceRegistration serviceRegistration - = bundleContext.registerService( - ProtocolProviderService.class, - service, - properties); - - if (serviceRegistration == null) - { - return false; - } - else - { - synchronized (registeredAccounts) - { - registeredAccounts.put(accountID, serviceRegistration); - } - return true; - } - } - - /** - * Unloads the account corresponding to the given accountID. - * Unregisters the corresponding protocol provider, but keeps the account in - * contrast to the uninstallAccount method. - * - * @param accountID the account identifier - * @return true if an account with the specified ID existed and was unloaded - * and false otherwise. - */ - public boolean unloadAccount(AccountID accountID) - { - // Unregister the protocol provider. - ServiceReference serRef - = getProviderForAccount(accountID); - - if (serRef == null) - { - return false; - } - - BundleContext bundleContext = getBundleContext(); - ProtocolProviderService protocolProvider - = bundleContext.getService(serRef); - - try - { - protocolProvider.unregister(); - } - catch (OperationFailedException ex) - { - logger.error( - "Failed to unregister protocol provider for account: " - + accountID + " caused by: " + ex); - } - - ServiceRegistration registration; - - synchronized (registeredAccounts) - { - registration = registeredAccounts.remove(accountID); - } - if (registration == null) - { - return false; - } - - // Kill the service. - registration.unregister(); - - return true; - } - - /** - * Initializes and creates an account corresponding to the specified - * accountProperties. - * - * @param accountProperties a set of protocol (or implementation) specific - * properties defining the new account. - * @return the AccountID of the newly created account - */ - public AccountID createAccount(Map accountProperties) - { - BundleContext bundleContext = getBundleContext(); - if (bundleContext == null) - throw new NullPointerException( - "The specified BundleContext was null"); - - if (accountProperties == null) - throw new NullPointerException( - "The specified property map was null"); - - String userID = accountProperties.get(USER_ID); - if (userID == null) - throw new NullPointerException( - "The account properties contained no user id."); - - String protocolName = getProtocolName(); - if (!accountProperties.containsKey(PROTOCOL)) - accountProperties.put(PROTOCOL, protocolName); - - return createAccountID(userID, accountProperties); - } - - /** - * Creates a new AccountID instance with a specific user ID to - * represent a given set of account properties. - *

    - * The method is a pure factory allowing implementers to specify the runtime - * type of the created AccountID and customize the instance. - * The returned AccountID will later be associated with a - * ProtocolProviderService by the caller (e.g. using - * {@link #createService(String, AccountID)}). - *

    - * - * @param userID the user ID of the new instance - * @param accountProperties the set of properties to be represented by the - * new instance - * @return a new AccountID instance with the specified user ID - * representing the given set of account properties - */ - protected abstract AccountID createAccountID( - String userID, Map accountProperties); - - /** - * Gets the name of the protocol this factory registers its - * ProtocolProviderServices with and to be placed in the - * properties of the accounts created by this factory. - * - * @return the name of the protocol this factory registers its - * ProtocolProviderServices with and to be placed in - * the properties of the accounts created by this factory - */ - public String getProtocolName() - { - return protocolName; - } - - /** - * Initializes a new ProtocolProviderService instance with a - * specific user ID to represent a specific AccountID. - *

    - * The method is a pure factory allowing implementers to specify the runtime - * type of the created ProtocolProviderService and customize - * the instance. The caller will later register the returned service with - * the BundleContext of this factory. - *

    - * - * @param userID the user ID to initialize the new instance with - * @param accountID the AccountID to be represented by the new - * instance - * @return a new ProtocolProviderService instance with the - * specific user ID representing the specified - * AccountID - */ - protected abstract ProtocolProviderService createService(String userID, - AccountID accountID); - - /** - * Removes the account with accountID from the set of accounts - * that are persistently stored inside the configuration service. - * - * @param accountID the AccountID of the account to remove. - * - * @return true if an account has been removed and false otherwise. - */ - protected boolean removeStoredAccount(AccountID accountID) - { - return getAccountManager().removeStoredAccount(this, accountID); - } - - /** - * Returns the prefix for all persistently stored properties of the account - * with the specified id. - * @param bundleContext a currently valid bundle context. - * @param accountID the AccountID of the account whose properties we're - * looking for. - * @param sourcePackageName a String containing the package name of the - * concrete factory class that extends us. - * @return a String indicating the ConfigurationService property name - * prefix under which all account properties are stored or null if no - * account corresponding to the specified id was found. - */ - public static String findAccountPrefix(BundleContext bundleContext, - AccountID accountID, - String sourcePackageName) - { - ServiceReference confReference - = bundleContext.getServiceReference(ConfigurationService.class); - ConfigurationService configurationService - = bundleContext.getService(confReference); - - //first retrieve all accounts that we've registered - List storedAccounts = - configurationService.getPropertyNamesByPrefix(sourcePackageName, - true); - - //find an account with the corresponding id. - for (String accountRootPropertyName : storedAccounts) - { - //unregister the account in the configuration service. - //all the properties must have been registered in the following - //hierarchy: - //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME - String accountUID = configurationService.getString( - accountRootPropertyName //node id - + "." + ACCOUNT_UID); // propname - - if (accountID.getAccountUniqueID().equals(accountUID)) - { - return accountRootPropertyName; - } - } - return null; - } - - /** - * Returns the name of the package that we're currently running in (i.e. - * the name of the package containing the proto factory that extends us). - * - * @return a String containing the package name of the concrete factory - * class that extends us. - */ - private String getFactoryImplPackageName() - { - String className = getClass().getName(); - - return className.substring(0, className.lastIndexOf('.')); - } - - /** - * Prepares the factory for bundle shutdown. - */ - public void stop() - { - if (logger.isTraceEnabled()) - logger.trace("Preparing to stop all protocol providers of" + this); - - synchronized (registeredAccounts) - { - for (ServiceRegistration reg - : registeredAccounts.values()) - { - stop(reg); - reg.unregister(); - } - - registeredAccounts.clear(); - } - } - - /** - * Shuts down the ProtocolProviderService representing an - * account registered with this factory. - * - * @param registeredAccount the ServiceRegistration of the - * ProtocolProviderService representing an account - * registered with this factory - */ - protected void stop( - ServiceRegistration registeredAccount) - { - ProtocolProviderService protocolProviderService - = getBundleContext().getService(registeredAccount.getReference()); - - protocolProviderService.shutdown(); - } - - /** - * Get the AccountManager of the protocol. - * - * @return AccountManager of the protocol - */ - private AccountManager getAccountManager() - { - BundleContext bundleContext = getBundleContext(); - ServiceReference serviceReference - = bundleContext.getServiceReference(AccountManager.class); - - return bundleContext.getService(serviceReference); - } - - - /** - * Finds registered ProtocolProviderFactory for given - * protocolName. - * @param bundleContext the OSGI bundle context that will be used. - * @param protocolName the protocol name. - * @return Registered ProtocolProviderFactory for given protocol - * name or null if no provider was found. - */ - static public ProtocolProviderFactory getProtocolProviderFactory( - BundleContext bundleContext, - String protocolName) - { - Collection> serRefs; - String osgiFilter - = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; - - try - { - serRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class, - osgiFilter); - } - catch (InvalidSyntaxException ex) - { - serRefs = null; - logger.error(ex); - } - if ((serRefs == null) || serRefs.isEmpty()) - return null; - else - return bundleContext.getService(serRefs.iterator().next()); - } -} +package net.java.sip.communicator.service.protocol; + +import java.lang.reflect.*; +import java.util.*; + +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * The ProtocolProviderFactory is what actually creates instances of a + * ProtocolProviderService implementation. A provider factory would register, + * persistently store, and remove when necessary, ProtocolProviders. The way + * things are in the SIP Communicator, a user account is represented (in a 1:1 + * relationship) by an AccountID and a ProtocolProvider. In other words - one + * would have as many protocol providers installed in a given moment as they + * would user account registered through the various services. + * + * @author Emil Ivov + * @author Lubomir Marinov + */ +public abstract class ProtocolProviderFactory +{ + /** + * The Logger used by the ProtocolProviderFactory class + * and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(ProtocolProviderFactory.class); + + /** + * Then name of a property which represents a password. + */ + public static final String PASSWORD = "PASSWORD"; + + /** + * The name of a property representing the name of the protocol for an + * ProtocolProviderFactory. + */ + public static final String PROTOCOL = "PROTOCOL_NAME"; + + /** + * The name of a property representing the path to protocol icons. + */ + public static final String PROTOCOL_ICON_PATH = "PROTOCOL_ICON_PATH"; + + /** + * The name of a property representing the path to the account icon to + * be used in the user interface, when the protocol provider service is not + * available. + */ + public static final String ACCOUNT_ICON_PATH = "ACCOUNT_ICON_PATH"; + + /** + * The name of a property which represents the AccountID of a + * ProtocolProvider and that, together with a password is used to login + * on the protocol network.. + */ + public static final String USER_ID = "USER_ID"; + + /** + * The name that should be displayed to others when we are calling or + * writing them. + */ + public static final String DISPLAY_NAME = "DISPLAY_NAME"; + + /** + * The name that should be displayed to the user on call via and chat via + * lists. + */ + public static final String ACCOUNT_DISPLAY_NAME = "ACCOUNT_DISPLAY_NAME"; + + /** + * The name of the property under which we store protocol AccountID-s. + */ + public static final String ACCOUNT_UID = "ACCOUNT_UID"; + + /** + * The name of the property under which we store protocol the address of + * a protocol centric entity (any protocol server). + */ + public static final String SERVER_ADDRESS = "SERVER_ADDRESS"; + + /** + * The name of the property under which we store the number of the port + * where the server stored against the SERVER_ADDRESS property is expecting + * connections to be made via this protocol. + */ + public static final String SERVER_PORT = "SERVER_PORT"; + + /** + * The name of the property under which we store the name of the transport + * protocol that needs to be used to access the server. + */ + public static final String SERVER_TRANSPORT = "SERVER_TRANSPORT"; + + /** + * The name of the property under which we store protocol the address of + * a protocol proxy. + */ + public static final String PROXY_ADDRESS = "PROXY_ADDRESS"; + + /** + * The name of the property under which we store the number of the port + * where the proxy stored against the PROXY_ADDRESS property is expecting + * connections to be made via this protocol. + */ + public static final String PROXY_PORT = "PROXY_PORT"; + + /** + * The name of the property which defines whether proxy is auto configured + * by the protocol by using known methods such as specific DNS queries. + */ + public static final String PROXY_AUTO_CONFIG = "PROXY_AUTO_CONFIG"; + + /** + * The property indicating the preferred UDP and TCP + * port to bind to for clear communications. + */ + public static final String PREFERRED_CLEAR_PORT_PROPERTY_NAME + = "net.java.sip.communicator.SIP_PREFERRED_CLEAR_PORT"; + + /** + * The property indicating the preferred TLS (TCP) + * port to bind to for secure communications. + */ + public static final String PREFERRED_SECURE_PORT_PROPERTY_NAME + = "net.java.sip.communicator.SIP_PREFERRED_SECURE_PORT"; + + /** + * The name of the property under which we store the the type of the proxy + * stored against the PROXY_ADDRESS property. Exact type values depend on + * protocols and among them are socks4, socks5, http and possibly others. + */ + public static final String PROXY_TYPE = "PROXY_TYPE"; + + /** + * The name of the property under which we store the the username for the + * proxy stored against the PROXY_ADDRESS property. + */ + public static final String PROXY_USERNAME = "PROXY_USERNAME"; + + /** + * The name of the property under which we store the the authorization name + * for the proxy stored against the PROXY_ADDRESS property. + */ + public static final String AUTHORIZATION_NAME = "AUTHORIZATION_NAME"; + + /** + * The name of the property under which we store the password for the proxy + * stored against the PROXY_ADDRESS property. + */ + public static final String PROXY_PASSWORD = "PROXY_PASSWORD"; + + /** + * The name of the property under which we store the name of the transport + * protocol that needs to be used to access the proxy. + */ + public static final String PROXY_TRANSPORT = "PROXY_TRANSPORT"; + + /** + * The name of the property that indicates whether loose routing should be + * forced for all traffic in an account, rather than routing through an + * outbound proxy which is the default for Jitsi. + */ + public static final String FORCE_PROXY_BYPASS = "FORCE_PROXY_BYPASS"; + + /** + * The name of the property that indicates whether the client must + * be registered with a registrar when making outgoing calls. + */ + public static final String MUST_REGISTER_TO_CALL = "MUST_REGISTER_TO_CALL"; + + /** + * The name of the property under which we store the user preference for a + * transport protocol to use (i.e. tcp or udp). + */ + public static final String PREFERRED_TRANSPORT = "PREFERRED_TRANSPORT"; + + /** + * The name of the property under which we store whether we generate + * resource values or we just use the stored one. + */ + public static final String AUTO_GENERATE_RESOURCE = "AUTO_GENERATE_RESOURCE"; + + /** + * The name of the property under which we store resources such as the + * jabber resource property. + */ + public static final String RESOURCE = "RESOURCE"; + + /** + * The name of the property under which we store resource priority. + */ + public static final String RESOURCE_PRIORITY = "RESOURCE_PRIORITY"; + + /** + * The name of the property which defines that the call is encrypted by + * default + */ + public static final String DEFAULT_ENCRYPTION = "DEFAULT_ENCRYPTION"; + + /** + * The name of the property that indicates the encryption protocols for this + * account. + */ + public static final String ENCRYPTION_PROTOCOL = "ENCRYPTION_PROTOCOL"; + + /** + * The name of the property that indicates the status (enabed or disabled) + * encryption protocols for this account. + */ + public static final String ENCRYPTION_PROTOCOL_STATUS + = "ENCRYPTION_PROTOCOL_STATUS"; + + /** + * The name of the property which defines if to include the ZRTP attribute + * to SIP/SDP + */ + public static final String DEFAULT_SIPZRTP_ATTRIBUTE = + "DEFAULT_SIPZRTP_ATTRIBUTE"; + + /** + * The name of the property which defines the ID of the client TLS + * certificate configuration entry. + */ + public static final String CLIENT_TLS_CERTIFICATE = + "CLIENT_TLS_CERTIFICATE"; + + /** + * The name of the property under which we store the boolean value + * indicating if the user name should be automatically changed if the + * specified name already exists. This property is meant to be used by IRC + * implementations. + */ + public static final String AUTO_CHANGE_USER_NAME = "AUTO_CHANGE_USER_NAME"; + + /** + * The name of the property under which we store the boolean value + * indicating if a password is required. Initially this property is meant to + * be used by IRC implementations. + */ + public static final String NO_PASSWORD_REQUIRED = "NO_PASSWORD_REQUIRED"; + + /** + * The name of the property under which we store if the presence is enabled. + */ + public static final String IS_PRESENCE_ENABLED = "IS_PRESENCE_ENABLED"; + + /** + * The name of the property under which we store if the p2p mode for SIMPLE + * should be forced. + */ + public static final String FORCE_P2P_MODE = "FORCE_P2P_MODE"; + + /** + * The name of the property under which we store the offline contact polling + * period for SIMPLE. + */ + public static final String POLLING_PERIOD = "POLLING_PERIOD"; + + /** + * The name of the property under which we store the chosen default + * subscription expiration value for SIMPLE. + */ + public static final String SUBSCRIPTION_EXPIRATION + = "SUBSCRIPTION_EXPIRATION"; + + /** + * Indicates if the server address has been validated. + */ + public static final String SERVER_ADDRESS_VALIDATED + = "SERVER_ADDRESS_VALIDATED"; + + /** + * Indicates if the server settings are over + */ + public static final String IS_SERVER_OVERRIDDEN + = "IS_SERVER_OVERRIDDEN"; + /** + * Indicates if the proxy address has been validated. + */ + public static final String PROXY_ADDRESS_VALIDATED + = "PROXY_ADDRESS_VALIDATED"; + + /** + * Indicates the search strategy chosen for the DICT protocole. + */ + public static final String STRATEGY = "STRATEGY"; + + /** + * Indicates a protocol that would not be shown in the user interface as an + * account. + */ + public static final String IS_PROTOCOL_HIDDEN = "IS_PROTOCOL_HIDDEN"; + + /** + * Indicates if the given account is the preferred account. + */ + public static final String IS_PREFERRED_PROTOCOL = "IS_PREFERRED_PROTOCOL"; + + /** + * The name of the property that would indicate if a given account is + * currently enabled or disabled. + */ + public static final String IS_ACCOUNT_DISABLED = "IS_ACCOUNT_DISABLED"; + + /** + * The name of the property that would indicate if a given account + * configuration form is currently hidden. + */ + public static final String IS_ACCOUNT_CONFIG_HIDDEN = "IS_CONFIG_HIDDEN"; + + /** + * The name of the property that would indicate if a given account + * status menu is currently hidden. + */ + public static final String IS_ACCOUNT_STATUS_MENU_HIDDEN = + "IS_STATUS_MENU_HIDDEN"; + + /** + * The name of the property that would indicate if a given account + * configuration is read only. + */ + public static final String IS_ACCOUNT_READ_ONLY = "IS_READ_ONLY"; + + /** + * The name of the property that would indicate if a given account + * groups are readonly, values can be all or a comma separated + * group names including root. + */ + public static final String ACCOUNT_READ_ONLY_GROUPS = "READ_ONLY_GROUPS"; + + /** + * Indicates if ICE should be used. + */ + public static final String IS_USE_ICE = "ICE_ENABLED"; + + /** + * Indicates if STUN server should be automatically discovered. + */ + public static final String AUTO_DISCOVER_STUN = "AUTO_DISCOVER_STUN"; + + /** + * Indicates if default STUN server would be used if no other STUN/TURN + * server are available. + */ + public static final String USE_DEFAULT_STUN_SERVER + = "USE_DEFAULT_STUN_SERVER"; + + /** + * The name of the boolean account property which indicates whether Jitsi + * Videobridge is to be used, if available and supported, for conference + * calls. + */ + public static final String USE_JITSI_VIDEO_BRIDGE + = "USE_JITSI_VIDEO_BRIDGE"; + + /** + * The property name prefix for all stun server properties. We generally use + * this prefix in conjunction with an index which is how we store multiple + * servers. + */ + public static final String STUN_PREFIX = "STUN"; + + /** + * The base property name for address of additional STUN servers specified. + */ + public static final String STUN_ADDRESS = "ADDRESS"; + + /** + * The base property name for port of additional STUN servers specified. + */ + public static final String STUN_PORT = "PORT"; + + /** + * The base property name for username of additional STUN servers specified. + */ + public static final String STUN_USERNAME = "USERNAME"; + + /** + * The base property name for password of additional STUN servers specified. + */ + public static final String STUN_PASSWORD = "PASSWORD"; + + /** + * The base property name for the turn supported property of additional + * STUN servers specified. + */ + public static final String STUN_IS_TURN_SUPPORTED = "IS_TURN_SUPPORTED"; + + /** + * Indicates if JingleNodes should be used with ICE. + */ + public static final String IS_USE_JINGLE_NODES = "JINGLE_NODES_ENABLED"; + + /** + * Indicates if JingleNodes should be used with ICE. + */ + public static final String AUTO_DISCOVER_JINGLE_NODES + = "AUTO_DISCOVER_JINGLE_NODES"; + + /** + * Indicates if JingleNodes should use buddies to search for nodes. + */ + public static final String JINGLE_NODES_SEARCH_BUDDIES + = "JINGLE_NODES_SEARCH_BUDDIES"; + + /** + * Indicates if UPnP should be used with ICE. + */ + public static final String IS_USE_UPNP = "UPNP_ENABLED"; + + /** + * Indicates if we allow non-TLS connection. + */ + public static final String IS_ALLOW_NON_SECURE = "ALLOW_NON_SECURE"; + + /** + * Enable notifications for new voicemail messages. + */ + public static final String VOICEMAIL_ENABLED = "VOICEMAIL_ENABLED"; + + /** + * Address used to reach voicemail box, by services able to + * subscribe for voicemail new messages notifications. + */ + public static final String VOICEMAIL_URI = "VOICEMAIL_URI"; + + /** + * Address used to call to hear your messages stored on the server + * for your voicemail. + */ + public static final String VOICEMAIL_CHECK_URI = "VOICEMAIL_CHECK_URI"; + + /** + * Indicates if calling is disabled for a certain account. + */ + public static final String IS_CALLING_DISABLED_FOR_ACCOUNT + = "CALLING_DISABLED"; + + /** + * Indicates if desktop streaming/sharing is disabled for a certain account. + */ + public static final String IS_DESKTOP_STREAMING_DISABLED + = "DESKTOP_STREAMING_DISABLED"; + + /** + * Indicates if desktop remote control is disabled for a certain account. + */ + public static final String IS_DESKTOP_REMOTE_CONTROL_DISABLED + = "DESKTOP_REMOTE_CONTROL_DISABLED"; + + /** + * The sms default server address. + */ + public static final String SMS_SERVER_ADDRESS = "SMS_SERVER_ADDRESS"; + + /** + * Keep-alive method used by the protocol. + */ + public static final String KEEP_ALIVE_METHOD = "KEEP_ALIVE_METHOD"; + + /** + * The interval for keep-alives if any. + */ + public static final String KEEP_ALIVE_INTERVAL = "KEEP_ALIVE_INTERVAL"; + + /** + * The name of the property holding DTMF method. + */ + public static final String DTMF_METHOD = "DTMF_METHOD"; + + /** + * The minimal DTMF tone duration. + */ + public static final String DTMF_MINIMAL_TONE_DURATION + = "DTMF_MINIMAL_TONE_DURATION"; + + /** + * Paranoia mode when turned on requires all calls to be secure and + * indicated as such. + */ + public static final String MODE_PARANOIA = "MODE_PARANOIA"; + + /** + * The name of the "override encodings" property + */ + public static final String OVERRIDE_ENCODINGS = "OVERRIDE_ENCODINGS"; + + /** + * The prefix used to store account encoding properties + */ + public static final String ENCODING_PROP_PREFIX = "Encodings"; + + /** + * An account property to provide a connected account to check for + * its status. Used when the current provider need to reject calls + * but is missing presence operation set and need to check other + * provider for status. + */ + public static final String CUSAX_PROVIDER_ACCOUNT_PROP + = "cusax.XMPP_ACCOUNT_ID"; + + /** + * The BundleContext containing (or to contain) the service + * registration of this factory. + */ + private final BundleContext bundleContext; + + /** + * The name of the protocol this factory registers its + * ProtocolProviderServices with and to be placed in the + * properties of the accounts created by this factory. + */ + private final String protocolName; + + /** + * The table that we store our accounts in. + *

    + * TODO Synchronize the access to the field which may in turn be better + * achieved by also hiding it from protected into private access. + *

    + */ + protected final Map> + registeredAccounts + = new HashMap>(); + + /** + * The name of the property that indicates the AVP type. + *
      + *
    • {@link #SAVP_OFF}
    • + *
    • {@link #SAVP_MANDATORY}
    • + *
    • {@link #SAVP_OPTIONAL}
    • + *
    + */ + public static final String SAVP_OPTION = "SAVP_OPTION"; + + /** + * Always use RTP/AVP + */ + public static final int SAVP_OFF = 0; + + /** + * Always use RTP/SAVP + */ + public static final int SAVP_MANDATORY = 1; + + /** + * Sends two media description, with RTP/SAVP being first. + */ + public static final int SAVP_OPTIONAL = 2; + + /** + * The name of the property that defines the enabled SDES cipher suites. + * Enabled suites are listed as CSV by their RFC name. + */ + public static final String SDES_CIPHER_SUITES = "SDES_CIPHER_SUITES"; + + /** + * The name of the property that defines the enabled/disabled state of + * message carbons. + */ + public static final String IS_CARBON_DISABLED = "CARBON_DISABLED"; + + /** + * Creates a new ProtocolProviderFactory. + * + * @param bundleContext the bundle context reference of the service + * @param protocolName the name of the protocol + */ + protected ProtocolProviderFactory(BundleContext bundleContext, + String protocolName) + { + this.bundleContext = bundleContext; + this.protocolName = protocolName; + } + + /** + * Gets the BundleContext containing (or to contain) the + * service registration of this factory. + * + * @return the BundleContext containing (or to contain) the + * service registration of this factory + */ + public BundleContext getBundleContext() + { + return bundleContext; + } + + /** + * Initializes and creates an account corresponding to the specified + * accountProperties and registers the resulting ProtocolProvider in the + * context BundleContext parameter. Note that account + * registration is persistent and accounts that are registered during + * a particular sip-communicator session would be automatically reloaded + * during all following sessions until they are removed through the + * removeAccount method. + * + * @param userID the user identifier uniquely representing the newly + * created account within the protocol namespace. + * @param accountProperties a set of protocol (or implementation) specific + * properties defining the new account. + * @return the AccountID of the newly created account. + * @throws java.lang.IllegalArgumentException if userID does not correspond + * to an identifier in the context of the underlying protocol or if + * accountProperties does not contain a complete set of account installation + * properties. + * @throws java.lang.IllegalStateException if the account has already been + * installed. + * @throws java.lang.NullPointerException if any of the arguments is null. + */ + public abstract AccountID installAccount(String userID, + Map accountProperties) + throws IllegalArgumentException, + IllegalStateException, + NullPointerException; + + + /** + * Modifies the account corresponding to the specified accountID. This + * method is meant to be used to change properties of already existing + * accounts. Note that if the given accountID doesn't correspond to any + * registered account this method would do nothing. + * + * @param protocolProvider the protocol provider service corresponding to + * the modified account. + * @param accountProperties a set of protocol (or implementation) specific + * properties defining the new account. + * + * @throws java.lang.NullPointerException if any of the arguments is null. + */ + public abstract void modifyAccount( + ProtocolProviderService protocolProvider, + Map accountProperties) + throws NullPointerException; + + /** + * Returns a copy of the list containing the AccountIDs of all + * accounts currently registered in this protocol provider. + * @return a copy of the list containing the AccountIDs of all + * accounts currently registered in this protocol provider. + */ + public ArrayList getRegisteredAccounts() + { + synchronized (registeredAccounts) + { + return new ArrayList(registeredAccounts.keySet()); + } + } + + /** + * Returns the ServiceReference for the protocol provider corresponding to + * the specified accountID or null if the accountID is unknown. + * @param accountID the accountID of the protocol provider we'd like to get + * @return a ServiceReference object to the protocol provider with the + * specified account id and null if the account id is unknown to the + * provider factory. + */ + public ServiceReference getProviderForAccount( + AccountID accountID) + { + ServiceRegistration registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.get(accountID); + } + + try + { + if (registration != null) + return registration.getReference(); + } + catch (IllegalStateException ise) + { + synchronized (registeredAccounts) + { + registeredAccounts.remove(accountID); + } + } + + return null; + } + + /** + * Removes the specified account from the list of accounts that this + * provider factory is handling. If the specified accountID is unknown to + * the ProtocolProviderFactory, the call has no effect and false is + * returned. This method is persistent in nature and once called the account + * corresponding to the specified ID will not be loaded during future runs + * of the project. + * + * @param accountID the ID of the account to remove. + * @return true if an account with the specified ID existed and was removed + * and false otherwise. + */ + public boolean uninstallAccount(AccountID accountID) + { + // Unregister the protocol provider. + ServiceReference serRef + = getProviderForAccount(accountID); + + boolean wasAccountExisting = false; + + // If the protocol provider service is registered, first unregister the + // service. + if (serRef != null) + { + BundleContext bundleContext = getBundleContext(); + ProtocolProviderService protocolProvider + = bundleContext.getService(serRef); + + try + { + protocolProvider.unregister(); + } + catch (OperationFailedException ex) + { + logger.error( + "Failed to unregister protocol provider for account: " + + accountID + " caused by: " + ex); + } + } + + ServiceRegistration registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.remove(accountID); + } + + // first remove the stored account so when PP is unregistered we can + // distinguish between deleted or just disabled account + wasAccountExisting = removeStoredAccount(accountID); + + if (registration != null) + { + // Kill the service. + registration.unregister(); + } + + return wasAccountExisting; + } + + /** + * The method stores the specified account in the configuration service + * under the package name of the source factory. The restore and remove + * account methods are to be used to obtain access to and control the stored + * accounts. + *

    + * In order to store all account properties, the method would create an + * entry in the configuration service corresponding (beginning with) the + * sourceFactory's package name and add to it a unique identifier + * (e.g. the current miliseconds.) + *

    + * + * @param accountID the AccountID corresponding to the account that we would + * like to store. + */ + protected void storeAccount(AccountID accountID) + { + this.storeAccount(accountID, true); + } + + /** + * The method stores the specified account in the configuration service + * under the package name of the source factory. The restore and remove + * account methods are to be used to obtain access to and control the stored + * accounts. + *

    + * In order to store all account properties, the method would create an + * entry in the configuration service corresponding (beginning with) the + * sourceFactory's package name and add to it a unique identifier + * (e.g. the current miliseconds.) + *

    + * + * @param accountID the AccountID corresponding to the account that we would + * like to store. + * @param isModification if false there must be no such already + * loaded account, it true ist modification of an existing account. + * Usually we use this method with false in method installAccount + * and with true or the overridden method in method + * modifyAccount. + */ + protected void storeAccount(AccountID accountID, boolean isModification) + { + if(!isModification + && getAccountManager().getStoredAccounts().contains(accountID)) + { + throw new IllegalStateException( + "An account for id " + accountID.getUserID() + + " was already loaded!"); + } + + try + { + getAccountManager().storeAccount(this, accountID); + } + catch (OperationFailedException ofex) + { + throw new UndeclaredThrowableException(ofex); + } + } + + /** + * Saves the password for the specified account after scrambling it a bit so + * that it is not visible from first sight. (The method remains highly + * insecure). + * + * @param accountID the AccountID for the account whose password we're + * storing + * @param password the password itself + * + * @throws IllegalArgumentException if no account corresponding to + * accountID has been previously stored + */ + public void storePassword(AccountID accountID, String password) + throws IllegalArgumentException + { + try + { + storePassword(getBundleContext(), accountID, password); + } + catch (OperationFailedException ofex) + { + throw new UndeclaredThrowableException(ofex); + } + } + + /** + * Saves the password for the specified account after scrambling it a bit + * so that it is not visible from first sight (Method remains highly + * insecure). + *

    + * TODO Delegate the implementation to {@link AccountManager} because it + * knows the format in which the password (among the other account + * properties) is to be saved. + *

    + * + * @param bundleContext a currently valid bundle context. + * @param accountID the AccountID of the account whose password is + * to be stored + * @param password the password to be stored + * + * @throws IllegalArgumentException if no account corresponding to + * accountID has been previously stored. + * @throws OperationFailedException if anything goes wrong while storing the + * specified password + */ + protected void storePassword(BundleContext bundleContext, + AccountID accountID, + String password) + throws IllegalArgumentException, + OperationFailedException + { + String accountPrefix + = findAccountPrefix( + bundleContext, + accountID, + getFactoryImplPackageName()); + + if (accountPrefix == null) + { + throw + new IllegalArgumentException( + "No previous records found for account ID: " + + accountID.getAccountUniqueID() + + " in package" + + getFactoryImplPackageName()); + } + + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + if (!credentialsStorage.storePassword(accountPrefix, password)) + { + throw + new OperationFailedException( + "CredentialsStorageService failed to storePassword", + OperationFailedException.GENERAL_ERROR); + } + + // Update password property also in the AccountID + // to prevent it from being removed during account reload + // in some cases. + accountID.setPassword(password); + + } + + /** + * Returns the password last saved for the specified account. + * + * @param accountID the AccountID for the account whose password we're + * looking for + * + * @return a String containing the password for the specified accountID + */ + public String loadPassword(AccountID accountID) + { + return loadPassword(getBundleContext(), accountID); + } + + /** + * Returns the password last saved for the specified account. + *

    + * TODO Delegate the implementation to {@link AccountManager} because it + * knows the format in which the password (among the other account + * properties) was saved. + *

    + * + * @param bundleContext a currently valid bundle context. + * @param accountID the AccountID for the account whose password we're + * looking for.. + * + * @return a String containing the password for the specified accountID. + */ + protected String loadPassword(BundleContext bundleContext, + AccountID accountID) + { + String accountPrefix = findAccountPrefix( + bundleContext, accountID, getFactoryImplPackageName()); + + if (accountPrefix == null) + return null; + + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + return credentialsStorage.loadPassword(accountPrefix); + } + + /** + * Initializes and creates an account corresponding to the specified + * accountProperties and registers the resulting ProtocolProvider in the + * context BundleContext parameter. This method has a persistent + * effect. Once created the resulting account will remain installed until + * removed through the uninstallAccount method. + * + * @param accountProperties a set of protocol (or implementation) specific + * properties defining the new account. + * @return the AccountID of the newly loaded account + */ + public AccountID loadAccount(Map accountProperties) + { + AccountID accountID = createAccount(accountProperties); + + loadAccount(accountID); + + return accountID; + } + + /** + * Creates a protocol provider for the given accountID and + * registers it in the bundle context. This method has a persistent + * effect. Once created the resulting account will remain installed until + * removed through the uninstallAccount method. + * + * @param accountID the account identifier + * @return true if the account with the given accountID is + * successfully loaded, otherwise returns false + */ + public boolean loadAccount(AccountID accountID) + { + // Need to obtain the original user id property, instead of calling + // accountID.getUserID(), because this method could return a modified + // version of the user id property. + String userID + = accountID.getAccountPropertyString( + ProtocolProviderFactory.USER_ID); + + ProtocolProviderService service = createService(userID, accountID); + + Dictionary properties = new Hashtable(); + properties.put(PROTOCOL, protocolName); + properties.put(USER_ID, userID); + + ServiceRegistration serviceRegistration + = bundleContext.registerService( + ProtocolProviderService.class, + service, + properties); + + if (serviceRegistration == null) + { + return false; + } + else + { + synchronized (registeredAccounts) + { + registeredAccounts.put(accountID, serviceRegistration); + } + return true; + } + } + + /** + * Unloads the account corresponding to the given accountID. + * Unregisters the corresponding protocol provider, but keeps the account in + * contrast to the uninstallAccount method. + * + * @param accountID the account identifier + * @return true if an account with the specified ID existed and was unloaded + * and false otherwise. + */ + public boolean unloadAccount(AccountID accountID) + { + // Unregister the protocol provider. + ServiceReference serRef + = getProviderForAccount(accountID); + + if (serRef == null) + { + return false; + } + + BundleContext bundleContext = getBundleContext(); + ProtocolProviderService protocolProvider + = bundleContext.getService(serRef); + + try + { + protocolProvider.unregister(); + } + catch (OperationFailedException ex) + { + logger.error( + "Failed to unregister protocol provider for account: " + + accountID + " caused by: " + ex); + } + + ServiceRegistration registration; + + synchronized (registeredAccounts) + { + registration = registeredAccounts.remove(accountID); + } + if (registration == null) + { + return false; + } + + // Kill the service. + registration.unregister(); + + return true; + } + + /** + * Initializes and creates an account corresponding to the specified + * accountProperties. + * + * @param accountProperties a set of protocol (or implementation) specific + * properties defining the new account. + * @return the AccountID of the newly created account + */ + public AccountID createAccount(Map accountProperties) + { + BundleContext bundleContext = getBundleContext(); + if (bundleContext == null) + throw new NullPointerException( + "The specified BundleContext was null"); + + if (accountProperties == null) + throw new NullPointerException( + "The specified property map was null"); + + String userID = accountProperties.get(USER_ID); + if (userID == null) + throw new NullPointerException( + "The account properties contained no user id."); + + String protocolName = getProtocolName(); + if (!accountProperties.containsKey(PROTOCOL)) + accountProperties.put(PROTOCOL, protocolName); + + return createAccountID(userID, accountProperties); + } + + /** + * Creates a new AccountID instance with a specific user ID to + * represent a given set of account properties. + *

    + * The method is a pure factory allowing implementers to specify the runtime + * type of the created AccountID and customize the instance. + * The returned AccountID will later be associated with a + * ProtocolProviderService by the caller (e.g. using + * {@link #createService(String, AccountID)}). + *

    + * + * @param userID the user ID of the new instance + * @param accountProperties the set of properties to be represented by the + * new instance + * @return a new AccountID instance with the specified user ID + * representing the given set of account properties + */ + protected abstract AccountID createAccountID( + String userID, Map accountProperties); + + /** + * Gets the name of the protocol this factory registers its + * ProtocolProviderServices with and to be placed in the + * properties of the accounts created by this factory. + * + * @return the name of the protocol this factory registers its + * ProtocolProviderServices with and to be placed in + * the properties of the accounts created by this factory + */ + public String getProtocolName() + { + return protocolName; + } + + /** + * Initializes a new ProtocolProviderService instance with a + * specific user ID to represent a specific AccountID. + *

    + * The method is a pure factory allowing implementers to specify the runtime + * type of the created ProtocolProviderService and customize + * the instance. The caller will later register the returned service with + * the BundleContext of this factory. + *

    + * + * @param userID the user ID to initialize the new instance with + * @param accountID the AccountID to be represented by the new + * instance + * @return a new ProtocolProviderService instance with the + * specific user ID representing the specified + * AccountID + */ + protected abstract ProtocolProviderService createService(String userID, + AccountID accountID); + + /** + * Removes the account with accountID from the set of accounts + * that are persistently stored inside the configuration service. + * + * @param accountID the AccountID of the account to remove. + * + * @return true if an account has been removed and false otherwise. + */ + protected boolean removeStoredAccount(AccountID accountID) + { + return getAccountManager().removeStoredAccount(this, accountID); + } + + /** + * Returns the prefix for all persistently stored properties of the account + * with the specified id. + * @param bundleContext a currently valid bundle context. + * @param accountID the AccountID of the account whose properties we're + * looking for. + * @param sourcePackageName a String containing the package name of the + * concrete factory class that extends us. + * @return a String indicating the ConfigurationService property name + * prefix under which all account properties are stored or null if no + * account corresponding to the specified id was found. + */ + public static String findAccountPrefix(BundleContext bundleContext, + AccountID accountID, + String sourcePackageName) + { + ServiceReference confReference + = bundleContext.getServiceReference(ConfigurationService.class); + ConfigurationService configurationService + = bundleContext.getService(confReference); + + //first retrieve all accounts that we've registered + List storedAccounts = + configurationService.getPropertyNamesByPrefix(sourcePackageName, + true); + + //find an account with the corresponding id. + for (String accountRootPropertyName : storedAccounts) + { + //unregister the account in the configuration service. + //all the properties must have been registered in the following + //hierarchy: + //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME + String accountUID = configurationService.getString( + accountRootPropertyName //node id + + "." + ACCOUNT_UID); // propname + + if (accountID.getAccountUniqueID().equals(accountUID)) + { + return accountRootPropertyName; + } + } + return null; + } + + /** + * Returns the name of the package that we're currently running in (i.e. + * the name of the package containing the proto factory that extends us). + * + * @return a String containing the package name of the concrete factory + * class that extends us. + */ + private String getFactoryImplPackageName() + { + String className = getClass().getName(); + + return className.substring(0, className.lastIndexOf('.')); + } + + /** + * Prepares the factory for bundle shutdown. + */ + public void stop() + { + if (logger.isTraceEnabled()) + logger.trace("Preparing to stop all protocol providers of" + this); + + synchronized (registeredAccounts) + { + for (ServiceRegistration reg + : registeredAccounts.values()) + { + stop(reg); + reg.unregister(); + } + + registeredAccounts.clear(); + } + } + + /** + * Shuts down the ProtocolProviderService representing an + * account registered with this factory. + * + * @param registeredAccount the ServiceRegistration of the + * ProtocolProviderService representing an account + * registered with this factory + */ + protected void stop( + ServiceRegistration registeredAccount) + { + ProtocolProviderService protocolProviderService + = getBundleContext().getService(registeredAccount.getReference()); + + protocolProviderService.shutdown(); + } + + /** + * Get the AccountManager of the protocol. + * + * @return AccountManager of the protocol + */ + private AccountManager getAccountManager() + { + BundleContext bundleContext = getBundleContext(); + ServiceReference serviceReference + = bundleContext.getServiceReference(AccountManager.class); + + return bundleContext.getService(serviceReference); + } + + + /** + * Finds registered ProtocolProviderFactory for given + * protocolName. + * @param bundleContext the OSGI bundle context that will be used. + * @param protocolName the protocol name. + * @return Registered ProtocolProviderFactory for given protocol + * name or null if no provider was found. + */ + static public ProtocolProviderFactory getProtocolProviderFactory( + BundleContext bundleContext, + String protocolName) + { + Collection> serRefs; + String osgiFilter + = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; + + try + { + serRefs + = bundleContext.getServiceReferences( + ProtocolProviderFactory.class, + osgiFilter); + } + catch (InvalidSyntaxException ex) + { + serRefs = null; + logger.error(ex); + } + if ((serRefs == null) || serRefs.isEmpty()) + return null; + else + return bundleContext.getService(serRefs.iterator().next()); + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java b/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java index db594bf..ecbd971 100644 --- a/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java +++ b/src/net/java/sip/communicator/service/protocol/event/AccountManagerEvent.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,86 +15,86 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol.event; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Represents a notifying event fired by a specific {@link AccountManager}. - * - * @author Lubomir Marinov - */ -public class AccountManagerEvent - extends EventObject -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The type of event notifying that the loading of the stored accounts of a - * specific ProtocolProviderFactory has finished. - */ - public static final int STORED_ACCOUNTS_LOADED = 1; - - /** - * The ProtocolProviderFactory being worked on at the time this - * event has been fired. - */ - private final ProtocolProviderFactory factory; - - /** - * The (detail) type of this event which is one of - * {@link #STORED_ACCOUNTS_LOADED}. - */ - private final int type; - - /** - * Initializes a new AccountManagerEvent instance fired by a - * specific AccountManager in order to notify of an event of a - * specific type occurring while working on a specific - * ProtocolProviderFactory. - * - * @param accountManager the AccountManager issuing the - * notification i.e. the source of the event - * @param type the type of the event which is one of - * {@link #STORED_ACCOUNTS_LOADED} - * @param factory the ProtocolProviderFactory being worked on - * at the time this event has been fired - */ - public AccountManagerEvent(AccountManager accountManager, int type, - ProtocolProviderFactory factory) - { - super(accountManager); - - this.type = type; - this.factory = factory; - } - - /** - * Gets the ProtocolProviderFactory being worked on at the time - * this event has been fired. - * - * @return the ProtocolProviderFactory being worked on at the - * time this event has been fired - */ - public ProtocolProviderFactory getFactory() - { - return factory; - } - - /** - * Gets the (detail) type of this event which is one of - * STORED_ACCOUNTS_LOADED. - * - * @return the (detail) type of this event which is one of - * STORED_ACCOUNTS_LOADED - */ - public int getType() - { - return type; - } -} +package net.java.sip.communicator.service.protocol.event; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.*; + +/** + * Represents a notifying event fired by a specific {@link AccountManager}. + * + * @author Lubomir Marinov + */ +public class AccountManagerEvent + extends EventObject +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The type of event notifying that the loading of the stored accounts of a + * specific ProtocolProviderFactory has finished. + */ + public static final int STORED_ACCOUNTS_LOADED = 1; + + /** + * The ProtocolProviderFactory being worked on at the time this + * event has been fired. + */ + private final ProtocolProviderFactory factory; + + /** + * The (detail) type of this event which is one of + * {@link #STORED_ACCOUNTS_LOADED}. + */ + private final int type; + + /** + * Initializes a new AccountManagerEvent instance fired by a + * specific AccountManager in order to notify of an event of a + * specific type occurring while working on a specific + * ProtocolProviderFactory. + * + * @param accountManager the AccountManager issuing the + * notification i.e. the source of the event + * @param type the type of the event which is one of + * {@link #STORED_ACCOUNTS_LOADED} + * @param factory the ProtocolProviderFactory being worked on + * at the time this event has been fired + */ + public AccountManagerEvent(AccountManager accountManager, int type, + ProtocolProviderFactory factory) + { + super(accountManager); + + this.type = type; + this.factory = factory; + } + + /** + * Gets the ProtocolProviderFactory being worked on at the time + * this event has been fired. + * + * @return the ProtocolProviderFactory being worked on at the + * time this event has been fired + */ + public ProtocolProviderFactory getFactory() + { + return factory; + } + + /** + * Gets the (detail) type of this event which is one of + * STORED_ACCOUNTS_LOADED. + * + * @return the (detail) type of this event which is one of + * STORED_ACCOUNTS_LOADED + */ + public int getType() + { + return type; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java b/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java index 607caea..6bcf4e0 100644 --- a/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java +++ b/src/net/java/sip/communicator/service/protocol/event/AccountManagerListener.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,28 +15,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol.event; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Represents a listener receiving notifications from {@link AccountManager}. - * - * @author Lubomir Marinov - */ -public interface AccountManagerListener - extends EventListener -{ - - /** - * Notifies this listener about an event fired by a specific - * AccountManager. - * - * @param event the AccountManagerEvent describing the - * AccountManager firing the notification and the - * other details of the specific notification. - */ - void handleAccountManagerEvent(AccountManagerEvent event); -} +package net.java.sip.communicator.service.protocol.event; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.*; + +/** + * Represents a listener receiving notifications from {@link AccountManager}. + * + * @author Lubomir Marinov + */ +public interface AccountManagerListener + extends EventListener +{ + + /** + * Notifies this listener about an event fired by a specific + * AccountManager. + * + * @param event the AccountManagerEvent describing the + * AccountManager firing the notification and the + * other details of the specific notification. + */ + void handleAccountManagerEvent(AccountManagerEvent event); +} diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java index 7a58e4a..da34f2c 100644 --- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java +++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,623 +15,623 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol.media; - -import java.beans.*; -import java.lang.ref.*; -import java.util.*; - -import org.jitsi.service.neomedia.*; -import org.jitsi.service.neomedia.device.*; -import org.jitsi.util.*; -import org.jitsi.util.event.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Extends CallConference to represent the media-specific information - * associated with the telephony conference-related state of a - * MediaAwareCall. - * - * @author Lyubomir Marinov - */ -public class MediaAwareCallConference - extends CallConference -{ - /** - * The PropertyChangeListener which will listen to the - * MediaService about PropertyChangeEvents. - */ - private static WeakPropertyChangeListener - mediaServicePropertyChangeListener; - - /** - * The MediaDevices indexed by MediaType ordinal which are - * to be used by this telephony conference for media capture and/or - * playback. If the MediaDevice for a specific MediaType - * is null, - * {@link MediaService#getDefaultDevice(MediaType, MediaUseCase)} is called. - */ - private final MediaDevice[] devices; - - /** - * The MediaDevices which implement media mixing on the respective - * MediaDevice in {@link #devices} for the purposes of this - * telephony conference. - */ - private final MediaDevice[] mixers; - - /** - * The VolumeControl implementation which is to control the volume - * (level) of the audio played back the telephony conference represented by - * this instance. - */ - private final VolumeControl outputVolumeControl - = new BasicVolumeControl( - VolumeControl.PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME); - - /** - * The PropertyChangeListener which listens to sources of - * PropertyChangeEvents on behalf of this instance. - */ - private final PropertyChangeListener propertyChangeListener - = new PropertyChangeListener() - { - @Override - public void propertyChange(PropertyChangeEvent ev) - { - MediaAwareCallConference.this.propertyChange(ev); - } - }; - - /** - * The RTPTranslator which forwards video RTP and RTCP traffic - * between the CallPeers of the Calls participating in - * this telephony conference when the local peer is acting as a conference - * focus. - */ - private RTPTranslator videoRTPTranslator; - - /** - * Initializes a new MediaAwareCallConference instance. - */ - public MediaAwareCallConference() - { - this(false); - } - - /** - * Initializes a new MediaAwareCallConference instance which is to - * optionally utilize the Jitsi Videobridge server-side telephony - * conferencing technology. - * - * @param jitsiVideobridge true if the telephony conference - * represented by the new instance is to utilize the Jitsi Videobridge - * server-side telephony conferencing technology; otherwise, false - */ - public MediaAwareCallConference(boolean jitsiVideobridge) - { - super(jitsiVideobridge); - - int mediaTypeCount = MediaType.values().length; - - devices = new MediaDevice[mediaTypeCount]; - mixers = new MediaDevice[mediaTypeCount]; - - /* - * Listen to the MediaService in order to reflect changes in the user's - * selection with respect to the default media device. - */ - addMediaServicePropertyChangeListener(propertyChangeListener); - } - - /** - * Adds a specific PropertyChangeListener to be notified about - * PropertyChangeEvents fired by the current MediaService - * implementation. The implementation adds a WeakReference to the - * specified listener because MediaAwareCallConference - * is unable to determine when the PropertyChangeListener is to be - * removed. - * - * @param listener the PropertyChangeListener to add - */ - private static synchronized void addMediaServicePropertyChangeListener( - PropertyChangeListener listener) - { - if (mediaServicePropertyChangeListener == null) - { - final MediaService mediaService - = ProtocolMediaActivator.getMediaService(); - - if (mediaService != null) - { - mediaServicePropertyChangeListener - = new WeakPropertyChangeListener() - { - @Override - protected void addThisToNotifier() - { - mediaService.addPropertyChangeListener(this); - } - - @Override - protected void removeThisFromNotifier() - { - mediaService.removePropertyChangeListener(this); - } - }; - } - } - if (mediaServicePropertyChangeListener != null) - { - mediaServicePropertyChangeListener.addPropertyChangeListener( - listener); - } - } - - /** - * {@inheritDoc} - * - * If this telephony conference switches from being a conference focus to - * not being such, disposes of the mixers used by this instance when it was - * a conference focus - */ - @Override - protected void conferenceFocusChanged(boolean oldValue, boolean newValue) - { - /* - * If this telephony conference switches from being a conference - * focus to not being one, dispose of the mixers used when it was a - * conference focus. - */ - if (oldValue && !newValue) - { - Arrays.fill(mixers, null); - - /* Disposing the video translator is not needed when the conference - changes as we have video and we will want to continue with - the video - Removed when chasing a bug where video call becomes conference - call and then back again video call and the video from the - conference focus side is not transmitted. - if (videoRTPTranslator != null) - { - videoRTPTranslator.dispose(); - videoRTPTranslator = null; - } - */ - } - - super.conferenceFocusChanged(oldValue, newValue); - } - - /** - * {@inheritDoc} - * - * Disposes of this.videoRTPTranslator if the removed Call - * was the last Call in this CallConference. - * - * @param call the Call which has been removed from the list of - * Calls participating in this telephony conference. - */ - @Override - protected void callRemoved(Call call) - { - super.callRemoved(call); - - if (getCallCount() == 0 && (videoRTPTranslator != null)) - { - videoRTPTranslator.dispose(); - videoRTPTranslator = null; - } - } - - /** - * Gets a MediaDevice which is capable of capture and/or playback - * of media of the specified MediaType and is the default choice of - * the user with respect to such a MediaDevice. - * - * @param mediaType the MediaType in which the retrieved - * MediaDevice is to capture and/or play back media - * @param useCase the MediaUseCase associated with the intended - * utilization of the MediaDevice to be retrieved - * @return a MediaDevice which is capable of capture and/or - * playback of media of the specified mediaType and is the default - * choice of the user with respect to such a MediaDevice - */ - public MediaDevice getDefaultDevice( - MediaType mediaType, - MediaUseCase useCase) - { - int mediaTypeIndex = mediaType.ordinal(); - MediaDevice device = devices[mediaTypeIndex]; - MediaService mediaService = ProtocolMediaActivator.getMediaService(); - - if (device == null) - device = mediaService.getDefaultDevice(mediaType, useCase); - - /* - * Make sure that the device is capable of mixing in order to support - * conferencing and call recording. - */ - if (device != null) - { - MediaDevice mixer = mixers[mediaTypeIndex]; - - if (mixer == null) - { - switch (mediaType) - { - case AUDIO: - /* - * TODO AudioMixer leads to very poor audio quality on - * Android so do not use it unless it is really really - * necessary. - */ - if ((!OSUtils.IS_ANDROID || isConferenceFocus()) - /* - * We can use the AudioMixer only if the device is - * able to capture (because the AudioMixer will push - * when the capture device pushes). - */ - && device.getDirection().allowsSending()) - { - mixer = mediaService.createMixer(device); - } - break; - - case VIDEO: - if (isConferenceFocus()) - mixer = mediaService.createMixer(device); - break; - } - - mixers[mediaTypeIndex] = mixer; - } - - if (mixer != null) - device = mixer; - } - - return device; - } - - /** - * Gets the VolumeControl which controls the volume (level) of the - * audio played back in the telephony conference represented by this - * instance. - * - * @return the VolumeControl which controls the volume (level) of - * the audio played back in the telephony conference represented by this - * instance - */ - public VolumeControl getOutputVolumeControl() - { - return outputVolumeControl; - } - - /** - * Gets the RTPTranslator which forwards RTP and RTCP traffic - * between the CallPeers of the Calls participating in - * this telephony conference when the local peer is acting as a conference - * focus. - * - * @param mediaType the MediaType of the MediaStream which - * RTP and RTCP traffic is to be forwarded between - * @return the RTPTranslator which forwards RTP and RTCP traffic - * between the CallPeers of the Calls participating in - * this telephony conference when the local peer is acting as a conference - * focus - */ - public RTPTranslator getRTPTranslator(MediaType mediaType) - { - RTPTranslator rtpTranslator = null; - - /* - * XXX A mixer is created for audio even when the local peer is not a - * conference focus in order to enable additional functionality. - * Similarly, the videoRTPTranslator is created even when the local peer - * is not a conference focus in order to enable the local peer to turn - * into a conference focus at a later time. More specifically, - * MediaStreamImpl is unable to accommodate an RTPTranslator after it - * has created its RTPManager. Yet again like the audio mixer, we'd - * better not try to use it on Android at this time because of - * performance issues that might arise. - */ - if (MediaType.VIDEO.equals(mediaType) - && (!OSUtils.IS_ANDROID || isConferenceFocus())) - { - if (videoRTPTranslator == null) - { - videoRTPTranslator - = ProtocolMediaActivator - .getMediaService() - .createRTPTranslator(); - } - rtpTranslator = videoRTPTranslator; - } - return rtpTranslator; - } - - /** - * Notifies this MediaAwareCallConference about changes in the - * values of the properties of sources of PropertyChangeEvents. For - * example, this instance listens to changes of the value of - * {@link MediaService#DEFAULT_DEVICE} which represents the user's choice - * with respect to the default audio device. - * - * @param ev a PropertyChangeEvent which specifies the name of the - * property which had its value changed and the old and new values of that - * property - */ - private void propertyChange(PropertyChangeEvent ev) - { - String propertyName = ev.getPropertyName(); - - if (MediaService.DEFAULT_DEVICE.equals(propertyName)) - { - Object source = ev.getSource(); - - if (source instanceof MediaService) - { - /* - * XXX We only support changing the default audio device at the - * time of this writing. - */ - int mediaTypeIndex = MediaType.AUDIO.ordinal(); - MediaDevice mixer = mixers[mediaTypeIndex]; - MediaDevice oldValue - = (mixer instanceof MediaDeviceWrapper) - ? ((MediaDeviceWrapper) mixer).getWrappedDevice() - : null; - MediaDevice newValue = devices[mediaTypeIndex]; - - if (newValue == null) - { - newValue - = ProtocolMediaActivator - .getMediaService() - .getDefaultDevice( - MediaType.AUDIO, - MediaUseCase.ANY); - } - - /* - * XXX If MediaService#getDefaultDevice(MediaType, MediaUseCase) - * above returns null and its earlier return value was not null, - * we will not notify of an actual change in the value of the - * user's choice with respect to the default audio device. - */ - if (oldValue != newValue) - { - mixers[mediaTypeIndex] = null; - firePropertyChange( - MediaAwareCall.DEFAULT_DEVICE, - oldValue, newValue); - } - } - } - } - - /** - * Sets the MediaDevice to be used by this telephony conference for - * capture and/or playback of media of a specific MediaType. - * - * @param mediaType the MediaType of the media which is to be - * captured and/or played back by the specified device - * @param device the MediaDevice to be used by this telephony - * conference for capture and/or playback of media of the specified - * mediaType - */ - void setDevice(MediaType mediaType, MediaDevice device) - { - int mediaTypeIndex = mediaType.ordinal(); - MediaDevice oldValue = devices[mediaTypeIndex]; - - /* - * XXX While we know the old and the new master/wrapped devices, we - * are not sure whether the mixer has been used. Anyway, we have to - * report different values in order to have PropertyChangeSupport - * really fire an event. - */ - MediaDevice mixer = mixers[mediaTypeIndex]; - - if (mixer instanceof MediaDeviceWrapper) - oldValue = ((MediaDeviceWrapper) mixer).getWrappedDevice(); - - MediaDevice newValue = devices[mediaTypeIndex] = device; - - if (oldValue != newValue) - { - mixers[mediaTypeIndex] = null; - firePropertyChange( - MediaAwareCall.DEFAULT_DEVICE, - oldValue, newValue); - } - } - - /** - * Implements a PropertyChangeListener which weakly references and - * delegates to specific PropertyChangeListeners and automatically - * adds itself to and removes itself from a specific - * PropertyChangeNotifier depending on whether there are - * PropertyChangeListeners to delegate to. Thus enables listening - * to a PropertyChangeNotifier by invoking - * {@link PropertyChangeNotifier#addPropertyChangeListener( - * PropertyChangeListener)} without - * {@link PropertyChangeNotifier#removePropertyChangeListener( - * PropertyChangeListener)}. - */ - private static class WeakPropertyChangeListener - implements PropertyChangeListener - { - /** - * The indicator which determines whether this - * PropertyChangeListener has been added to {@link #notifier}. - */ - private boolean added = false; - - /** - * The list of PropertyChangeListeners which are to be notified - * about PropertyChangeEvents fired by {@link #notifier}. - */ - private final List> listeners - = new LinkedList>(); - - /** - * The PropertyChangeNotifier this instance is to listen to - * about PropertyChangeEvents which are to be forwarded to - * {@link #listeners}. - */ - private final PropertyChangeNotifier notifier; - - /** - * Initializes a new WeakPropertyChangeListener instance. - */ - protected WeakPropertyChangeListener() - { - this(null); - } - - /** - * Initializes a new WeakPropertyChangeListener instance which - * is to listen to a specific PropertyChangeNotifier. - * - * @param notifier the PropertyChangeNotifier the new instance - * is to listen to - */ - public WeakPropertyChangeListener(PropertyChangeNotifier notifier) - { - this.notifier = notifier; - } - - /** - * Adds a specific PropertyChangeListener to the list of - * PropertyChangeListeners to be notified about - * PropertyChangeEvents fired by the - * PropertyChangeNotifier associated with this instance. - * - * @param listener the PropertyChangeListener to add - */ - public synchronized void addPropertyChangeListener( - PropertyChangeListener listener) - { - Iterator> i - = listeners.iterator(); - boolean add = true; - - while (i.hasNext()) - { - PropertyChangeListener l = i.next().get(); - - if (l == null) - i.remove(); - else if (l.equals(listener)) - add = false; - } - if (add - && listeners.add( - new WeakReference(listener)) - && !this.added) - { - addThisToNotifier(); - this.added = true; - } - } - - /** - * Adds this as a PropertyChangeListener to {@link #notifier}. - */ - protected void addThisToNotifier() - { - if (notifier != null) - notifier.addPropertyChangeListener(this); - } - - /** - * {@inheritDoc} - * - * Notifies this instance about a PropertyChangeEvent fired by - * {@link #notifier}. - */ - @Override - public void propertyChange(PropertyChangeEvent ev) - { - PropertyChangeListener[] ls; - int n; - - synchronized (this) - { - Iterator> i - = listeners.iterator(); - - ls = new PropertyChangeListener[listeners.size()]; - n = 0; - while (i.hasNext()) - { - PropertyChangeListener l = i.next().get(); - - if (l == null) - i.remove(); - else - ls[n++] = l; - } - if ((n == 0) && this.added) - { - removeThisFromNotifier(); - this.added = false; - } - } - - if (n != 0) - { - for (PropertyChangeListener l : ls) - { - if (l == null) - break; - else - l.propertyChange(ev); - } - } - } - - /** - * Removes a specific PropertyChangeListener from the list of - * PropertyChangeListeners to be notified about - * PropertyChangeEvents fired by the - * PropertyChangeNotifier associated with this instance. - * - * @param listener the PropertyChangeListener to remove - */ - @SuppressWarnings("unused") - public synchronized void removePropertyChangeListener( - PropertyChangeListener listener) - { - Iterator> i - = listeners.iterator(); - - while (i.hasNext()) - { - PropertyChangeListener l = i.next().get(); - - if ((l == null) || l.equals(listener)) - i.remove(); - } - if (this.added && (listeners.size() == 0)) - { - removeThisFromNotifier(); - this.added = false; - } - } - - /** - * Removes this as a PropertyChangeListener from - * {@link #notifier}. - */ - protected void removeThisFromNotifier() - { - if (notifier != null) - notifier.removePropertyChangeListener(this); - } - } -} +package net.java.sip.communicator.service.protocol.media; + +import java.beans.*; +import java.lang.ref.*; +import java.util.*; + +import org.jitsi.service.neomedia.*; +import org.jitsi.service.neomedia.device.*; +import org.jitsi.util.*; +import org.jitsi.util.event.*; + +import net.java.sip.communicator.service.protocol.*; + +/** + * Extends CallConference to represent the media-specific information + * associated with the telephony conference-related state of a + * MediaAwareCall. + * + * @author Lyubomir Marinov + */ +public class MediaAwareCallConference + extends CallConference +{ + /** + * The PropertyChangeListener which will listen to the + * MediaService about PropertyChangeEvents. + */ + private static WeakPropertyChangeListener + mediaServicePropertyChangeListener; + + /** + * The MediaDevices indexed by MediaType ordinal which are + * to be used by this telephony conference for media capture and/or + * playback. If the MediaDevice for a specific MediaType + * is null, + * {@link MediaService#getDefaultDevice(MediaType, MediaUseCase)} is called. + */ + private final MediaDevice[] devices; + + /** + * The MediaDevices which implement media mixing on the respective + * MediaDevice in {@link #devices} for the purposes of this + * telephony conference. + */ + private final MediaDevice[] mixers; + + /** + * The VolumeControl implementation which is to control the volume + * (level) of the audio played back the telephony conference represented by + * this instance. + */ + private final VolumeControl outputVolumeControl + = new BasicVolumeControl( + VolumeControl.PLAYBACK_VOLUME_LEVEL_PROPERTY_NAME); + + /** + * The PropertyChangeListener which listens to sources of + * PropertyChangeEvents on behalf of this instance. + */ + private final PropertyChangeListener propertyChangeListener + = new PropertyChangeListener() + { + @Override + public void propertyChange(PropertyChangeEvent ev) + { + MediaAwareCallConference.this.propertyChange(ev); + } + }; + + /** + * The RTPTranslator which forwards video RTP and RTCP traffic + * between the CallPeers of the Calls participating in + * this telephony conference when the local peer is acting as a conference + * focus. + */ + private RTPTranslator videoRTPTranslator; + + /** + * Initializes a new MediaAwareCallConference instance. + */ + public MediaAwareCallConference() + { + this(false); + } + + /** + * Initializes a new MediaAwareCallConference instance which is to + * optionally utilize the Jitsi Videobridge server-side telephony + * conferencing technology. + * + * @param jitsiVideobridge true if the telephony conference + * represented by the new instance is to utilize the Jitsi Videobridge + * server-side telephony conferencing technology; otherwise, false + */ + public MediaAwareCallConference(boolean jitsiVideobridge) + { + super(jitsiVideobridge); + + int mediaTypeCount = MediaType.values().length; + + devices = new MediaDevice[mediaTypeCount]; + mixers = new MediaDevice[mediaTypeCount]; + + /* + * Listen to the MediaService in order to reflect changes in the user's + * selection with respect to the default media device. + */ + addMediaServicePropertyChangeListener(propertyChangeListener); + } + + /** + * Adds a specific PropertyChangeListener to be notified about + * PropertyChangeEvents fired by the current MediaService + * implementation. The implementation adds a WeakReference to the + * specified listener because MediaAwareCallConference + * is unable to determine when the PropertyChangeListener is to be + * removed. + * + * @param listener the PropertyChangeListener to add + */ + private static synchronized void addMediaServicePropertyChangeListener( + PropertyChangeListener listener) + { + if (mediaServicePropertyChangeListener == null) + { + final MediaService mediaService + = ProtocolMediaActivator.getMediaService(); + + if (mediaService != null) + { + mediaServicePropertyChangeListener + = new WeakPropertyChangeListener() + { + @Override + protected void addThisToNotifier() + { + mediaService.addPropertyChangeListener(this); + } + + @Override + protected void removeThisFromNotifier() + { + mediaService.removePropertyChangeListener(this); + } + }; + } + } + if (mediaServicePropertyChangeListener != null) + { + mediaServicePropertyChangeListener.addPropertyChangeListener( + listener); + } + } + + /** + * {@inheritDoc} + * + * If this telephony conference switches from being a conference focus to + * not being such, disposes of the mixers used by this instance when it was + * a conference focus + */ + @Override + protected void conferenceFocusChanged(boolean oldValue, boolean newValue) + { + /* + * If this telephony conference switches from being a conference + * focus to not being one, dispose of the mixers used when it was a + * conference focus. + */ + if (oldValue && !newValue) + { + Arrays.fill(mixers, null); + + /* Disposing the video translator is not needed when the conference + changes as we have video and we will want to continue with + the video + Removed when chasing a bug where video call becomes conference + call and then back again video call and the video from the + conference focus side is not transmitted. + if (videoRTPTranslator != null) + { + videoRTPTranslator.dispose(); + videoRTPTranslator = null; + } + */ + } + + super.conferenceFocusChanged(oldValue, newValue); + } + + /** + * {@inheritDoc} + * + * Disposes of this.videoRTPTranslator if the removed Call + * was the last Call in this CallConference. + * + * @param call the Call which has been removed from the list of + * Calls participating in this telephony conference. + */ + @Override + protected void callRemoved(Call call) + { + super.callRemoved(call); + + if (getCallCount() == 0 && (videoRTPTranslator != null)) + { + videoRTPTranslator.dispose(); + videoRTPTranslator = null; + } + } + + /** + * Gets a MediaDevice which is capable of capture and/or playback + * of media of the specified MediaType and is the default choice of + * the user with respect to such a MediaDevice. + * + * @param mediaType the MediaType in which the retrieved + * MediaDevice is to capture and/or play back media + * @param useCase the MediaUseCase associated with the intended + * utilization of the MediaDevice to be retrieved + * @return a MediaDevice which is capable of capture and/or + * playback of media of the specified mediaType and is the default + * choice of the user with respect to such a MediaDevice + */ + public MediaDevice getDefaultDevice( + MediaType mediaType, + MediaUseCase useCase) + { + int mediaTypeIndex = mediaType.ordinal(); + MediaDevice device = devices[mediaTypeIndex]; + MediaService mediaService = ProtocolMediaActivator.getMediaService(); + + if (device == null) + device = mediaService.getDefaultDevice(mediaType, useCase); + + /* + * Make sure that the device is capable of mixing in order to support + * conferencing and call recording. + */ + if (device != null) + { + MediaDevice mixer = mixers[mediaTypeIndex]; + + if (mixer == null) + { + switch (mediaType) + { + case AUDIO: + /* + * TODO AudioMixer leads to very poor audio quality on + * Android so do not use it unless it is really really + * necessary. + */ + if ((!OSUtils.IS_ANDROID || isConferenceFocus()) + /* + * We can use the AudioMixer only if the device is + * able to capture (because the AudioMixer will push + * when the capture device pushes). + */ + && device.getDirection().allowsSending()) + { + mixer = mediaService.createMixer(device); + } + break; + + case VIDEO: + if (isConferenceFocus()) + mixer = mediaService.createMixer(device); + break; + } + + mixers[mediaTypeIndex] = mixer; + } + + if (mixer != null) + device = mixer; + } + + return device; + } + + /** + * Gets the VolumeControl which controls the volume (level) of the + * audio played back in the telephony conference represented by this + * instance. + * + * @return the VolumeControl which controls the volume (level) of + * the audio played back in the telephony conference represented by this + * instance + */ + public VolumeControl getOutputVolumeControl() + { + return outputVolumeControl; + } + + /** + * Gets the RTPTranslator which forwards RTP and RTCP traffic + * between the CallPeers of the Calls participating in + * this telephony conference when the local peer is acting as a conference + * focus. + * + * @param mediaType the MediaType of the MediaStream which + * RTP and RTCP traffic is to be forwarded between + * @return the RTPTranslator which forwards RTP and RTCP traffic + * between the CallPeers of the Calls participating in + * this telephony conference when the local peer is acting as a conference + * focus + */ + public RTPTranslator getRTPTranslator(MediaType mediaType) + { + RTPTranslator rtpTranslator = null; + + /* + * XXX A mixer is created for audio even when the local peer is not a + * conference focus in order to enable additional functionality. + * Similarly, the videoRTPTranslator is created even when the local peer + * is not a conference focus in order to enable the local peer to turn + * into a conference focus at a later time. More specifically, + * MediaStreamImpl is unable to accommodate an RTPTranslator after it + * has created its RTPManager. Yet again like the audio mixer, we'd + * better not try to use it on Android at this time because of + * performance issues that might arise. + */ + if (MediaType.VIDEO.equals(mediaType) + && (!OSUtils.IS_ANDROID || isConferenceFocus())) + { + if (videoRTPTranslator == null) + { + videoRTPTranslator + = ProtocolMediaActivator + .getMediaService() + .createRTPTranslator(); + } + rtpTranslator = videoRTPTranslator; + } + return rtpTranslator; + } + + /** + * Notifies this MediaAwareCallConference about changes in the + * values of the properties of sources of PropertyChangeEvents. For + * example, this instance listens to changes of the value of + * {@link MediaService#DEFAULT_DEVICE} which represents the user's choice + * with respect to the default audio device. + * + * @param ev a PropertyChangeEvent which specifies the name of the + * property which had its value changed and the old and new values of that + * property + */ + private void propertyChange(PropertyChangeEvent ev) + { + String propertyName = ev.getPropertyName(); + + if (MediaService.DEFAULT_DEVICE.equals(propertyName)) + { + Object source = ev.getSource(); + + if (source instanceof MediaService) + { + /* + * XXX We only support changing the default audio device at the + * time of this writing. + */ + int mediaTypeIndex = MediaType.AUDIO.ordinal(); + MediaDevice mixer = mixers[mediaTypeIndex]; + MediaDevice oldValue + = (mixer instanceof MediaDeviceWrapper) + ? ((MediaDeviceWrapper) mixer).getWrappedDevice() + : null; + MediaDevice newValue = devices[mediaTypeIndex]; + + if (newValue == null) + { + newValue + = ProtocolMediaActivator + .getMediaService() + .getDefaultDevice( + MediaType.AUDIO, + MediaUseCase.ANY); + } + + /* + * XXX If MediaService#getDefaultDevice(MediaType, MediaUseCase) + * above returns null and its earlier return value was not null, + * we will not notify of an actual change in the value of the + * user's choice with respect to the default audio device. + */ + if (oldValue != newValue) + { + mixers[mediaTypeIndex] = null; + firePropertyChange( + MediaAwareCall.DEFAULT_DEVICE, + oldValue, newValue); + } + } + } + } + + /** + * Sets the MediaDevice to be used by this telephony conference for + * capture and/or playback of media of a specific MediaType. + * + * @param mediaType the MediaType of the media which is to be + * captured and/or played back by the specified device + * @param device the MediaDevice to be used by this telephony + * conference for capture and/or playback of media of the specified + * mediaType + */ + void setDevice(MediaType mediaType, MediaDevice device) + { + int mediaTypeIndex = mediaType.ordinal(); + MediaDevice oldValue = devices[mediaTypeIndex]; + + /* + * XXX While we know the old and the new master/wrapped devices, we + * are not sure whether the mixer has been used. Anyway, we have to + * report different values in order to have PropertyChangeSupport + * really fire an event. + */ + MediaDevice mixer = mixers[mediaTypeIndex]; + + if (mixer instanceof MediaDeviceWrapper) + oldValue = ((MediaDeviceWrapper) mixer).getWrappedDevice(); + + MediaDevice newValue = devices[mediaTypeIndex] = device; + + if (oldValue != newValue) + { + mixers[mediaTypeIndex] = null; + firePropertyChange( + MediaAwareCall.DEFAULT_DEVICE, + oldValue, newValue); + } + } + + /** + * Implements a PropertyChangeListener which weakly references and + * delegates to specific PropertyChangeListeners and automatically + * adds itself to and removes itself from a specific + * PropertyChangeNotifier depending on whether there are + * PropertyChangeListeners to delegate to. Thus enables listening + * to a PropertyChangeNotifier by invoking + * {@link PropertyChangeNotifier#addPropertyChangeListener( + * PropertyChangeListener)} without + * {@link PropertyChangeNotifier#removePropertyChangeListener( + * PropertyChangeListener)}. + */ + private static class WeakPropertyChangeListener + implements PropertyChangeListener + { + /** + * The indicator which determines whether this + * PropertyChangeListener has been added to {@link #notifier}. + */ + private boolean added = false; + + /** + * The list of PropertyChangeListeners which are to be notified + * about PropertyChangeEvents fired by {@link #notifier}. + */ + private final List> listeners + = new LinkedList>(); + + /** + * The PropertyChangeNotifier this instance is to listen to + * about PropertyChangeEvents which are to be forwarded to + * {@link #listeners}. + */ + private final PropertyChangeNotifier notifier; + + /** + * Initializes a new WeakPropertyChangeListener instance. + */ + protected WeakPropertyChangeListener() + { + this(null); + } + + /** + * Initializes a new WeakPropertyChangeListener instance which + * is to listen to a specific PropertyChangeNotifier. + * + * @param notifier the PropertyChangeNotifier the new instance + * is to listen to + */ + public WeakPropertyChangeListener(PropertyChangeNotifier notifier) + { + this.notifier = notifier; + } + + /** + * Adds a specific PropertyChangeListener to the list of + * PropertyChangeListeners to be notified about + * PropertyChangeEvents fired by the + * PropertyChangeNotifier associated with this instance. + * + * @param listener the PropertyChangeListener to add + */ + public synchronized void addPropertyChangeListener( + PropertyChangeListener listener) + { + Iterator> i + = listeners.iterator(); + boolean add = true; + + while (i.hasNext()) + { + PropertyChangeListener l = i.next().get(); + + if (l == null) + i.remove(); + else if (l.equals(listener)) + add = false; + } + if (add + && listeners.add( + new WeakReference(listener)) + && !this.added) + { + addThisToNotifier(); + this.added = true; + } + } + + /** + * Adds this as a PropertyChangeListener to {@link #notifier}. + */ + protected void addThisToNotifier() + { + if (notifier != null) + notifier.addPropertyChangeListener(this); + } + + /** + * {@inheritDoc} + * + * Notifies this instance about a PropertyChangeEvent fired by + * {@link #notifier}. + */ + @Override + public void propertyChange(PropertyChangeEvent ev) + { + PropertyChangeListener[] ls; + int n; + + synchronized (this) + { + Iterator> i + = listeners.iterator(); + + ls = new PropertyChangeListener[listeners.size()]; + n = 0; + while (i.hasNext()) + { + PropertyChangeListener l = i.next().get(); + + if (l == null) + i.remove(); + else + ls[n++] = l; + } + if ((n == 0) && this.added) + { + removeThisFromNotifier(); + this.added = false; + } + } + + if (n != 0) + { + for (PropertyChangeListener l : ls) + { + if (l == null) + break; + else + l.propertyChange(ev); + } + } + } + + /** + * Removes a specific PropertyChangeListener from the list of + * PropertyChangeListeners to be notified about + * PropertyChangeEvents fired by the + * PropertyChangeNotifier associated with this instance. + * + * @param listener the PropertyChangeListener to remove + */ + @SuppressWarnings("unused") + public synchronized void removePropertyChangeListener( + PropertyChangeListener listener) + { + Iterator> i + = listeners.iterator(); + + while (i.hasNext()) + { + PropertyChangeListener l = i.next().get(); + + if ((l == null) || l.equals(listener)) + i.remove(); + } + if (this.added && (listeners.size() == 0)) + { + removeThisFromNotifier(); + this.added = false; + } + } + + /** + * Removes this as a PropertyChangeListener from + * {@link #notifier}. + */ + protected void removeThisFromNotifier() + { + if (notifier != null) + notifier.removePropertyChangeListener(this); + } + } +} diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java index 4e15038..23e42d4 100644 --- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java +++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1247 +15,1247 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol.media; - -import java.beans.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.neomedia.*; -import org.jitsi.service.neomedia.event.*; - -/** - * A utility class implementing media control code shared between current - * telephony implementations. This class is only meant for use by protocol - * implementations and should/could not be accessed by bundles that are simply - * using the telephony functionalities. - * - * @param the peer extension class like for example CallSipImpl - * or CallJabberImpl - * @param the media handler extension class like for example - * CallPeerMediaHandlerSipImpl or - * CallPeerMediaHandlerJabberImpl - * @param the provider extension class like for example - * ProtocolProviderServiceSipImpl or - * ProtocolProviderServiceJabberImpl - * - * @author Emil Ivov - * @author Lyubomir Marinov - * @author Boris Grozev - */ -public abstract class MediaAwareCallPeer - , - U extends CallPeerMediaHandler, - V extends ProtocolProviderService> - extends AbstractCallPeer - implements SrtpListener, - CallPeerConferenceListener, - CsrcAudioLevelListener, - SimpleAudioLevelListener -{ - /** - * The Logger used by the MediaAwareCallPeer class and its - * instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(MediaAwareCallPeer.class); - - /** - * The call this peer belongs to. - */ - private T call; - - /** - * The listeners registered for level changes in the audio of participants - * that this peer might be mixing and that we are not directly communicating - * with. - */ - private final List - conferenceMembersSoundLevelListeners - = new ArrayList(); - - /** - * A byte array containing the image/photo representing the call peer. - */ - private byte[] image; - - /** - * The media handler class handles all media management for a single - * CallPeer. This includes initializing and configuring streams, - * generating SDP, handling ICE, etc. One instance of CallPeeralways - * corresponds to exactly one instance of CallPeerMediaHandler and - * both classes are only separated for reasons of readability. - */ - private U mediaHandler; - - /** - * The PropertyChangeListener which listens to - * {@link CallPeerMediaHandler} for changes in the values of its properties. - */ - private PropertyChangeListener mediaHandlerPropertyChangeListener; - - /** - * A string uniquely identifying the peer. - */ - private String peerID; - - /** - * The protocol provider that this peer belongs to. - */ - private final V protocolProvider; - - /** - * The list of SoundLevelListeners interested in level changes in - * the audio we are getting from the remote peer. - *

    - * It is implemented as a copy-on-write storage because the number of - * additions and removals of SoundLevelListeners is expected to be - * far smaller than the number of audio level changes. The access to it is - * to be synchronized using {@link #streamSoundLevelListenersSyncRoot}. - *

    - */ - private List streamSoundLevelListeners; - - /** - * The Object to synchronize the access to - * {@link #streamSoundLevelListeners}. - */ - private final Object streamSoundLevelListenersSyncRoot = new Object(); - - /** - * The List of PropertyChangeListeners listening to this - * CallPeer for changes in the values of its properties related to - * video. - */ - private final List videoPropertyChangeListeners - = new LinkedList(); - - /** - * Represents the last Conference Information (RFC4575) document sent to - * this CallPeer. This is always a document with state "full", even - * if the last document actually sent was a "partial" - */ - private ConferenceInfoDocument lastConferenceInfoSent = null; - - /** - * The time (as obtained by System.currentTimeMillis()) at which - * a Conference Information (RFC4575) document was last sent to this - * CallPeer. - */ - private long lastConferenceInfoSentTimestamp = -1; - - /** - * The last Conference Information (RFC4575) document sent to us by this - * CallPeer. This is always a document with state "full", which is - * only gets updated by "partial" or "deleted" documents. - */ - private ConferenceInfoDocument lastConferenceInfoReceived = null; - - /** - * Whether a conference-info document has been scheduled to be sent to this - * CallPeer - */ - private boolean confInfoScheduled = false; - - /** - * Synchronization object for confInfoScheduled - */ - private final Object confInfoScheduledSyncRoot = new Object(); - - /** - * Creates a new call peer with address peerAddress. - * - * @param owningCall the call that contains this call peer. - */ - public MediaAwareCallPeer(T owningCall) - { - this.call = owningCall; - this.protocolProvider = owningCall.getProtocolProvider(); - - // create the uid - this.peerID - = String.valueOf(System.currentTimeMillis()) - + String.valueOf(hashCode()); - - // we listen for events when the call will become focus or not - // of a conference so we will add or remove our sound level listeners - super.addCallPeerConferenceListener(this); - } - - /** - * Adds a specific ConferenceMembersSoundLevelListener to the list - * of listeners interested in and notified about changes in conference - * members sound level. - * - * @param listener the ConferenceMembersSoundLevelListener to add - * @throws NullPointerException if listener is null - */ - public void addConferenceMembersSoundLevelListener( - ConferenceMembersSoundLevelListener listener) - { - /* - * XXX The uses of the method at the time of this writing rely on being - * able to add a null listener so make it a no-op here. - */ - if (listener == null) - return; - - synchronized (conferenceMembersSoundLevelListeners) - { - if (conferenceMembersSoundLevelListeners.size() == 0) - { - // if this is the first listener that's being registered with - // us, we also need to register ourselves as a CSRC audio level - // listener with the media handler. - getMediaHandler().setCsrcAudioLevelListener(this); - } - conferenceMembersSoundLevelListeners.add(listener); - } - } - - /** - * Adds a specific SoundLevelListener to the list of listeners - * interested in and notified about changes in the sound level of the audio - * sent by the remote party. When the first listener is being registered - * the method also registers its single listener with the media handler so - * that it would receive level change events and delegate them to the - * listeners that have registered with us. - * - * @param listener the SoundLevelListener to add - */ - public void addStreamSoundLevelListener(SoundLevelListener listener) - { - synchronized (streamSoundLevelListenersSyncRoot) - { - if ((streamSoundLevelListeners == null) - || streamSoundLevelListeners.isEmpty()) - { - CallPeerMediaHandler mediaHandler = getMediaHandler(); - - if (isJitsiVideobridge()) - { - /* - * When the local user/peer has organized a telephony - * conference utilizing the Jitsi Videobridge server-side - * technology, the server will calculate the audio levels - * and not the client. - */ - mediaHandler.setCsrcAudioLevelListener(this); - } - else - { - /* - * If this is the first listener that's being registered - * with us, we also need to register ourselves as an audio - * level listener with the media handler. We do this so that - * audio levels would only be calculated if anyone is - * interested in receiving them. - */ - mediaHandler.setStreamAudioLevelListener(this); - } - } - - /* - * Implement streamAudioLevelListeners as a copy-on-write storage so - * that iterators over it can iterate without - * ConcurrentModificationExceptions. - */ - streamSoundLevelListeners - = (streamSoundLevelListeners == null) - ? new ArrayList() - : new ArrayList( - streamSoundLevelListeners); - streamSoundLevelListeners.add(listener); - } - } - - /** - * Adds a specific PropertyChangeListener to the list of - * listeners which get notified when the properties (e.g. - * LOCAL_VIDEO_STREAMING) associated with this CallPeer change - * their values. - * - * @param listener the PropertyChangeListener to be notified - * when the properties associated with the specified Call change - * their values - */ - public void addVideoPropertyChangeListener(PropertyChangeListener listener) - { - if (listener == null) - throw new NullPointerException("listener"); - - synchronized (videoPropertyChangeListeners) - { - /* - * The video is part of the media-related functionality and thus it - * is the responsibility of mediaHandler. So listen to mediaHandler - * for video-related property changes and re-fire them as - * originating from this instance. - */ - if (!videoPropertyChangeListeners.contains(listener) - && videoPropertyChangeListeners.add(listener) - && (mediaHandlerPropertyChangeListener == null)) - { - mediaHandlerPropertyChangeListener - = new PropertyChangeListener() - { - public void propertyChange(PropertyChangeEvent event) - { - Iterable listeners; - - synchronized (videoPropertyChangeListeners) - { - listeners - = new LinkedList( - videoPropertyChangeListeners); - } - - PropertyChangeEvent thisEvent - = new PropertyChangeEvent( - this, - event.getPropertyName(), - event.getOldValue(), - event.getNewValue()); - - for (PropertyChangeListener listener : listeners) - listener.propertyChange(thisEvent); - } - }; - getMediaHandler() - .addPropertyChangeListener( - mediaHandlerPropertyChangeListener); - } - } - } - - /** - * Notified by its very majesty the media service about changes in the audio - * level of the stream coming from this peer, the method generates the - * corresponding events and delivers them to the listeners that have - * registered here. - * - * @param newLevel the new audio level of the audio stream received from the - * remote peer - */ - public void audioLevelChanged(int newLevel) - { - /* - * If we're in a conference in which this CallPeer is the focus and - * we're the only member in it besides the focus, we will not receive - * audio levels in the RTP and our media will instead measure the audio - * levels of the received media. In order to make the UI oblivious of - * the difference, we have to translate the event to the appropriate - * type of listener. - * - * We may end up in a conference call with 0 members if the server - * for some reason doesn't support sip conference (our subscribes - * doesn't go to the focus of the conference) and so we must - * pass the sound levels measured on the stream so we can see - * the stream activity of the call. - */ - int conferenceMemberCount = getConferenceMemberCount(); - - if ((conferenceMemberCount > 0) && (conferenceMemberCount < 3)) - { - long audioRemoteSSRC - = getMediaHandler().getRemoteSSRC(MediaType.AUDIO); - - if (audioRemoteSSRC != CallPeerMediaHandler.SSRC_UNKNOWN) - { - audioLevelsReceived(new long[] { audioRemoteSSRC, newLevel }); - return; - } - } - - fireStreamSoundLevelChanged(newLevel); - } - - - /** - * Implements {@link CsrcAudioLevelListener#audioLevelsReceived(long[])}. - * Delivers the received audio levels to the - * {@link ConferenceMembersSoundLevelListener}s registered with this - * MediaAwareCallPeer.. - * - * @param audioLevels the levels that we need to dispatch to all registered - * ConferenceMemberSoundLevelListeners. - */ - public void audioLevelsReceived(long[] audioLevels) - { - /* - * When the local user/peer has organized a telephony conference - * utilizing the Jitsi Videobridge server-side technology, the server - * will calculate the audio levels and not the client. - */ - if (isJitsiVideobridge()) - { - long audioRemoteSSRC - = getMediaHandler().getRemoteSSRC(MediaType.AUDIO); - - if (audioRemoteSSRC != CallPeerMediaHandler.SSRC_UNKNOWN) - { - for (int i = 0; i < audioLevels.length; i += 2) - { - if (audioLevels[i] == audioRemoteSSRC) - { - fireStreamSoundLevelChanged((int) audioLevels[i + 1]); - break; - } - } - } - } - - if (getConferenceMemberCount() == 0) - return; - - Map levelsMap - = new HashMap(); - - for (int i = 0; i < audioLevels.length; i += 2) - { - ConferenceMember mmbr = findConferenceMember(audioLevels[i]); - - if (mmbr != null) - levelsMap.put(mmbr, (int) audioLevels[i + 1]); - } - - synchronized (conferenceMembersSoundLevelListeners) - { - int conferenceMemberSoundLevelListenerCount - = conferenceMembersSoundLevelListeners.size(); - - if (conferenceMemberSoundLevelListenerCount > 0) - { - ConferenceMembersSoundLevelEvent ev - = new ConferenceMembersSoundLevelEvent(this, levelsMap); - - for (int i = 0; - i < conferenceMemberSoundLevelListenerCount; - i++) - { - conferenceMembersSoundLevelListeners - .get(i) - .soundLevelChanged(ev); - } - } - } - } - - /** - * Does nothing. - * @param evt the event. - */ - public void callPeerAdded(CallPeerEvent evt) {} - - /** - * Does nothing. - * @param evt the event. - */ - public void callPeerRemoved(CallPeerEvent evt) {} - - /** - * Dummy implementation of {@link CallPeerConferenceListener - * #conferenceFocusChanged(CallPeerConferenceEvent)}. - * - * @param evt ignored - */ - public void conferenceFocusChanged(CallPeerConferenceEvent evt) - { - } - - /** - * Called when this peer becomes a mixer. The method add removes this class - * as the stream audio level listener for the media coming from this peer - * because the levels it delivers no longer represent the level of a - * particular member. The method also adds this class as a member (CSRC) - * audio level listener. - * - * @param conferenceEvent the event containing information (that we don't - * really use) on the newly add member. - */ - public void conferenceMemberAdded(CallPeerConferenceEvent conferenceEvent) - { - if (getConferenceMemberCount() > 2) - { - /* - * This peer is now a conference focus with more than three - * participants. It means that this peer is mixing and sending us - * audio for at least two separate participants. We therefore need - * to switch from stream to CSRC level listening. - */ - CallPeerMediaHandler mediaHandler = getMediaHandler(); - - mediaHandler.setStreamAudioLevelListener(null); - mediaHandler.setCsrcAudioLevelListener(this); - } - } - - /** - * Dummy implementation of {@link CallPeerConferenceListener - * #conferenceMemberErrorReceived(CallPeerConferenceEvent)}. - * - * @param ev the event - */ - public void conferenceMemberErrorReceived(CallPeerConferenceEvent ev) {}; - - /** - * Called when this peer stops being a mixer. The method add removes this - * class as the stream audio level listener for the media coming from this - * peer because the levels it delivers no longer represent the level of a - * particular member. The method also adds this class as a member (CSRC) - * audio level listener. - * - * @param conferenceEvent the event containing information (that we don't - * really use) on the freshly removed member. - */ - public void conferenceMemberRemoved(CallPeerConferenceEvent conferenceEvent) - { - if (getConferenceMemberCount() < 3) - { - /* - * This call peer is no longer mixing audio from multiple sources - * since there's only us and her in the call. We therefore need to - * switch from CSRC to stream level listening. - */ - CallPeerMediaHandler mediaHandler = getMediaHandler(); - - mediaHandler.setStreamAudioLevelListener(this); - mediaHandler.setCsrcAudioLevelListener(null); - } - } - - /** - * Invokes {@link SoundLevelListener#soundLevelChanged(Object, int) on - * the SoundLevelListeners interested in the changes of the audio - * stream received from the remote peer i.e. in - * {@link #streamSoundLevelListeners}. - * - * @param newLevel the new value of the sound level to notify - * streamSoundLevelListeners about - */ - private void fireStreamSoundLevelChanged(int newLevel) - { - List streamSoundLevelListeners; - - synchronized (streamSoundLevelListenersSyncRoot) - { - /* - * Since the streamAudioLevelListeners field of this - * MediaAwareCallPeer is implemented as a copy-on-write storage, - * just get a reference to it and it should be safe to iterate over it - * without ConcurrentModificationExceptions. - */ - streamSoundLevelListeners = this.streamSoundLevelListeners; - } - - if (streamSoundLevelListeners != null) - { - /* - * Iterate over streamAudioLevelListeners using an index rather than - * an Iterator in order to try to reduce the number of allocations - * (as the number of audio level changes is expected to be very - * large). - */ - int streamSoundLevelListenerCount - = streamSoundLevelListeners.size(); - - for(int i = 0; i < streamSoundLevelListenerCount; i++) - { - streamSoundLevelListeners.get(i).soundLevelChanged( - this, - newLevel); - } - } - } - - /** - * Returns a reference to the call that this peer belongs to. Calls - * are created by underlying telephony protocol implementations. - * - * @return a reference to the call containing this peer. - */ - @Override - public T getCall() - { - return call; - } - - /** - * The method returns an image representation of the call peer if one is - * available. - * - * @return byte[] a byte array containing the image or null if no image is - * available. - */ - public byte[] getImage() - { - return image; - } - - /** - * Returns a reference to the CallPeerMediaHandler used by this - * peer. The media handler class handles all media management for a single - * CallPeer. This includes initializing and configuring streams, - * generating SDP, handling ICE, etc. One instance of CallPeer - * always corresponds to exactly one instance of - * CallPeerMediaHandler and both classes are only separated for - * reasons of readability. - * - * @return a reference to the CallPeerMediaHandler instance that - * this peer uses for media related tips and tricks. - */ - public U getMediaHandler() - { - return mediaHandler; - } - - /** - * Returns a unique identifier representing this peer. - * - * @return an identifier representing this call peer. - */ - public String getPeerID() - { - return peerID; - } - - /** - * Returns the protocol provider that this peer belongs to. - * - * @return a reference to the ProtocolProviderService that this - * peer belongs to. - */ - @Override - public V getProtocolProvider() - { - return protocolProvider; - } - - /** - * Determines whether this CallPeer is participating in a telephony - * conference organized by the local user/peer utilizing the Jitsi - * Videobridge server-side technology. - * - * @return true if this CallPeer is participating in a - * telephony conference organized by the local user/peer utilizing the Jitsi - * Videobridge server-side technology; otherwise, false - */ - public final boolean isJitsiVideobridge() - { - Call call = getCall(); - - if (call != null) - { - CallConference conference = call.getConference(); - - if (conference != null) - return conference.isJitsiVideobridge(); - } - return false; - } - - /** - * Determines whether we are currently streaming video toward whoever this - * MediaAwareCallPeer represents. - * - * @return true if we are currently streaming video toward this - * CallPeer and false otherwise. - */ - public boolean isLocalVideoStreaming() - { - return getMediaHandler().isLocalVideoTransmissionEnabled(); - } - - /** - * Determines whether the audio stream (if any) being sent to this - * peer is mute. - * - * @return true if an audio stream is being sent to this - * peer and it is currently mute; false, otherwise - */ - @Override - public boolean isMute() - { - return getMediaHandler().isMute(); - } - - /** - * Logs message and cause and sets this peer's - * state to CallPeerState.FAILED - * - * @param message a message to log and display to the user. - * @param throwable the exception that cause the error we are logging - */ - public void logAndFail(String message, Throwable throwable) - { - logger.error(message, throwable); - setState(CallPeerState.FAILED, message); - } - - /** - * Updates the state of this CallPeer to match the locally-on-hold - * status of our media handler. - */ - public void reevalLocalHoldStatus() - { - CallPeerState state = getState(); - boolean locallyOnHold = getMediaHandler().isLocallyOnHold(); - - if (CallPeerState.ON_HOLD_LOCALLY.equals(state)) - { - if (!locallyOnHold) - setState(CallPeerState.CONNECTED); - } - else if (CallPeerState.ON_HOLD_MUTUALLY.equals(state)) - { - if (!locallyOnHold) - setState(CallPeerState.ON_HOLD_REMOTELY); - } - else if (CallPeerState.ON_HOLD_REMOTELY.equals(state)) - { - if (locallyOnHold) - setState(CallPeerState.ON_HOLD_MUTUALLY); - } - else if (locallyOnHold) - { - setState(CallPeerState.ON_HOLD_LOCALLY); - } - } - - /** - * Updates the state of this CallPeer to match the remotely-on-hold - * status of our media handler. - */ - public void reevalRemoteHoldStatus() - { - boolean remotelyOnHold = getMediaHandler().isRemotelyOnHold(); - - CallPeerState state = getState(); - if (CallPeerState.ON_HOLD_LOCALLY.equals(state)) - { - if (remotelyOnHold) - setState(CallPeerState.ON_HOLD_MUTUALLY); - } - else if (CallPeerState.ON_HOLD_MUTUALLY.equals(state)) - { - if (!remotelyOnHold) - setState(CallPeerState.ON_HOLD_LOCALLY); - } - else if (CallPeerState.ON_HOLD_REMOTELY.equals(state)) - { - if (!remotelyOnHold) - setState(CallPeerState.CONNECTED); - } - else if (remotelyOnHold) - { - setState(CallPeerState.ON_HOLD_REMOTELY); - } - } - - /** - * Removes a specific ConferenceMembersSoundLevelListener of the - * list of listeners interested in and notified about changes in conference - * members sound level. - * - * @param listener the ConferenceMembersSoundLevelListener to - * remove - */ - public void removeConferenceMembersSoundLevelListener( - ConferenceMembersSoundLevelListener listener) - { - synchronized (conferenceMembersSoundLevelListeners) - { - if (conferenceMembersSoundLevelListeners.remove(listener) - && (conferenceMembersSoundLevelListeners.size() == 0)) - { - // if this was the last listener then we also remove ourselves - // as a CSRC audio level listener from the handler so that we - // don't have to create new events and maps for something no one - // is interested in. - getMediaHandler().setCsrcAudioLevelListener(null); - } - } - } - - /** - * Removes a specific SoundLevelListener of the list of - * listeners interested in and notified about changes in stream sound level - * related information. - * - * @param listener the SoundLevelListener to remove - */ - public void removeStreamSoundLevelListener(SoundLevelListener listener) - { - synchronized (streamSoundLevelListenersSyncRoot) - { - /* - * Implement streamAudioLevelListeners as a copy-on-write storage so - * that iterators over it can iterate over it without - * ConcurrentModificationExceptions. - */ - if (streamSoundLevelListeners != null) - { - streamSoundLevelListeners - = new ArrayList( - streamSoundLevelListeners); - if (streamSoundLevelListeners.remove(listener) - && streamSoundLevelListeners.isEmpty()) - streamSoundLevelListeners = null; - } - - if ((streamSoundLevelListeners == null) - || streamSoundLevelListeners.isEmpty()) - { - // if this was the last listener then we also need to remove - // ourselves as an audio level so that audio levels would only - // be calculated if anyone is interested in receiving them. - getMediaHandler().setStreamAudioLevelListener(null); - } - } - } - - /** - * Removes a specific PropertyChangeListener from the list of - * listeners which get notified when the properties (e.g. - * LOCAL_VIDEO_STREAMING) associated with this CallPeer change - * their values. - * - * @param listener the PropertyChangeListener to no longer be - * notified when the properties associated with the specified Call - * change their values - */ - public void removeVideoPropertyChangeListener( - PropertyChangeListener listener) - { - if (listener != null) - synchronized (videoPropertyChangeListeners) - { - /* - * The video is part of the media-related functionality and thus - * it is the responsibility of mediaHandler. So we're listening - * to mediaHandler for video-related property changes and w're - * re-firing them as originating from this instance. Make sure - * that we're not listening to mediaHandler if noone is - * interested in video-related property changes originating from - * this instance. - */ - if (videoPropertyChangeListeners.remove(listener) - && videoPropertyChangeListeners.isEmpty() - && (mediaHandlerPropertyChangeListener != null)) - { -// getMediaHandler() -// .removePropertyChangeListener( -// mediaHandlerPropertyChangeListener); - mediaHandlerPropertyChangeListener = null; - } - } - } - - /** - * Sets the security message associated with a failure/warning or - * information coming from the encryption protocol. - * - * @param messageType the type of the message. - * @param i18nMessage the message - * @param severity severity level - */ - public void securityMessageReceived( - String messageType, - String i18nMessage, - int severity) - { - fireCallPeerSecurityMessageEvent(messageType, - i18nMessage, - severity); - } - - /** - * Indicates that the other party has timeouted replying to our - * offer to secure the connection. - * - * @param mediaType the MediaType of the call session - * @param sender the security controller that caused the event - */ - public void securityNegotiationStarted( - MediaType mediaType, - SrtpControl sender) - { - fireCallPeerSecurityNegotiationStartedEvent( - new CallPeerSecurityNegotiationStartedEvent( - this, - toSessionType(mediaType), - sender)); - } - - /** - * Indicates that the other party has timeouted replying to our - * offer to secure the connection. - * - * @param mediaType the MediaType of the call session - */ - public void securityTimeout(MediaType mediaType) - { - fireCallPeerSecurityTimeoutEvent( - new CallPeerSecurityTimeoutEvent( - this, - toSessionType(mediaType))); - } - - /** - * Sets the security status to OFF for this call peer. - * - * @param mediaType the MediaType of the call session - */ - public void securityTurnedOff(MediaType mediaType) - { - // If this event has been triggered because of a call end event and the - // call is already ended we don't need to alert the user for - // security off. - if((call != null) && !call.getCallState().equals(CallState.CALL_ENDED)) - { - fireCallPeerSecurityOffEvent( - new CallPeerSecurityOffEvent( - this, - toSessionType(mediaType))); - } - } - - /** - * Sets the security status to ON for this call peer. - * - * @param mediaType the MediaType of the call session - * @param cipher the cipher - * @param sender the security controller that caused the event - */ - public void securityTurnedOn( - MediaType mediaType, - String cipher, - SrtpControl sender) - { - getMediaHandler().startSrtpMultistream(sender); - fireCallPeerSecurityOnEvent( - new CallPeerSecurityOnEvent( - this, - toSessionType(mediaType), - cipher, - sender)); - } - - /** - * Sets the call containing this peer. - * - * @param call the call that this call peer is participating in. - */ - public void setCall(T call) - { - this.call = call; - } - - /** - * Sets the byte array containing an image representation (photo or picture) - * of the call peer. - * - * @param image a byte array containing the image - */ - public void setImage(byte[] image) - { - byte[] oldImage = getImage(); - this.image = image; - - //Fire the Event - fireCallPeerChangeEvent( - CallPeerChangeEvent.CALL_PEER_IMAGE_CHANGE, - oldImage, - image); - } - - /** - * Modifies the local media setup to reflect the requested setting for the - * streaming of the local video and then re-invites the peer represented by - * this class using a corresponding SDP description.. - * - * @param allowed true if local video transmission is allowed and - * false otherwise. - * - * @throws OperationFailedException if video initialization fails. - */ - public void setLocalVideoAllowed(boolean allowed) - throws OperationFailedException - { - CallPeerMediaHandler mediaHandler = getMediaHandler(); - - if(mediaHandler.isLocalVideoTransmissionEnabled() != allowed) - { - // Modify the local media setup to reflect the requested setting for - // the streaming of the local video. - mediaHandler.setLocalVideoTransmissionEnabled(allowed); - } - } - - /** - * Sets a reference to the CallPeerMediaHandler used by this - * peer. The media handler class handles all media management for a single - * CallPeer. This includes initializing and configuring streams, - * generating SDP, handling ICE, etc. One instance of CallPeer - * always corresponds to exactly one instance of - * CallPeerMediaHandler and both classes are only separated for - * reasons of readability. - * - * @param mediaHandler a reference to the CallPeerMediaHandler - * instance that this peer uses for media related tips and tricks. - */ - protected void setMediaHandler(U mediaHandler) - { - this.mediaHandler = mediaHandler; - } - - /** - * Sets the mute property for this call peer. - * - * @param newMuteValue the new value of the mute property for this call peer - */ - @Override - public void setMute(boolean newMuteValue) - { - getMediaHandler().setMute(newMuteValue); - super.setMute(newMuteValue); - } - - /** - * Sets the String that serves as a unique identifier of this - * CallPeer. - * @param peerID the ID of this call peer. - */ - public void setPeerID(String peerID) - { - this.peerID = peerID; - } - - /** - * Overrides the parent set state method in order to make sure that we - * close our media handler whenever we enter a disconnected state. - * - * @param newState the CallPeerState that we are about to enter and - * that we pass to our predecessor. - * @param reason a reason phrase explaining the state (e.g. if newState - * indicates a failure) and that we pass to our predecessor. - * @param reasonCode the code for the reason of the state change. - */ - @Override - public void setState(CallPeerState newState, String reason, int reasonCode) - { - // synchronized to mediaHandler if there are currently jobs of - // initializing, configuring and starting streams (method processAnswer - // of CallPeerMediaHandler) we won't set and fire the current state - // to Disconnected. Before closing the mediaHandler is setting the state - // in order to deliver states as quick as possible. - CallPeerMediaHandler mediaHandler = getMediaHandler(); - - synchronized(mediaHandler) - { - try - { - super.setState(newState, reason, reasonCode); - } - finally - { - // make sure whatever happens to close the media - if (CallPeerState.DISCONNECTED.equals(newState) - || CallPeerState.FAILED.equals(newState)) - mediaHandler.close(); - } - } - } - - /** - * Returns the last ConferenceInfoDocument sent by us to this - * CallPeer. It is a document with state full - * @return the last ConferenceInfoDocument sent by us to this - * CallPeer. It is a document with state full - */ - public ConferenceInfoDocument getLastConferenceInfoSent() - { - return lastConferenceInfoSent; - } - - /** - * Sets the last ConferenceInfoDocument sent by us to this - * CallPeer. - * @param confInfo the document to set. - */ - public void setLastConferenceInfoSent(ConferenceInfoDocument confInfo) - { - lastConferenceInfoSent = confInfo; - } - - /** - * Gets the time (as obtained by System.currentTimeMillis()) - * at which we last sent a ConferenceInfoDocument to this - * CallPeer. - * @return the time (as obtained by System.currentTimeMillis()) - * at which we last sent a ConferenceInfoDocument to this - * CallPeer. - */ - public long getLastConferenceInfoSentTimestamp() - { - return lastConferenceInfoSentTimestamp; - } - - /** - * Sets the time (as obtained by System.currentTimeMillis()) - * at which we last sent a ConferenceInfoDocument to this - * CallPeer. - * @param newTimestamp the time to set - */ - public void setLastConferenceInfoSentTimestamp(long newTimestamp) - { - lastConferenceInfoSentTimestamp = newTimestamp; - } - - /** - * Gets the last ConferenceInfoDocument sent to us by this - * CallPeer. - * @return the last ConferenceInfoDocument sent to us by this - * CallPeer. - */ - public ConferenceInfoDocument getLastConferenceInfoReceived() - { - return lastConferenceInfoReceived; - } - - /** - * Gets the last ConferenceInfoDocument sent to us by this - * CallPeer. - * @return the last ConferenceInfoDocument sent to us by this - * CallPeer. - */ - public void setLastConferenceInfoReceived(ConferenceInfoDocument confInfo) - { - lastConferenceInfoReceived = confInfo; - } - - /** - * Gets the version of the last ConferenceInfoDocument - * sent to us by this CallPeer, or -1 if we haven't (yet) received - * a ConferenceInformationDocument from this CallPeer. - * @return - */ - public int getLastConferenceInfoReceivedVersion() - { - return (lastConferenceInfoReceived == null) - ? -1 - : lastConferenceInfoReceived.getVersion(); - } - - /** - * Gets the String to be used for this CallPeer when - * we describe it in a ConferenceInfoDocument (e.g. the - * entity key attribute which to use for the user - * element corresponding to this CallPeer) - * - * @return the String to be used for this CallPeer when - * we describe it in a ConferenceInfoDocument (e.g. the - * entity key attribute which to use for the user - * element corresponding to this CallPeer) - */ - public abstract String getEntity(); - - /** - * Check whether a conference-info document is scheduled to be sent to - * this CallPeer (i.e. there is a thread which will eventually - * (after sleeping a certain amount of time) trigger a document to be sent) - * @return true if there is a conference-info document scheduled - * to be sent to this CallPeer and false otherwise. - */ - public boolean isConfInfoScheduled() - { - synchronized (confInfoScheduledSyncRoot) - { - return confInfoScheduled; - } - } - - /** - * Sets the property which indicates whether a conference-info document - * is scheduled to be sent to this CallPeer. - * @param confInfoScheduled - */ - public void setConfInfoScheduled(boolean confInfoScheduled) - { - synchronized (confInfoScheduledSyncRoot) - { - this.confInfoScheduled = confInfoScheduled; - } - } - - /** - * Returns the direction of the session for media of type mediaType - * that we have with this CallPeer. This is the direction of the - * session negotiated in the signaling protocol, and it may or may not - * coincide with the direction of the media stream. - * For example, if we are the focus of a videobridge conference and another - * peer is sending video to us, we have a RECVONLY video stream, - * but SENDONLY or SENDRECV (Jingle) sessions with the - * rest of the conference members. - * Should always return non-null. - * - * @param mediaType the MediaType to use - * @return Returns the direction of the session for media of type - * mediaType that we have with this CallPeer. - */ - public abstract MediaDirection getDirection(MediaType mediaType); - - /** - * {@inheritDoc} - * - * When a ConferenceMember is removed from a conference with a - * Jitsi-videobridge, an RTCP BYE packet is not always sent. Therefore, - * if the ConferenceMember had an associated video SSRC, the stream - * isn't be removed until it times out, leaving a blank video container in - * the interface for a few seconds. - * TODO: This works around the problem by removing the - * ConferenceMember's ReceiveStream when the - * ConferenceMember is removed. The proper solution is to ensure - * that RTCP BYEs are sent whenever necessary, and when it is deployed this - * code should be removed. - * - * @param conferenceMember a ConferenceMember to be removed from - * the list of ConferenceMember reported by this peer. If the - * specified ConferenceMember is no contained in the list, no event - */ - @Override - public void removeConferenceMember(ConferenceMember conferenceMember) - { - MediaStream videoStream = getMediaHandler().getStream(MediaType.VIDEO); - if (videoStream != null) - videoStream.removeReceiveStreamForSsrc( - conferenceMember.getVideoSsrc()); - - super.removeConferenceMember(conferenceMember); - } - - /** - * Converts a specific MediaType into a sessionType value - * in the terms of the CallPeerSecurityStatusEvent class. - * - * @param mediaType the MediaType to be converted - * @return the sessionType value in the terms of the - * CallPeerSecurityStatusEvent class that is equivalent to the - * specified mediaType - */ - private static int toSessionType(MediaType mediaType) - { - switch (mediaType) - { - case AUDIO: - return CallPeerSecurityStatusEvent.AUDIO_SESSION; - case VIDEO: - return CallPeerSecurityStatusEvent.VIDEO_SESSION; - default: - throw new IllegalArgumentException("mediaType"); - } - } -} +package net.java.sip.communicator.service.protocol.media; + +import java.beans.*; +import java.util.*; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.neomedia.*; +import org.jitsi.service.neomedia.event.*; + +/** + * A utility class implementing media control code shared between current + * telephony implementations. This class is only meant for use by protocol + * implementations and should/could not be accessed by bundles that are simply + * using the telephony functionalities. + * + * @param the peer extension class like for example CallSipImpl + * or CallJabberImpl + * @param the media handler extension class like for example + * CallPeerMediaHandlerSipImpl or + * CallPeerMediaHandlerJabberImpl + * @param the provider extension class like for example + * ProtocolProviderServiceSipImpl or + * ProtocolProviderServiceJabberImpl + * + * @author Emil Ivov + * @author Lyubomir Marinov + * @author Boris Grozev + */ +public abstract class MediaAwareCallPeer + , + U extends CallPeerMediaHandler, + V extends ProtocolProviderService> + extends AbstractCallPeer + implements SrtpListener, + CallPeerConferenceListener, + CsrcAudioLevelListener, + SimpleAudioLevelListener +{ + /** + * The Logger used by the MediaAwareCallPeer class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(MediaAwareCallPeer.class); + + /** + * The call this peer belongs to. + */ + private T call; + + /** + * The listeners registered for level changes in the audio of participants + * that this peer might be mixing and that we are not directly communicating + * with. + */ + private final List + conferenceMembersSoundLevelListeners + = new ArrayList(); + + /** + * A byte array containing the image/photo representing the call peer. + */ + private byte[] image; + + /** + * The media handler class handles all media management for a single + * CallPeer. This includes initializing and configuring streams, + * generating SDP, handling ICE, etc. One instance of CallPeeralways + * corresponds to exactly one instance of CallPeerMediaHandler and + * both classes are only separated for reasons of readability. + */ + private U mediaHandler; + + /** + * The PropertyChangeListener which listens to + * {@link CallPeerMediaHandler} for changes in the values of its properties. + */ + private PropertyChangeListener mediaHandlerPropertyChangeListener; + + /** + * A string uniquely identifying the peer. + */ + private String peerID; + + /** + * The protocol provider that this peer belongs to. + */ + private final V protocolProvider; + + /** + * The list of SoundLevelListeners interested in level changes in + * the audio we are getting from the remote peer. + *

    + * It is implemented as a copy-on-write storage because the number of + * additions and removals of SoundLevelListeners is expected to be + * far smaller than the number of audio level changes. The access to it is + * to be synchronized using {@link #streamSoundLevelListenersSyncRoot}. + *

    + */ + private List streamSoundLevelListeners; + + /** + * The Object to synchronize the access to + * {@link #streamSoundLevelListeners}. + */ + private final Object streamSoundLevelListenersSyncRoot = new Object(); + + /** + * The List of PropertyChangeListeners listening to this + * CallPeer for changes in the values of its properties related to + * video. + */ + private final List videoPropertyChangeListeners + = new LinkedList(); + + /** + * Represents the last Conference Information (RFC4575) document sent to + * this CallPeer. This is always a document with state "full", even + * if the last document actually sent was a "partial" + */ + private ConferenceInfoDocument lastConferenceInfoSent = null; + + /** + * The time (as obtained by System.currentTimeMillis()) at which + * a Conference Information (RFC4575) document was last sent to this + * CallPeer. + */ + private long lastConferenceInfoSentTimestamp = -1; + + /** + * The last Conference Information (RFC4575) document sent to us by this + * CallPeer. This is always a document with state "full", which is + * only gets updated by "partial" or "deleted" documents. + */ + private ConferenceInfoDocument lastConferenceInfoReceived = null; + + /** + * Whether a conference-info document has been scheduled to be sent to this + * CallPeer + */ + private boolean confInfoScheduled = false; + + /** + * Synchronization object for confInfoScheduled + */ + private final Object confInfoScheduledSyncRoot = new Object(); + + /** + * Creates a new call peer with address peerAddress. + * + * @param owningCall the call that contains this call peer. + */ + public MediaAwareCallPeer(T owningCall) + { + this.call = owningCall; + this.protocolProvider = owningCall.getProtocolProvider(); + + // create the uid + this.peerID + = String.valueOf(System.currentTimeMillis()) + + String.valueOf(hashCode()); + + // we listen for events when the call will become focus or not + // of a conference so we will add or remove our sound level listeners + super.addCallPeerConferenceListener(this); + } + + /** + * Adds a specific ConferenceMembersSoundLevelListener to the list + * of listeners interested in and notified about changes in conference + * members sound level. + * + * @param listener the ConferenceMembersSoundLevelListener to add + * @throws NullPointerException if listener is null + */ + public void addConferenceMembersSoundLevelListener( + ConferenceMembersSoundLevelListener listener) + { + /* + * XXX The uses of the method at the time of this writing rely on being + * able to add a null listener so make it a no-op here. + */ + if (listener == null) + return; + + synchronized (conferenceMembersSoundLevelListeners) + { + if (conferenceMembersSoundLevelListeners.size() == 0) + { + // if this is the first listener that's being registered with + // us, we also need to register ourselves as a CSRC audio level + // listener with the media handler. + getMediaHandler().setCsrcAudioLevelListener(this); + } + conferenceMembersSoundLevelListeners.add(listener); + } + } + + /** + * Adds a specific SoundLevelListener to the list of listeners + * interested in and notified about changes in the sound level of the audio + * sent by the remote party. When the first listener is being registered + * the method also registers its single listener with the media handler so + * that it would receive level change events and delegate them to the + * listeners that have registered with us. + * + * @param listener the SoundLevelListener to add + */ + public void addStreamSoundLevelListener(SoundLevelListener listener) + { + synchronized (streamSoundLevelListenersSyncRoot) + { + if ((streamSoundLevelListeners == null) + || streamSoundLevelListeners.isEmpty()) + { + CallPeerMediaHandler mediaHandler = getMediaHandler(); + + if (isJitsiVideobridge()) + { + /* + * When the local user/peer has organized a telephony + * conference utilizing the Jitsi Videobridge server-side + * technology, the server will calculate the audio levels + * and not the client. + */ + mediaHandler.setCsrcAudioLevelListener(this); + } + else + { + /* + * If this is the first listener that's being registered + * with us, we also need to register ourselves as an audio + * level listener with the media handler. We do this so that + * audio levels would only be calculated if anyone is + * interested in receiving them. + */ + mediaHandler.setStreamAudioLevelListener(this); + } + } + + /* + * Implement streamAudioLevelListeners as a copy-on-write storage so + * that iterators over it can iterate without + * ConcurrentModificationExceptions. + */ + streamSoundLevelListeners + = (streamSoundLevelListeners == null) + ? new ArrayList() + : new ArrayList( + streamSoundLevelListeners); + streamSoundLevelListeners.add(listener); + } + } + + /** + * Adds a specific PropertyChangeListener to the list of + * listeners which get notified when the properties (e.g. + * LOCAL_VIDEO_STREAMING) associated with this CallPeer change + * their values. + * + * @param listener the PropertyChangeListener to be notified + * when the properties associated with the specified Call change + * their values + */ + public void addVideoPropertyChangeListener(PropertyChangeListener listener) + { + if (listener == null) + throw new NullPointerException("listener"); + + synchronized (videoPropertyChangeListeners) + { + /* + * The video is part of the media-related functionality and thus it + * is the responsibility of mediaHandler. So listen to mediaHandler + * for video-related property changes and re-fire them as + * originating from this instance. + */ + if (!videoPropertyChangeListeners.contains(listener) + && videoPropertyChangeListeners.add(listener) + && (mediaHandlerPropertyChangeListener == null)) + { + mediaHandlerPropertyChangeListener + = new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent event) + { + Iterable listeners; + + synchronized (videoPropertyChangeListeners) + { + listeners + = new LinkedList( + videoPropertyChangeListeners); + } + + PropertyChangeEvent thisEvent + = new PropertyChangeEvent( + this, + event.getPropertyName(), + event.getOldValue(), + event.getNewValue()); + + for (PropertyChangeListener listener : listeners) + listener.propertyChange(thisEvent); + } + }; + getMediaHandler() + .addPropertyChangeListener( + mediaHandlerPropertyChangeListener); + } + } + } + + /** + * Notified by its very majesty the media service about changes in the audio + * level of the stream coming from this peer, the method generates the + * corresponding events and delivers them to the listeners that have + * registered here. + * + * @param newLevel the new audio level of the audio stream received from the + * remote peer + */ + public void audioLevelChanged(int newLevel) + { + /* + * If we're in a conference in which this CallPeer is the focus and + * we're the only member in it besides the focus, we will not receive + * audio levels in the RTP and our media will instead measure the audio + * levels of the received media. In order to make the UI oblivious of + * the difference, we have to translate the event to the appropriate + * type of listener. + * + * We may end up in a conference call with 0 members if the server + * for some reason doesn't support sip conference (our subscribes + * doesn't go to the focus of the conference) and so we must + * pass the sound levels measured on the stream so we can see + * the stream activity of the call. + */ + int conferenceMemberCount = getConferenceMemberCount(); + + if ((conferenceMemberCount > 0) && (conferenceMemberCount < 3)) + { + long audioRemoteSSRC + = getMediaHandler().getRemoteSSRC(MediaType.AUDIO); + + if (audioRemoteSSRC != CallPeerMediaHandler.SSRC_UNKNOWN) + { + audioLevelsReceived(new long[] { audioRemoteSSRC, newLevel }); + return; + } + } + + fireStreamSoundLevelChanged(newLevel); + } + + + /** + * Implements {@link CsrcAudioLevelListener#audioLevelsReceived(long[])}. + * Delivers the received audio levels to the + * {@link ConferenceMembersSoundLevelListener}s registered with this + * MediaAwareCallPeer.. + * + * @param audioLevels the levels that we need to dispatch to all registered + * ConferenceMemberSoundLevelListeners. + */ + public void audioLevelsReceived(long[] audioLevels) + { + /* + * When the local user/peer has organized a telephony conference + * utilizing the Jitsi Videobridge server-side technology, the server + * will calculate the audio levels and not the client. + */ + if (isJitsiVideobridge()) + { + long audioRemoteSSRC + = getMediaHandler().getRemoteSSRC(MediaType.AUDIO); + + if (audioRemoteSSRC != CallPeerMediaHandler.SSRC_UNKNOWN) + { + for (int i = 0; i < audioLevels.length; i += 2) + { + if (audioLevels[i] == audioRemoteSSRC) + { + fireStreamSoundLevelChanged((int) audioLevels[i + 1]); + break; + } + } + } + } + + if (getConferenceMemberCount() == 0) + return; + + Map levelsMap + = new HashMap(); + + for (int i = 0; i < audioLevels.length; i += 2) + { + ConferenceMember mmbr = findConferenceMember(audioLevels[i]); + + if (mmbr != null) + levelsMap.put(mmbr, (int) audioLevels[i + 1]); + } + + synchronized (conferenceMembersSoundLevelListeners) + { + int conferenceMemberSoundLevelListenerCount + = conferenceMembersSoundLevelListeners.size(); + + if (conferenceMemberSoundLevelListenerCount > 0) + { + ConferenceMembersSoundLevelEvent ev + = new ConferenceMembersSoundLevelEvent(this, levelsMap); + + for (int i = 0; + i < conferenceMemberSoundLevelListenerCount; + i++) + { + conferenceMembersSoundLevelListeners + .get(i) + .soundLevelChanged(ev); + } + } + } + } + + /** + * Does nothing. + * @param evt the event. + */ + public void callPeerAdded(CallPeerEvent evt) {} + + /** + * Does nothing. + * @param evt the event. + */ + public void callPeerRemoved(CallPeerEvent evt) {} + + /** + * Dummy implementation of {@link CallPeerConferenceListener + * #conferenceFocusChanged(CallPeerConferenceEvent)}. + * + * @param evt ignored + */ + public void conferenceFocusChanged(CallPeerConferenceEvent evt) + { + } + + /** + * Called when this peer becomes a mixer. The method add removes this class + * as the stream audio level listener for the media coming from this peer + * because the levels it delivers no longer represent the level of a + * particular member. The method also adds this class as a member (CSRC) + * audio level listener. + * + * @param conferenceEvent the event containing information (that we don't + * really use) on the newly add member. + */ + public void conferenceMemberAdded(CallPeerConferenceEvent conferenceEvent) + { + if (getConferenceMemberCount() > 2) + { + /* + * This peer is now a conference focus with more than three + * participants. It means that this peer is mixing and sending us + * audio for at least two separate participants. We therefore need + * to switch from stream to CSRC level listening. + */ + CallPeerMediaHandler mediaHandler = getMediaHandler(); + + mediaHandler.setStreamAudioLevelListener(null); + mediaHandler.setCsrcAudioLevelListener(this); + } + } + + /** + * Dummy implementation of {@link CallPeerConferenceListener + * #conferenceMemberErrorReceived(CallPeerConferenceEvent)}. + * + * @param ev the event + */ + public void conferenceMemberErrorReceived(CallPeerConferenceEvent ev) {}; + + /** + * Called when this peer stops being a mixer. The method add removes this + * class as the stream audio level listener for the media coming from this + * peer because the levels it delivers no longer represent the level of a + * particular member. The method also adds this class as a member (CSRC) + * audio level listener. + * + * @param conferenceEvent the event containing information (that we don't + * really use) on the freshly removed member. + */ + public void conferenceMemberRemoved(CallPeerConferenceEvent conferenceEvent) + { + if (getConferenceMemberCount() < 3) + { + /* + * This call peer is no longer mixing audio from multiple sources + * since there's only us and her in the call. We therefore need to + * switch from CSRC to stream level listening. + */ + CallPeerMediaHandler mediaHandler = getMediaHandler(); + + mediaHandler.setStreamAudioLevelListener(this); + mediaHandler.setCsrcAudioLevelListener(null); + } + } + + /** + * Invokes {@link SoundLevelListener#soundLevelChanged(Object, int) on + * the SoundLevelListeners interested in the changes of the audio + * stream received from the remote peer i.e. in + * {@link #streamSoundLevelListeners}. + * + * @param newLevel the new value of the sound level to notify + * streamSoundLevelListeners about + */ + private void fireStreamSoundLevelChanged(int newLevel) + { + List streamSoundLevelListeners; + + synchronized (streamSoundLevelListenersSyncRoot) + { + /* + * Since the streamAudioLevelListeners field of this + * MediaAwareCallPeer is implemented as a copy-on-write storage, + * just get a reference to it and it should be safe to iterate over it + * without ConcurrentModificationExceptions. + */ + streamSoundLevelListeners = this.streamSoundLevelListeners; + } + + if (streamSoundLevelListeners != null) + { + /* + * Iterate over streamAudioLevelListeners using an index rather than + * an Iterator in order to try to reduce the number of allocations + * (as the number of audio level changes is expected to be very + * large). + */ + int streamSoundLevelListenerCount + = streamSoundLevelListeners.size(); + + for(int i = 0; i < streamSoundLevelListenerCount; i++) + { + streamSoundLevelListeners.get(i).soundLevelChanged( + this, + newLevel); + } + } + } + + /** + * Returns a reference to the call that this peer belongs to. Calls + * are created by underlying telephony protocol implementations. + * + * @return a reference to the call containing this peer. + */ + @Override + public T getCall() + { + return call; + } + + /** + * The method returns an image representation of the call peer if one is + * available. + * + * @return byte[] a byte array containing the image or null if no image is + * available. + */ + public byte[] getImage() + { + return image; + } + + /** + * Returns a reference to the CallPeerMediaHandler used by this + * peer. The media handler class handles all media management for a single + * CallPeer. This includes initializing and configuring streams, + * generating SDP, handling ICE, etc. One instance of CallPeer + * always corresponds to exactly one instance of + * CallPeerMediaHandler and both classes are only separated for + * reasons of readability. + * + * @return a reference to the CallPeerMediaHandler instance that + * this peer uses for media related tips and tricks. + */ + public U getMediaHandler() + { + return mediaHandler; + } + + /** + * Returns a unique identifier representing this peer. + * + * @return an identifier representing this call peer. + */ + public String getPeerID() + { + return peerID; + } + + /** + * Returns the protocol provider that this peer belongs to. + * + * @return a reference to the ProtocolProviderService that this + * peer belongs to. + */ + @Override + public V getProtocolProvider() + { + return protocolProvider; + } + + /** + * Determines whether this CallPeer is participating in a telephony + * conference organized by the local user/peer utilizing the Jitsi + * Videobridge server-side technology. + * + * @return true if this CallPeer is participating in a + * telephony conference organized by the local user/peer utilizing the Jitsi + * Videobridge server-side technology; otherwise, false + */ + public final boolean isJitsiVideobridge() + { + Call call = getCall(); + + if (call != null) + { + CallConference conference = call.getConference(); + + if (conference != null) + return conference.isJitsiVideobridge(); + } + return false; + } + + /** + * Determines whether we are currently streaming video toward whoever this + * MediaAwareCallPeer represents. + * + * @return true if we are currently streaming video toward this + * CallPeer and false otherwise. + */ + public boolean isLocalVideoStreaming() + { + return getMediaHandler().isLocalVideoTransmissionEnabled(); + } + + /** + * Determines whether the audio stream (if any) being sent to this + * peer is mute. + * + * @return true if an audio stream is being sent to this + * peer and it is currently mute; false, otherwise + */ + @Override + public boolean isMute() + { + return getMediaHandler().isMute(); + } + + /** + * Logs message and cause and sets this peer's + * state to CallPeerState.FAILED + * + * @param message a message to log and display to the user. + * @param throwable the exception that cause the error we are logging + */ + public void logAndFail(String message, Throwable throwable) + { + logger.error(message, throwable); + setState(CallPeerState.FAILED, message); + } + + /** + * Updates the state of this CallPeer to match the locally-on-hold + * status of our media handler. + */ + public void reevalLocalHoldStatus() + { + CallPeerState state = getState(); + boolean locallyOnHold = getMediaHandler().isLocallyOnHold(); + + if (CallPeerState.ON_HOLD_LOCALLY.equals(state)) + { + if (!locallyOnHold) + setState(CallPeerState.CONNECTED); + } + else if (CallPeerState.ON_HOLD_MUTUALLY.equals(state)) + { + if (!locallyOnHold) + setState(CallPeerState.ON_HOLD_REMOTELY); + } + else if (CallPeerState.ON_HOLD_REMOTELY.equals(state)) + { + if (locallyOnHold) + setState(CallPeerState.ON_HOLD_MUTUALLY); + } + else if (locallyOnHold) + { + setState(CallPeerState.ON_HOLD_LOCALLY); + } + } + + /** + * Updates the state of this CallPeer to match the remotely-on-hold + * status of our media handler. + */ + public void reevalRemoteHoldStatus() + { + boolean remotelyOnHold = getMediaHandler().isRemotelyOnHold(); + + CallPeerState state = getState(); + if (CallPeerState.ON_HOLD_LOCALLY.equals(state)) + { + if (remotelyOnHold) + setState(CallPeerState.ON_HOLD_MUTUALLY); + } + else if (CallPeerState.ON_HOLD_MUTUALLY.equals(state)) + { + if (!remotelyOnHold) + setState(CallPeerState.ON_HOLD_LOCALLY); + } + else if (CallPeerState.ON_HOLD_REMOTELY.equals(state)) + { + if (!remotelyOnHold) + setState(CallPeerState.CONNECTED); + } + else if (remotelyOnHold) + { + setState(CallPeerState.ON_HOLD_REMOTELY); + } + } + + /** + * Removes a specific ConferenceMembersSoundLevelListener of the + * list of listeners interested in and notified about changes in conference + * members sound level. + * + * @param listener the ConferenceMembersSoundLevelListener to + * remove + */ + public void removeConferenceMembersSoundLevelListener( + ConferenceMembersSoundLevelListener listener) + { + synchronized (conferenceMembersSoundLevelListeners) + { + if (conferenceMembersSoundLevelListeners.remove(listener) + && (conferenceMembersSoundLevelListeners.size() == 0)) + { + // if this was the last listener then we also remove ourselves + // as a CSRC audio level listener from the handler so that we + // don't have to create new events and maps for something no one + // is interested in. + getMediaHandler().setCsrcAudioLevelListener(null); + } + } + } + + /** + * Removes a specific SoundLevelListener of the list of + * listeners interested in and notified about changes in stream sound level + * related information. + * + * @param listener the SoundLevelListener to remove + */ + public void removeStreamSoundLevelListener(SoundLevelListener listener) + { + synchronized (streamSoundLevelListenersSyncRoot) + { + /* + * Implement streamAudioLevelListeners as a copy-on-write storage so + * that iterators over it can iterate over it without + * ConcurrentModificationExceptions. + */ + if (streamSoundLevelListeners != null) + { + streamSoundLevelListeners + = new ArrayList( + streamSoundLevelListeners); + if (streamSoundLevelListeners.remove(listener) + && streamSoundLevelListeners.isEmpty()) + streamSoundLevelListeners = null; + } + + if ((streamSoundLevelListeners == null) + || streamSoundLevelListeners.isEmpty()) + { + // if this was the last listener then we also need to remove + // ourselves as an audio level so that audio levels would only + // be calculated if anyone is interested in receiving them. + getMediaHandler().setStreamAudioLevelListener(null); + } + } + } + + /** + * Removes a specific PropertyChangeListener from the list of + * listeners which get notified when the properties (e.g. + * LOCAL_VIDEO_STREAMING) associated with this CallPeer change + * their values. + * + * @param listener the PropertyChangeListener to no longer be + * notified when the properties associated with the specified Call + * change their values + */ + public void removeVideoPropertyChangeListener( + PropertyChangeListener listener) + { + if (listener != null) + synchronized (videoPropertyChangeListeners) + { + /* + * The video is part of the media-related functionality and thus + * it is the responsibility of mediaHandler. So we're listening + * to mediaHandler for video-related property changes and w're + * re-firing them as originating from this instance. Make sure + * that we're not listening to mediaHandler if noone is + * interested in video-related property changes originating from + * this instance. + */ + if (videoPropertyChangeListeners.remove(listener) + && videoPropertyChangeListeners.isEmpty() + && (mediaHandlerPropertyChangeListener != null)) + { +// getMediaHandler() +// .removePropertyChangeListener( +// mediaHandlerPropertyChangeListener); + mediaHandlerPropertyChangeListener = null; + } + } + } + + /** + * Sets the security message associated with a failure/warning or + * information coming from the encryption protocol. + * + * @param messageType the type of the message. + * @param i18nMessage the message + * @param severity severity level + */ + public void securityMessageReceived( + String messageType, + String i18nMessage, + int severity) + { + fireCallPeerSecurityMessageEvent(messageType, + i18nMessage, + severity); + } + + /** + * Indicates that the other party has timeouted replying to our + * offer to secure the connection. + * + * @param mediaType the MediaType of the call session + * @param sender the security controller that caused the event + */ + public void securityNegotiationStarted( + MediaType mediaType, + SrtpControl sender) + { + fireCallPeerSecurityNegotiationStartedEvent( + new CallPeerSecurityNegotiationStartedEvent( + this, + toSessionType(mediaType), + sender)); + } + + /** + * Indicates that the other party has timeouted replying to our + * offer to secure the connection. + * + * @param mediaType the MediaType of the call session + */ + public void securityTimeout(MediaType mediaType) + { + fireCallPeerSecurityTimeoutEvent( + new CallPeerSecurityTimeoutEvent( + this, + toSessionType(mediaType))); + } + + /** + * Sets the security status to OFF for this call peer. + * + * @param mediaType the MediaType of the call session + */ + public void securityTurnedOff(MediaType mediaType) + { + // If this event has been triggered because of a call end event and the + // call is already ended we don't need to alert the user for + // security off. + if((call != null) && !call.getCallState().equals(CallState.CALL_ENDED)) + { + fireCallPeerSecurityOffEvent( + new CallPeerSecurityOffEvent( + this, + toSessionType(mediaType))); + } + } + + /** + * Sets the security status to ON for this call peer. + * + * @param mediaType the MediaType of the call session + * @param cipher the cipher + * @param sender the security controller that caused the event + */ + public void securityTurnedOn( + MediaType mediaType, + String cipher, + SrtpControl sender) + { + getMediaHandler().startSrtpMultistream(sender); + fireCallPeerSecurityOnEvent( + new CallPeerSecurityOnEvent( + this, + toSessionType(mediaType), + cipher, + sender)); + } + + /** + * Sets the call containing this peer. + * + * @param call the call that this call peer is participating in. + */ + public void setCall(T call) + { + this.call = call; + } + + /** + * Sets the byte array containing an image representation (photo or picture) + * of the call peer. + * + * @param image a byte array containing the image + */ + public void setImage(byte[] image) + { + byte[] oldImage = getImage(); + this.image = image; + + //Fire the Event + fireCallPeerChangeEvent( + CallPeerChangeEvent.CALL_PEER_IMAGE_CHANGE, + oldImage, + image); + } + + /** + * Modifies the local media setup to reflect the requested setting for the + * streaming of the local video and then re-invites the peer represented by + * this class using a corresponding SDP description.. + * + * @param allowed true if local video transmission is allowed and + * false otherwise. + * + * @throws OperationFailedException if video initialization fails. + */ + public void setLocalVideoAllowed(boolean allowed) + throws OperationFailedException + { + CallPeerMediaHandler mediaHandler = getMediaHandler(); + + if(mediaHandler.isLocalVideoTransmissionEnabled() != allowed) + { + // Modify the local media setup to reflect the requested setting for + // the streaming of the local video. + mediaHandler.setLocalVideoTransmissionEnabled(allowed); + } + } + + /** + * Sets a reference to the CallPeerMediaHandler used by this + * peer. The media handler class handles all media management for a single + * CallPeer. This includes initializing and configuring streams, + * generating SDP, handling ICE, etc. One instance of CallPeer + * always corresponds to exactly one instance of + * CallPeerMediaHandler and both classes are only separated for + * reasons of readability. + * + * @param mediaHandler a reference to the CallPeerMediaHandler + * instance that this peer uses for media related tips and tricks. + */ + protected void setMediaHandler(U mediaHandler) + { + this.mediaHandler = mediaHandler; + } + + /** + * Sets the mute property for this call peer. + * + * @param newMuteValue the new value of the mute property for this call peer + */ + @Override + public void setMute(boolean newMuteValue) + { + getMediaHandler().setMute(newMuteValue); + super.setMute(newMuteValue); + } + + /** + * Sets the String that serves as a unique identifier of this + * CallPeer. + * @param peerID the ID of this call peer. + */ + public void setPeerID(String peerID) + { + this.peerID = peerID; + } + + /** + * Overrides the parent set state method in order to make sure that we + * close our media handler whenever we enter a disconnected state. + * + * @param newState the CallPeerState that we are about to enter and + * that we pass to our predecessor. + * @param reason a reason phrase explaining the state (e.g. if newState + * indicates a failure) and that we pass to our predecessor. + * @param reasonCode the code for the reason of the state change. + */ + @Override + public void setState(CallPeerState newState, String reason, int reasonCode) + { + // synchronized to mediaHandler if there are currently jobs of + // initializing, configuring and starting streams (method processAnswer + // of CallPeerMediaHandler) we won't set and fire the current state + // to Disconnected. Before closing the mediaHandler is setting the state + // in order to deliver states as quick as possible. + CallPeerMediaHandler mediaHandler = getMediaHandler(); + + synchronized(mediaHandler) + { + try + { + super.setState(newState, reason, reasonCode); + } + finally + { + // make sure whatever happens to close the media + if (CallPeerState.DISCONNECTED.equals(newState) + || CallPeerState.FAILED.equals(newState)) + mediaHandler.close(); + } + } + } + + /** + * Returns the last ConferenceInfoDocument sent by us to this + * CallPeer. It is a document with state full + * @return the last ConferenceInfoDocument sent by us to this + * CallPeer. It is a document with state full + */ + public ConferenceInfoDocument getLastConferenceInfoSent() + { + return lastConferenceInfoSent; + } + + /** + * Sets the last ConferenceInfoDocument sent by us to this + * CallPeer. + * @param confInfo the document to set. + */ + public void setLastConferenceInfoSent(ConferenceInfoDocument confInfo) + { + lastConferenceInfoSent = confInfo; + } + + /** + * Gets the time (as obtained by System.currentTimeMillis()) + * at which we last sent a ConferenceInfoDocument to this + * CallPeer. + * @return the time (as obtained by System.currentTimeMillis()) + * at which we last sent a ConferenceInfoDocument to this + * CallPeer. + */ + public long getLastConferenceInfoSentTimestamp() + { + return lastConferenceInfoSentTimestamp; + } + + /** + * Sets the time (as obtained by System.currentTimeMillis()) + * at which we last sent a ConferenceInfoDocument to this + * CallPeer. + * @param newTimestamp the time to set + */ + public void setLastConferenceInfoSentTimestamp(long newTimestamp) + { + lastConferenceInfoSentTimestamp = newTimestamp; + } + + /** + * Gets the last ConferenceInfoDocument sent to us by this + * CallPeer. + * @return the last ConferenceInfoDocument sent to us by this + * CallPeer. + */ + public ConferenceInfoDocument getLastConferenceInfoReceived() + { + return lastConferenceInfoReceived; + } + + /** + * Gets the last ConferenceInfoDocument sent to us by this + * CallPeer. + * @return the last ConferenceInfoDocument sent to us by this + * CallPeer. + */ + public void setLastConferenceInfoReceived(ConferenceInfoDocument confInfo) + { + lastConferenceInfoReceived = confInfo; + } + + /** + * Gets the version of the last ConferenceInfoDocument + * sent to us by this CallPeer, or -1 if we haven't (yet) received + * a ConferenceInformationDocument from this CallPeer. + * @return + */ + public int getLastConferenceInfoReceivedVersion() + { + return (lastConferenceInfoReceived == null) + ? -1 + : lastConferenceInfoReceived.getVersion(); + } + + /** + * Gets the String to be used for this CallPeer when + * we describe it in a ConferenceInfoDocument (e.g. the + * entity key attribute which to use for the user + * element corresponding to this CallPeer) + * + * @return the String to be used for this CallPeer when + * we describe it in a ConferenceInfoDocument (e.g. the + * entity key attribute which to use for the user + * element corresponding to this CallPeer) + */ + public abstract String getEntity(); + + /** + * Check whether a conference-info document is scheduled to be sent to + * this CallPeer (i.e. there is a thread which will eventually + * (after sleeping a certain amount of time) trigger a document to be sent) + * @return true if there is a conference-info document scheduled + * to be sent to this CallPeer and false otherwise. + */ + public boolean isConfInfoScheduled() + { + synchronized (confInfoScheduledSyncRoot) + { + return confInfoScheduled; + } + } + + /** + * Sets the property which indicates whether a conference-info document + * is scheduled to be sent to this CallPeer. + * @param confInfoScheduled + */ + public void setConfInfoScheduled(boolean confInfoScheduled) + { + synchronized (confInfoScheduledSyncRoot) + { + this.confInfoScheduled = confInfoScheduled; + } + } + + /** + * Returns the direction of the session for media of type mediaType + * that we have with this CallPeer. This is the direction of the + * session negotiated in the signaling protocol, and it may or may not + * coincide with the direction of the media stream. + * For example, if we are the focus of a videobridge conference and another + * peer is sending video to us, we have a RECVONLY video stream, + * but SENDONLY or SENDRECV (Jingle) sessions with the + * rest of the conference members. + * Should always return non-null. + * + * @param mediaType the MediaType to use + * @return Returns the direction of the session for media of type + * mediaType that we have with this CallPeer. + */ + public abstract MediaDirection getDirection(MediaType mediaType); + + /** + * {@inheritDoc} + * + * When a ConferenceMember is removed from a conference with a + * Jitsi-videobridge, an RTCP BYE packet is not always sent. Therefore, + * if the ConferenceMember had an associated video SSRC, the stream + * isn't be removed until it times out, leaving a blank video container in + * the interface for a few seconds. + * TODO: This works around the problem by removing the + * ConferenceMember's ReceiveStream when the + * ConferenceMember is removed. The proper solution is to ensure + * that RTCP BYEs are sent whenever necessary, and when it is deployed this + * code should be removed. + * + * @param conferenceMember a ConferenceMember to be removed from + * the list of ConferenceMember reported by this peer. If the + * specified ConferenceMember is no contained in the list, no event + */ + @Override + public void removeConferenceMember(ConferenceMember conferenceMember) + { + MediaStream videoStream = getMediaHandler().getStream(MediaType.VIDEO); + if (videoStream != null) + videoStream.removeReceiveStreamForSsrc( + conferenceMember.getVideoSsrc()); + + super.removeConferenceMember(conferenceMember); + } + + /** + * Converts a specific MediaType into a sessionType value + * in the terms of the CallPeerSecurityStatusEvent class. + * + * @param mediaType the MediaType to be converted + * @return the sessionType value in the terms of the + * CallPeerSecurityStatusEvent class that is equivalent to the + * specified mediaType + */ + private static int toSessionType(MediaType mediaType) + { + switch (mediaType) + { + case AUDIO: + return CallPeerSecurityStatusEvent.AUDIO_SESSION; + case VIDEO: + return CallPeerSecurityStatusEvent.VIDEO_SESSION; + default: + throw new IllegalArgumentException("mediaType"); + } + } +} diff --git a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java index 973ebcb..7906199 100644 --- a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java +++ b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,870 +15,870 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.protocol.media; - -import java.net.*; - -import net.java.sip.communicator.service.netaddr.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.ice4j.ice.*; -import org.jitsi.service.configuration.*; -import org.jitsi.service.neomedia.*; - -/** - * TransportManagers are responsible for allocating ports, gathering - * local candidates and managing ICE whenever we are using it. - * - * @param the peer extension class like for example CallPeerSipImpl - * or CallPeerJabberImpl - * - * @author Emil Ivov - * @author Lyubomir Marinov - * @author Sebastien Vincent - */ -public abstract class TransportManager> -{ - /** - * The Logger used by the TransportManager - * class and its instances for logging output. - */ - private static final Logger logger - = Logger.getLogger(TransportManager.class); - - /** - * The port tracker that we should use when binding generic media streams. - *

    - * Initialized by {@link #initializePortNumbers()}. - *

    - */ - private static final PortTracker defaultPortTracker - = new PortTracker(5000, 6000); - - /** - * The port tracker that we should use when binding video media streams. - *

    - * Potentially initialized by {@link #initializePortNumbers()} if the - * necessary properties are set. - *

    - */ - private static PortTracker videoPortTracker; - - /** - * The port tracker that we should use when binding data channels. - *

    - * Potentially initialized by {@link #initializePortNumbers()} if the - * necessary properties are set. - *

    - */ - private static PortTracker dataPortTracker; - - /** - * The port tracker that we should use when binding data media streams. - *

    - * Potentially initialized by {@link #initializePortNumbers()} if the - * necessary properties are set. - *

    - */ - private static PortTracker audioPortTracker; - - /** - * RTP audio DSCP configuration property name. - */ - private static final String RTP_AUDIO_DSCP_PROPERTY = - "net.java.sip.communicator.impl.protocol.RTP_AUDIO_DSCP"; - - /** - * RTP video DSCP configuration property name. - */ - private static final String RTP_VIDEO_DSCP_PROPERTY = - "net.java.sip.communicator.impl.protocol.RTP_VIDEO_DSCP"; - - /** - * Number of empty UDP packets to send for NAT hole punching. - */ - private static final String HOLE_PUNCH_PKT_COUNT_PROPERTY = - "net.java.sip.communicator.impl.protocol.HOLE_PUNCH_PKT_COUNT"; - - /** - * Number of empty UDP packets to send for NAT hole punching. - */ - private static final int DEFAULT_HOLE_PUNCH_PKT_COUNT = 3; - - /** - * The {@link MediaAwareCallPeer} whose traffic we will be taking care of. - */ - private U callPeer; - - /** - * The RTP/RTCP socket couples that this TransportManager uses to - * send and receive media flows through indexed by MediaType - * (ordinal). - */ - private final StreamConnector[] streamConnectors - = new StreamConnector[MediaType.values().length]; - - /** - * Creates a new instance of this transport manager, binding it to the - * specified peer. - * - * @param callPeer the {@link MediaAwareCallPeer} whose traffic we will be - * taking care of. - */ - protected TransportManager(U callPeer) - { - this.callPeer = callPeer; - } - - /** - * Returns the StreamConnector instance that this media handler - * should use for streams of the specified mediaType. The method - * would also create a new StreamConnector if no connector has - * been initialized for this mediaType yet or in case one - * of its underlying sockets has been closed. - * - * @param mediaType the MediaType that we'd like to create a - * connector for. - * @return this media handler's StreamConnector for the specified - * mediaType. - * - * @throws OperationFailedException in case we failed to initialize our - * connector. - */ - public StreamConnector getStreamConnector(MediaType mediaType) - throws OperationFailedException - { - int streamConnectorIndex = mediaType.ordinal(); - StreamConnector streamConnector - = streamConnectors[streamConnectorIndex]; - - if((streamConnector == null) - || (streamConnector.getProtocol() == StreamConnector.Protocol.UDP)) - { - DatagramSocket controlSocket; - - if((streamConnector == null) - || streamConnector.getDataSocket().isClosed() - || (((controlSocket = streamConnector.getControlSocket()) - != null) - && controlSocket.isClosed())) - { - streamConnectors[streamConnectorIndex] - = streamConnector - = createStreamConnector(mediaType); - } - } - else if(streamConnector.getProtocol() == StreamConnector.Protocol.TCP) - { - Socket controlTCPSocket; - - if(streamConnector.getDataTCPSocket().isClosed() - || (((controlTCPSocket = streamConnector.getControlTCPSocket()) - != null) - && controlTCPSocket.isClosed())) - { - streamConnectors[streamConnectorIndex] - = streamConnector - = createStreamConnector(mediaType); - } - } - return streamConnector; - } - - /** - * Closes the existing StreamConnector, if any, associated with a - * specific MediaType and removes its reference from this - * TransportManager. - * - * @param mediaType the MediaType associated with the - * StreamConnector to close - */ - public void closeStreamConnector(MediaType mediaType) - { - int index = mediaType.ordinal(); - StreamConnector streamConnector = streamConnectors[index]; - - if (streamConnector != null) - { - closeStreamConnector(mediaType, streamConnector); - streamConnectors[index] = null; - } - } - - /** - * Closes a specific StreamConnector associated with a specific - * MediaType. If this TransportManager has a reference to - * the specified streamConnector, it remains. Allows extenders to - * override and perform additional customizations to the closing of the - * specified streamConnector. - * - * @param mediaType the MediaType associated with the specified - * streamConnector - * @param streamConnector the StreamConnector to be closed - * @see #closeStreamConnector(MediaType) - */ - protected void closeStreamConnector( - MediaType mediaType, - StreamConnector streamConnector) - { - /* - * XXX The connected owns the sockets so it is important that it - * decides whether to close them i.e. this TransportManager is not - * allowed to explicitly close the sockets by itself. - */ - streamConnector.close(); - } - - /** - * Creates a media StreamConnector for a stream of a specific - * MediaType. The minimum and maximum of the media port boundaries - * are taken into account. - * - * @param mediaType the MediaType of the stream for which a - * StreamConnector is to be created - * @return a StreamConnector for the stream of the specified - * mediaType - * @throws OperationFailedException if the binding of the sockets fails - */ - protected StreamConnector createStreamConnector(MediaType mediaType) - throws OperationFailedException - { - NetworkAddressManagerService nam - = ProtocolMediaActivator.getNetworkAddressManagerService(); - InetAddress intendedDestination = getIntendedDestination(getCallPeer()); - InetAddress localHostForPeer = nam.getLocalHost(intendedDestination); - - PortTracker portTracker = getPortTracker(mediaType); - - //create the RTP socket. - DatagramSocket rtpSocket = null; - try - { - rtpSocket = nam.createDatagramSocket( - localHostForPeer, portTracker.getPort(), - portTracker.getMinPort(), portTracker.getMaxPort()); - } - catch (Exception exc) - { - throw new OperationFailedException( - "Failed to allocate the network ports necessary for the call.", - OperationFailedException.INTERNAL_ERROR, exc); - } - - //make sure that next time we don't try to bind on occupied ports - //also, refuse validation in case someone set the tracker range to 1 - portTracker.setNextPort( rtpSocket.getLocalPort() + 1, false); - - //create the RTCP socket, preferably on the port following our RTP one. - DatagramSocket rtcpSocket = null; - try - { - rtcpSocket = nam.createDatagramSocket( - localHostForPeer, portTracker.getPort(), - portTracker.getMinPort(), portTracker.getMaxPort()); - } - catch (Exception exc) - { - throw new OperationFailedException( - "Failed to allocate the network ports necessary for the call.", - OperationFailedException.INTERNAL_ERROR, - exc); - } - - //make sure that next time we don't try to bind on occupied ports - portTracker.setNextPort( rtcpSocket.getLocalPort() + 1); - - return new DefaultStreamConnector(rtpSocket, rtcpSocket); - } - - /** - * Tries to set the ranges of the PortTrackers (e.g. default, - * audio, video, data channel) to the values specified in the - * ConfigurationService. - */ - protected synchronized static void initializePortNumbers() - { - //try the default tracker first - ConfigurationService cfg - = ProtocolMediaActivator.getConfigurationService(); - String minPort, maxPort; - - minPort - = cfg.getString( - OperationSetBasicTelephony - .MIN_MEDIA_PORT_NUMBER_PROPERTY_NAME); - if (minPort != null) - { - maxPort - = cfg.getString( - OperationSetBasicTelephony - .MAX_MEDIA_PORT_NUMBER_PROPERTY_NAME); - if (maxPort != null) - { - //Try the specified range; otherwise, leave the tracker as it - //is: [5000, 6000]. - defaultPortTracker.tryRange(minPort, maxPort); - } - } - - //try the VIDEO tracker - minPort - = cfg.getString( - OperationSetBasicTelephony - .MIN_VIDEO_PORT_NUMBER_PROPERTY_NAME); - if (minPort != null) - { - maxPort - = cfg.getString( - OperationSetBasicTelephony - .MAX_VIDEO_PORT_NUMBER_PROPERTY_NAME); - if (maxPort != null) - { - //Try the specified range; otherwise, leave the tracker to null. - if (videoPortTracker == null) - { - videoPortTracker - = PortTracker.createTracker(minPort, maxPort); - } - else - { - videoPortTracker.tryRange(minPort, maxPort); - } - } - } - - //try the AUDIO tracker - minPort - = cfg.getString( - OperationSetBasicTelephony - .MIN_AUDIO_PORT_NUMBER_PROPERTY_NAME); - if (minPort != null) - { - maxPort - = cfg.getString( - OperationSetBasicTelephony - .MAX_AUDIO_PORT_NUMBER_PROPERTY_NAME); - if (maxPort != null) - { - //Try the specified range; otherwise, leave the tracker to null. - if (audioPortTracker == null) - { - audioPortTracker - = PortTracker.createTracker(minPort, maxPort); - } - else - { - audioPortTracker.tryRange(minPort, maxPort); - } - } - } - - //try the DATA CHANNEL tracker - minPort - = cfg.getString( - OperationSetBasicTelephony - .MIN_DATA_CHANNEL_PORT_NUMBER_PROPERTY_NAME); - if (minPort != null) - { - maxPort - = cfg.getString( - OperationSetBasicTelephony - .MAX_DATA_CHANNEL_PORT_NUMBER_PROPERTY_NAME); - if (maxPort != null) - { - //Try the specified range; otherwise, leave the tracker to null. - if (dataPortTracker == null) - { - dataPortTracker - = PortTracker.createTracker(minPort, maxPort); - } - else - { - dataPortTracker.tryRange(minPort, maxPort); - } - } - } - } - - /** - * Returns the InetAddress that we are using in one of our - * StreamConnectors or, in case we don't have any connectors yet - * the address returned by the our network address manager as the best local - * address to use when contacting the CallPeer associated with this - * MediaHandler. This method is primarily meant for use with the - * o= and c= fields of a newly created session description. The point is - * that we create our StreamConnectors when constructing the media - * descriptions so we already have a specific local address assigned to them - * at the time we get ready to create the c= and o= fields. It is therefore - * better to try and return one of these addresses before trying the net - * address manager again and running the slight risk of getting a different - * address. - * - * @return an InetAddress that we use in one of the - * StreamConnectors in this class. - */ - public InetAddress getLastUsedLocalHost() - { - for (MediaType mediaType : MediaType.values()) - { - StreamConnector streamConnector - = streamConnectors[mediaType.ordinal()]; - - if (streamConnector != null) - return streamConnector.getDataSocket().getLocalAddress(); - } - - NetworkAddressManagerService nam - = ProtocolMediaActivator.getNetworkAddressManagerService(); - InetAddress intendedDestination = getIntendedDestination(getCallPeer()); - - return nam.getLocalHost(intendedDestination); - } - - /** - * Sends empty UDP packets to target destination data/control ports in order - * to open ports on NATs or and help RTP proxies latch onto our RTP ports. - * - * @param target MediaStreamTarget - * @param type the {@link MediaType} of the connector we'd like to send the - * hole punching packet through. - */ - public void sendHolePunchPacket(MediaStreamTarget target, MediaType type) - { - logger.info("Send NAT hole punch packets"); - - //check how many hole punch packets we would be supposed to send: - int packetCount - = ProtocolMediaActivator.getConfigurationService().getInt( - HOLE_PUNCH_PKT_COUNT_PROPERTY, - DEFAULT_HOLE_PUNCH_PKT_COUNT); - - if (packetCount < 0) - packetCount = DEFAULT_HOLE_PUNCH_PKT_COUNT; - if (packetCount == 0) - return; - - try - { - StreamConnector connector = getStreamConnector(type); - - if(connector.getProtocol() == StreamConnector.Protocol.TCP) - return; - - byte[] buf = new byte[0]; - - synchronized(connector) - { - //we may want to send more than one packet in case they get lost - for(int i=0; i < packetCount; i++) - { - DatagramSocket socket; - - // data/RTP - if((socket = connector.getDataSocket()) != null) - { - InetSocketAddress dataAddress = target.getDataAddress(); - - socket.send( - new DatagramPacket( - buf, - buf.length, - dataAddress.getAddress(), - dataAddress.getPort())); - } - - // control/RTCP - if((socket = connector.getControlSocket()) != null) - { - InetSocketAddress controlAddress - = target.getControlAddress(); - - socket.send( - new DatagramPacket( - buf, - buf.length, - controlAddress.getAddress(), - controlAddress.getPort())); - } - } - } - } - catch(Exception e) - { - logger.error("Error cannot send to remote peer", e); - } - } - - /** - * Set traffic class (QoS) for the RTP socket. - * - * @param target MediaStreamTarget - * @param type the {@link MediaType} of the connector we'd like to set - * traffic class - */ - protected void setTrafficClass(MediaStreamTarget target, MediaType type) - { - // get traffic class value for RTP audio/video - int trafficClass = getDSCP(type); - - if(trafficClass <= 0) - return; - - if (logger.isInfoEnabled()) - logger.info( - "Set traffic class for " + type + " to " + trafficClass); - try - { - StreamConnector connector = getStreamConnector(type); - - synchronized(connector) - { - if(connector.getProtocol() == StreamConnector.Protocol.TCP) - { - connector.getDataTCPSocket().setTrafficClass(trafficClass); - - Socket controlTCPSocket = connector.getControlTCPSocket(); - - if (controlTCPSocket != null) - controlTCPSocket.setTrafficClass(trafficClass); - } - else - { - /* data port (RTP) */ - connector.getDataSocket().setTrafficClass(trafficClass); - - /* control port (RTCP) */ - DatagramSocket controlSocket = connector.getControlSocket(); - - if (controlSocket != null) - controlSocket.setTrafficClass(trafficClass); - } - } - } - catch(Exception e) - { - logger.error( - "Failed to set traffic class for " + type + " to " - + trafficClass, - e); - } - } - - /** - * Gets the SIP traffic class associated with a specific MediaType - * from the configuration. - * - * @param type the MediaType to get the associated SIP traffic - * class of - * @return the SIP traffic class associated with the specified - * MediaType or 0 if not configured - */ - private int getDSCP(MediaType type) - { - String dscpPropertyName; - - switch (type) - { - case AUDIO: - dscpPropertyName = RTP_AUDIO_DSCP_PROPERTY; - break; - case VIDEO: - dscpPropertyName = RTP_VIDEO_DSCP_PROPERTY; - break; - default: - dscpPropertyName = null; - break; - } - - return - (dscpPropertyName == null) - ? 0 - : (ProtocolMediaActivator.getConfigurationService().getInt( - dscpPropertyName, - 0) - << 2); - } - - /** - * Returns the InetAddress that is most likely to be used as a - * next hop when contacting the specified destination. This is - * an utility method that is used whenever we have to choose one of our - * local addresses to put in the Via, Contact or (in the case of no - * registrar accounts) From headers. - * - * @param peer the CallPeer that we would contact. - * - * @return the InetAddress that is most likely to be to be used - * as a next hop when contacting the specified destination. - * - * @throws IllegalArgumentException if destination is not a valid - * host/ip/fqdn - */ - protected abstract InetAddress getIntendedDestination(U peer); - - /** - * Returns the {@link MediaAwareCallPeer} that this transport manager is - * serving. - * - * @return the {@link MediaAwareCallPeer} that this transport manager is - * serving. - */ - public U getCallPeer() - { - return callPeer; - } - - /** - * Returns the port tracker that we are supposed to use when binding ports - * for the specified {@link MediaType}. - * - * @param mediaType the media type that we want to obtain the port tracker - * for. Use null to obtain the default port tracker. - * - * @return the port tracker that we are supposed to use when binding ports - * for the specified {@link MediaType}. - */ - protected static PortTracker getPortTracker(MediaType mediaType) - { - //make sure our port numbers reflect the configuration service settings - initializePortNumbers(); - - if (mediaType != null) - { - switch (mediaType) - { - case AUDIO: - if (audioPortTracker != null) - return audioPortTracker; - else - break; - case VIDEO: - if (videoPortTracker != null) - return videoPortTracker; - else - break; - case DATA: - if (dataPortTracker != null) - return dataPortTracker; - else - break; - } - } - - return defaultPortTracker; - } - - /** - * Returns the port tracker that we are supposed to use when binding ports - * for the {@link MediaType} indicated by the string param. If we do not - * recognize the string as a valid media type, we simply return the default - * port tracker. - * - * @param mediaTypeStr the name of the media type that we want to obtain a - * port tracker for. - * - * @return the port tracker that we are supposed to use when binding ports - * for the {@link MediaType} with the specified name or the default tracker - * in case the name doesn't ring a bell. - */ - protected static PortTracker getPortTracker(String mediaTypeStr) - { - try - { - return getPortTracker(MediaType.parseString(mediaTypeStr)); - } - catch (Exception e) - { - logger.info( - "Returning default port tracker for unrecognized media type: " - + mediaTypeStr); - - return defaultPortTracker; - } - } - - /** - * Returns the extended type of the candidate selected if this transport - * manager is using ICE. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return The extended type of the candidate selected if this transport - * manager is using ICE. Otherwise, returns null. - */ - public abstract String getICECandidateExtendedType(String streamName); - - /** - * Returns the current state of ICE processing. - * - * @return the current state of ICE processing if this transport - * manager is using ICE. Otherwise, returns null. - */ - public abstract String getICEState(); - - /** - * Returns the ICE local host address. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local host address if this transport - * manager is using ICE. Otherwise, returns null. - */ - public abstract InetSocketAddress getICELocalHostAddress(String streamName); - - /** - * Returns the ICE remote host address. - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote host address if this transport - * manager is using ICE. Otherwise, returns null. - */ - public abstract InetSocketAddress getICERemoteHostAddress( - String streamName); - - /** - * Returns the ICE local reflexive address (server or peer reflexive). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local reflexive address. May be null if this transport - * manager is not using ICE or if there is no reflexive address for the - * local candidate used. - */ - public abstract InetSocketAddress getICELocalReflexiveAddress( - String streamName); - - /** - * Returns the ICE remote reflexive address (server or peer reflexive). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote reflexive address. May be null if this transport - * manager is not using ICE or if there is no reflexive address for the - * remote candidate used. - */ - public abstract InetSocketAddress getICERemoteReflexiveAddress( - String streamName); - - /** - * Returns the ICE local relayed address (server or peer relayed). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE local relayed address. May be null if this transport - * manager is not using ICE or if there is no relayed address for the - * local candidate used. - */ - public abstract InetSocketAddress getICELocalRelayedAddress( - String streamName); - - /** - * Returns the ICE remote relayed address (server or peer relayed). - * - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return the ICE remote relayed address. May be null if this transport - * manager is not using ICE or if there is no relayed address for the - * remote candidate used. - */ - public abstract InetSocketAddress getICERemoteRelayedAddress( - String streamName); - - /** - * Returns the total harvesting time (in ms) for all harvesters. - * - * @return The total harvesting time (in ms) for all the harvesters. 0 if - * the ICE agent is null, or if the agent has nevers harvested. - */ - public abstract long getTotalHarvestingTime(); - - /** - * Returns the harvesting time (in ms) for the harvester given in parameter. - * - * @param harvesterName The class name if the harvester. - * - * @return The harvesting time (in ms) for the harvester given in parameter. - * 0 if this harvester does not exists, if the ICE agent is null, or if the - * agent has never harvested with this harvester. - */ - public abstract long getHarvestingTime(String harvesterName); - - /** - * Returns the number of harvesting for this agent. - * - * @return The number of harvesting for this agent. - */ - public abstract int getNbHarvesting(); - - /** - * Returns the number of harvesting time for the harvester given in - * parameter. - * - * @param harvesterName The class name if the harvester. - * - * @return The number of harvesting time for the harvester given in - * parameter. - */ - public abstract int getNbHarvesting(String harvesterName); - - /** - * Returns the ICE candidate extended type selected by the given agent. - * - * @param iceAgent The ICE agent managing the ICE offer/answer exchange, - * collecting and selecting the candidate. - * @param streamName The stream name (AUDIO, VIDEO); - * - * @return The ICE candidate extended type selected by the given agent. null - * if the iceAgent is null or if there is no candidate selected or - * available. - */ - public static String getICECandidateExtendedType( - Agent iceAgent, - String streamName) - { - if(iceAgent != null) - { - LocalCandidate localCandidate - = iceAgent.getSelectedLocalCandidate(streamName); - - if(localCandidate != null) - return localCandidate.getExtendedType().toString(); - } - return null; - } - - - /** - * Creates the ICE agent that we would be using in this transport manager - * for all negotiation. - * - * @return the ICE agent to use for all the ICE negotiation that this - * transport manager would be going through - */ - protected Agent createIceAgent() - { - //work in progress - return null; - } - - /** - * Creates an {@link IceMediaStream} with the specified media - * name. - * - * @param media the name of the stream we'd like to create. - * @param agent the ICE {@link Agent} that we will be appending the stream - * to. - * - * @return the newly created {@link IceMediaStream} - * - * @throws OperationFailedException if binding on the specified media stream - * fails for some reason. - */ - protected IceMediaStream createIceStream(String media, Agent agent) - throws OperationFailedException - { - return null; - } -} +package net.java.sip.communicator.service.protocol.media; + +import java.net.*; + +import net.java.sip.communicator.service.netaddr.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.ice4j.ice.*; +import org.jitsi.service.configuration.*; +import org.jitsi.service.neomedia.*; + +/** + * TransportManagers are responsible for allocating ports, gathering + * local candidates and managing ICE whenever we are using it. + * + * @param the peer extension class like for example CallPeerSipImpl + * or CallPeerJabberImpl + * + * @author Emil Ivov + * @author Lyubomir Marinov + * @author Sebastien Vincent + */ +public abstract class TransportManager> +{ + /** + * The Logger used by the TransportManager + * class and its instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(TransportManager.class); + + /** + * The port tracker that we should use when binding generic media streams. + *

    + * Initialized by {@link #initializePortNumbers()}. + *

    + */ + private static final PortTracker defaultPortTracker + = new PortTracker(5000, 6000); + + /** + * The port tracker that we should use when binding video media streams. + *

    + * Potentially initialized by {@link #initializePortNumbers()} if the + * necessary properties are set. + *

    + */ + private static PortTracker videoPortTracker; + + /** + * The port tracker that we should use when binding data channels. + *

    + * Potentially initialized by {@link #initializePortNumbers()} if the + * necessary properties are set. + *

    + */ + private static PortTracker dataPortTracker; + + /** + * The port tracker that we should use when binding data media streams. + *

    + * Potentially initialized by {@link #initializePortNumbers()} if the + * necessary properties are set. + *

    + */ + private static PortTracker audioPortTracker; + + /** + * RTP audio DSCP configuration property name. + */ + private static final String RTP_AUDIO_DSCP_PROPERTY = + "net.java.sip.communicator.impl.protocol.RTP_AUDIO_DSCP"; + + /** + * RTP video DSCP configuration property name. + */ + private static final String RTP_VIDEO_DSCP_PROPERTY = + "net.java.sip.communicator.impl.protocol.RTP_VIDEO_DSCP"; + + /** + * Number of empty UDP packets to send for NAT hole punching. + */ + private static final String HOLE_PUNCH_PKT_COUNT_PROPERTY = + "net.java.sip.communicator.impl.protocol.HOLE_PUNCH_PKT_COUNT"; + + /** + * Number of empty UDP packets to send for NAT hole punching. + */ + private static final int DEFAULT_HOLE_PUNCH_PKT_COUNT = 3; + + /** + * The {@link MediaAwareCallPeer} whose traffic we will be taking care of. + */ + private U callPeer; + + /** + * The RTP/RTCP socket couples that this TransportManager uses to + * send and receive media flows through indexed by MediaType + * (ordinal). + */ + private final StreamConnector[] streamConnectors + = new StreamConnector[MediaType.values().length]; + + /** + * Creates a new instance of this transport manager, binding it to the + * specified peer. + * + * @param callPeer the {@link MediaAwareCallPeer} whose traffic we will be + * taking care of. + */ + protected TransportManager(U callPeer) + { + this.callPeer = callPeer; + } + + /** + * Returns the StreamConnector instance that this media handler + * should use for streams of the specified mediaType. The method + * would also create a new StreamConnector if no connector has + * been initialized for this mediaType yet or in case one + * of its underlying sockets has been closed. + * + * @param mediaType the MediaType that we'd like to create a + * connector for. + * @return this media handler's StreamConnector for the specified + * mediaType. + * + * @throws OperationFailedException in case we failed to initialize our + * connector. + */ + public StreamConnector getStreamConnector(MediaType mediaType) + throws OperationFailedException + { + int streamConnectorIndex = mediaType.ordinal(); + StreamConnector streamConnector + = streamConnectors[streamConnectorIndex]; + + if((streamConnector == null) + || (streamConnector.getProtocol() == StreamConnector.Protocol.UDP)) + { + DatagramSocket controlSocket; + + if((streamConnector == null) + || streamConnector.getDataSocket().isClosed() + || (((controlSocket = streamConnector.getControlSocket()) + != null) + && controlSocket.isClosed())) + { + streamConnectors[streamConnectorIndex] + = streamConnector + = createStreamConnector(mediaType); + } + } + else if(streamConnector.getProtocol() == StreamConnector.Protocol.TCP) + { + Socket controlTCPSocket; + + if(streamConnector.getDataTCPSocket().isClosed() + || (((controlTCPSocket = streamConnector.getControlTCPSocket()) + != null) + && controlTCPSocket.isClosed())) + { + streamConnectors[streamConnectorIndex] + = streamConnector + = createStreamConnector(mediaType); + } + } + return streamConnector; + } + + /** + * Closes the existing StreamConnector, if any, associated with a + * specific MediaType and removes its reference from this + * TransportManager. + * + * @param mediaType the MediaType associated with the + * StreamConnector to close + */ + public void closeStreamConnector(MediaType mediaType) + { + int index = mediaType.ordinal(); + StreamConnector streamConnector = streamConnectors[index]; + + if (streamConnector != null) + { + closeStreamConnector(mediaType, streamConnector); + streamConnectors[index] = null; + } + } + + /** + * Closes a specific StreamConnector associated with a specific + * MediaType. If this TransportManager has a reference to + * the specified streamConnector, it remains. Allows extenders to + * override and perform additional customizations to the closing of the + * specified streamConnector. + * + * @param mediaType the MediaType associated with the specified + * streamConnector + * @param streamConnector the StreamConnector to be closed + * @see #closeStreamConnector(MediaType) + */ + protected void closeStreamConnector( + MediaType mediaType, + StreamConnector streamConnector) + { + /* + * XXX The connected owns the sockets so it is important that it + * decides whether to close them i.e. this TransportManager is not + * allowed to explicitly close the sockets by itself. + */ + streamConnector.close(); + } + + /** + * Creates a media StreamConnector for a stream of a specific + * MediaType. The minimum and maximum of the media port boundaries + * are taken into account. + * + * @param mediaType the MediaType of the stream for which a + * StreamConnector is to be created + * @return a StreamConnector for the stream of the specified + * mediaType + * @throws OperationFailedException if the binding of the sockets fails + */ + protected StreamConnector createStreamConnector(MediaType mediaType) + throws OperationFailedException + { + NetworkAddressManagerService nam + = ProtocolMediaActivator.getNetworkAddressManagerService(); + InetAddress intendedDestination = getIntendedDestination(getCallPeer()); + InetAddress localHostForPeer = nam.getLocalHost(intendedDestination); + + PortTracker portTracker = getPortTracker(mediaType); + + //create the RTP socket. + DatagramSocket rtpSocket = null; + try + { + rtpSocket = nam.createDatagramSocket( + localHostForPeer, portTracker.getPort(), + portTracker.getMinPort(), portTracker.getMaxPort()); + } + catch (Exception exc) + { + throw new OperationFailedException( + "Failed to allocate the network ports necessary for the call.", + OperationFailedException.INTERNAL_ERROR, exc); + } + + //make sure that next time we don't try to bind on occupied ports + //also, refuse validation in case someone set the tracker range to 1 + portTracker.setNextPort( rtpSocket.getLocalPort() + 1, false); + + //create the RTCP socket, preferably on the port following our RTP one. + DatagramSocket rtcpSocket = null; + try + { + rtcpSocket = nam.createDatagramSocket( + localHostForPeer, portTracker.getPort(), + portTracker.getMinPort(), portTracker.getMaxPort()); + } + catch (Exception exc) + { + throw new OperationFailedException( + "Failed to allocate the network ports necessary for the call.", + OperationFailedException.INTERNAL_ERROR, + exc); + } + + //make sure that next time we don't try to bind on occupied ports + portTracker.setNextPort( rtcpSocket.getLocalPort() + 1); + + return new DefaultStreamConnector(rtpSocket, rtcpSocket); + } + + /** + * Tries to set the ranges of the PortTrackers (e.g. default, + * audio, video, data channel) to the values specified in the + * ConfigurationService. + */ + protected synchronized static void initializePortNumbers() + { + //try the default tracker first + ConfigurationService cfg + = ProtocolMediaActivator.getConfigurationService(); + String minPort, maxPort; + + minPort + = cfg.getString( + OperationSetBasicTelephony + .MIN_MEDIA_PORT_NUMBER_PROPERTY_NAME); + if (minPort != null) + { + maxPort + = cfg.getString( + OperationSetBasicTelephony + .MAX_MEDIA_PORT_NUMBER_PROPERTY_NAME); + if (maxPort != null) + { + //Try the specified range; otherwise, leave the tracker as it + //is: [5000, 6000]. + defaultPortTracker.tryRange(minPort, maxPort); + } + } + + //try the VIDEO tracker + minPort + = cfg.getString( + OperationSetBasicTelephony + .MIN_VIDEO_PORT_NUMBER_PROPERTY_NAME); + if (minPort != null) + { + maxPort + = cfg.getString( + OperationSetBasicTelephony + .MAX_VIDEO_PORT_NUMBER_PROPERTY_NAME); + if (maxPort != null) + { + //Try the specified range; otherwise, leave the tracker to null. + if (videoPortTracker == null) + { + videoPortTracker + = PortTracker.createTracker(minPort, maxPort); + } + else + { + videoPortTracker.tryRange(minPort, maxPort); + } + } + } + + //try the AUDIO tracker + minPort + = cfg.getString( + OperationSetBasicTelephony + .MIN_AUDIO_PORT_NUMBER_PROPERTY_NAME); + if (minPort != null) + { + maxPort + = cfg.getString( + OperationSetBasicTelephony + .MAX_AUDIO_PORT_NUMBER_PROPERTY_NAME); + if (maxPort != null) + { + //Try the specified range; otherwise, leave the tracker to null. + if (audioPortTracker == null) + { + audioPortTracker + = PortTracker.createTracker(minPort, maxPort); + } + else + { + audioPortTracker.tryRange(minPort, maxPort); + } + } + } + + //try the DATA CHANNEL tracker + minPort + = cfg.getString( + OperationSetBasicTelephony + .MIN_DATA_CHANNEL_PORT_NUMBER_PROPERTY_NAME); + if (minPort != null) + { + maxPort + = cfg.getString( + OperationSetBasicTelephony + .MAX_DATA_CHANNEL_PORT_NUMBER_PROPERTY_NAME); + if (maxPort != null) + { + //Try the specified range; otherwise, leave the tracker to null. + if (dataPortTracker == null) + { + dataPortTracker + = PortTracker.createTracker(minPort, maxPort); + } + else + { + dataPortTracker.tryRange(minPort, maxPort); + } + } + } + } + + /** + * Returns the InetAddress that we are using in one of our + * StreamConnectors or, in case we don't have any connectors yet + * the address returned by the our network address manager as the best local + * address to use when contacting the CallPeer associated with this + * MediaHandler. This method is primarily meant for use with the + * o= and c= fields of a newly created session description. The point is + * that we create our StreamConnectors when constructing the media + * descriptions so we already have a specific local address assigned to them + * at the time we get ready to create the c= and o= fields. It is therefore + * better to try and return one of these addresses before trying the net + * address manager again and running the slight risk of getting a different + * address. + * + * @return an InetAddress that we use in one of the + * StreamConnectors in this class. + */ + public InetAddress getLastUsedLocalHost() + { + for (MediaType mediaType : MediaType.values()) + { + StreamConnector streamConnector + = streamConnectors[mediaType.ordinal()]; + + if (streamConnector != null) + return streamConnector.getDataSocket().getLocalAddress(); + } + + NetworkAddressManagerService nam + = ProtocolMediaActivator.getNetworkAddressManagerService(); + InetAddress intendedDestination = getIntendedDestination(getCallPeer()); + + return nam.getLocalHost(intendedDestination); + } + + /** + * Sends empty UDP packets to target destination data/control ports in order + * to open ports on NATs or and help RTP proxies latch onto our RTP ports. + * + * @param target MediaStreamTarget + * @param type the {@link MediaType} of the connector we'd like to send the + * hole punching packet through. + */ + public void sendHolePunchPacket(MediaStreamTarget target, MediaType type) + { + logger.info("Send NAT hole punch packets"); + + //check how many hole punch packets we would be supposed to send: + int packetCount + = ProtocolMediaActivator.getConfigurationService().getInt( + HOLE_PUNCH_PKT_COUNT_PROPERTY, + DEFAULT_HOLE_PUNCH_PKT_COUNT); + + if (packetCount < 0) + packetCount = DEFAULT_HOLE_PUNCH_PKT_COUNT; + if (packetCount == 0) + return; + + try + { + StreamConnector connector = getStreamConnector(type); + + if(connector.getProtocol() == StreamConnector.Protocol.TCP) + return; + + byte[] buf = new byte[0]; + + synchronized(connector) + { + //we may want to send more than one packet in case they get lost + for(int i=0; i < packetCount; i++) + { + DatagramSocket socket; + + // data/RTP + if((socket = connector.getDataSocket()) != null) + { + InetSocketAddress dataAddress = target.getDataAddress(); + + socket.send( + new DatagramPacket( + buf, + buf.length, + dataAddress.getAddress(), + dataAddress.getPort())); + } + + // control/RTCP + if((socket = connector.getControlSocket()) != null) + { + InetSocketAddress controlAddress + = target.getControlAddress(); + + socket.send( + new DatagramPacket( + buf, + buf.length, + controlAddress.getAddress(), + controlAddress.getPort())); + } + } + } + } + catch(Exception e) + { + logger.error("Error cannot send to remote peer", e); + } + } + + /** + * Set traffic class (QoS) for the RTP socket. + * + * @param target MediaStreamTarget + * @param type the {@link MediaType} of the connector we'd like to set + * traffic class + */ + protected void setTrafficClass(MediaStreamTarget target, MediaType type) + { + // get traffic class value for RTP audio/video + int trafficClass = getDSCP(type); + + if(trafficClass <= 0) + return; + + if (logger.isInfoEnabled()) + logger.info( + "Set traffic class for " + type + " to " + trafficClass); + try + { + StreamConnector connector = getStreamConnector(type); + + synchronized(connector) + { + if(connector.getProtocol() == StreamConnector.Protocol.TCP) + { + connector.getDataTCPSocket().setTrafficClass(trafficClass); + + Socket controlTCPSocket = connector.getControlTCPSocket(); + + if (controlTCPSocket != null) + controlTCPSocket.setTrafficClass(trafficClass); + } + else + { + /* data port (RTP) */ + connector.getDataSocket().setTrafficClass(trafficClass); + + /* control port (RTCP) */ + DatagramSocket controlSocket = connector.getControlSocket(); + + if (controlSocket != null) + controlSocket.setTrafficClass(trafficClass); + } + } + } + catch(Exception e) + { + logger.error( + "Failed to set traffic class for " + type + " to " + + trafficClass, + e); + } + } + + /** + * Gets the SIP traffic class associated with a specific MediaType + * from the configuration. + * + * @param type the MediaType to get the associated SIP traffic + * class of + * @return the SIP traffic class associated with the specified + * MediaType or 0 if not configured + */ + private int getDSCP(MediaType type) + { + String dscpPropertyName; + + switch (type) + { + case AUDIO: + dscpPropertyName = RTP_AUDIO_DSCP_PROPERTY; + break; + case VIDEO: + dscpPropertyName = RTP_VIDEO_DSCP_PROPERTY; + break; + default: + dscpPropertyName = null; + break; + } + + return + (dscpPropertyName == null) + ? 0 + : (ProtocolMediaActivator.getConfigurationService().getInt( + dscpPropertyName, + 0) + << 2); + } + + /** + * Returns the InetAddress that is most likely to be used as a + * next hop when contacting the specified destination. This is + * an utility method that is used whenever we have to choose one of our + * local addresses to put in the Via, Contact or (in the case of no + * registrar accounts) From headers. + * + * @param peer the CallPeer that we would contact. + * + * @return the InetAddress that is most likely to be to be used + * as a next hop when contacting the specified destination. + * + * @throws IllegalArgumentException if destination is not a valid + * host/ip/fqdn + */ + protected abstract InetAddress getIntendedDestination(U peer); + + /** + * Returns the {@link MediaAwareCallPeer} that this transport manager is + * serving. + * + * @return the {@link MediaAwareCallPeer} that this transport manager is + * serving. + */ + public U getCallPeer() + { + return callPeer; + } + + /** + * Returns the port tracker that we are supposed to use when binding ports + * for the specified {@link MediaType}. + * + * @param mediaType the media type that we want to obtain the port tracker + * for. Use null to obtain the default port tracker. + * + * @return the port tracker that we are supposed to use when binding ports + * for the specified {@link MediaType}. + */ + protected static PortTracker getPortTracker(MediaType mediaType) + { + //make sure our port numbers reflect the configuration service settings + initializePortNumbers(); + + if (mediaType != null) + { + switch (mediaType) + { + case AUDIO: + if (audioPortTracker != null) + return audioPortTracker; + else + break; + case VIDEO: + if (videoPortTracker != null) + return videoPortTracker; + else + break; + case DATA: + if (dataPortTracker != null) + return dataPortTracker; + else + break; + } + } + + return defaultPortTracker; + } + + /** + * Returns the port tracker that we are supposed to use when binding ports + * for the {@link MediaType} indicated by the string param. If we do not + * recognize the string as a valid media type, we simply return the default + * port tracker. + * + * @param mediaTypeStr the name of the media type that we want to obtain a + * port tracker for. + * + * @return the port tracker that we are supposed to use when binding ports + * for the {@link MediaType} with the specified name or the default tracker + * in case the name doesn't ring a bell. + */ + protected static PortTracker getPortTracker(String mediaTypeStr) + { + try + { + return getPortTracker(MediaType.parseString(mediaTypeStr)); + } + catch (Exception e) + { + logger.info( + "Returning default port tracker for unrecognized media type: " + + mediaTypeStr); + + return defaultPortTracker; + } + } + + /** + * Returns the extended type of the candidate selected if this transport + * manager is using ICE. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return The extended type of the candidate selected if this transport + * manager is using ICE. Otherwise, returns null. + */ + public abstract String getICECandidateExtendedType(String streamName); + + /** + * Returns the current state of ICE processing. + * + * @return the current state of ICE processing if this transport + * manager is using ICE. Otherwise, returns null. + */ + public abstract String getICEState(); + + /** + * Returns the ICE local host address. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local host address if this transport + * manager is using ICE. Otherwise, returns null. + */ + public abstract InetSocketAddress getICELocalHostAddress(String streamName); + + /** + * Returns the ICE remote host address. + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote host address if this transport + * manager is using ICE. Otherwise, returns null. + */ + public abstract InetSocketAddress getICERemoteHostAddress( + String streamName); + + /** + * Returns the ICE local reflexive address (server or peer reflexive). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local reflexive address. May be null if this transport + * manager is not using ICE or if there is no reflexive address for the + * local candidate used. + */ + public abstract InetSocketAddress getICELocalReflexiveAddress( + String streamName); + + /** + * Returns the ICE remote reflexive address (server or peer reflexive). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote reflexive address. May be null if this transport + * manager is not using ICE or if there is no reflexive address for the + * remote candidate used. + */ + public abstract InetSocketAddress getICERemoteReflexiveAddress( + String streamName); + + /** + * Returns the ICE local relayed address (server or peer relayed). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE local relayed address. May be null if this transport + * manager is not using ICE or if there is no relayed address for the + * local candidate used. + */ + public abstract InetSocketAddress getICELocalRelayedAddress( + String streamName); + + /** + * Returns the ICE remote relayed address (server or peer relayed). + * + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return the ICE remote relayed address. May be null if this transport + * manager is not using ICE or if there is no relayed address for the + * remote candidate used. + */ + public abstract InetSocketAddress getICERemoteRelayedAddress( + String streamName); + + /** + * Returns the total harvesting time (in ms) for all harvesters. + * + * @return The total harvesting time (in ms) for all the harvesters. 0 if + * the ICE agent is null, or if the agent has nevers harvested. + */ + public abstract long getTotalHarvestingTime(); + + /** + * Returns the harvesting time (in ms) for the harvester given in parameter. + * + * @param harvesterName The class name if the harvester. + * + * @return The harvesting time (in ms) for the harvester given in parameter. + * 0 if this harvester does not exists, if the ICE agent is null, or if the + * agent has never harvested with this harvester. + */ + public abstract long getHarvestingTime(String harvesterName); + + /** + * Returns the number of harvesting for this agent. + * + * @return The number of harvesting for this agent. + */ + public abstract int getNbHarvesting(); + + /** + * Returns the number of harvesting time for the harvester given in + * parameter. + * + * @param harvesterName The class name if the harvester. + * + * @return The number of harvesting time for the harvester given in + * parameter. + */ + public abstract int getNbHarvesting(String harvesterName); + + /** + * Returns the ICE candidate extended type selected by the given agent. + * + * @param iceAgent The ICE agent managing the ICE offer/answer exchange, + * collecting and selecting the candidate. + * @param streamName The stream name (AUDIO, VIDEO); + * + * @return The ICE candidate extended type selected by the given agent. null + * if the iceAgent is null or if there is no candidate selected or + * available. + */ + public static String getICECandidateExtendedType( + Agent iceAgent, + String streamName) + { + if(iceAgent != null) + { + LocalCandidate localCandidate + = iceAgent.getSelectedLocalCandidate(streamName); + + if(localCandidate != null) + return localCandidate.getExtendedType().toString(); + } + return null; + } + + + /** + * Creates the ICE agent that we would be using in this transport manager + * for all negotiation. + * + * @return the ICE agent to use for all the ICE negotiation that this + * transport manager would be going through + */ + protected Agent createIceAgent() + { + //work in progress + return null; + } + + /** + * Creates an {@link IceMediaStream} with the specified media + * name. + * + * @param media the name of the stream we'd like to create. + * @param agent the ICE {@link Agent} that we will be appending the stream + * to. + * + * @return the newly created {@link IceMediaStream} + * + * @throws OperationFailedException if binding on the specified media stream + * fails for some reason. + */ + protected IceMediaStream createIceStream(String media, Agent agent) + throws OperationFailedException + { + return null; + } +} diff --git a/src/net/java/sip/communicator/service/resources/ImageID.java b/src/net/java/sip/communicator/service/resources/ImageID.java index cc90191..785ca96 100644 --- a/src/net/java/sip/communicator/service/resources/ImageID.java +++ b/src/net/java/sip/communicator/service/resources/ImageID.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,22 +15,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.resources; - -/** - * Represents the Image Identifier. - */ -public class ImageID -{ - private final String id; - - public ImageID(String id) - { - this.id = id; - } - - public String getId() - { - return id; - } -} +package net.java.sip.communicator.service.resources; + +/** + * Represents the Image Identifier. + */ +public class ImageID +{ + private final String id; + + public ImageID(String id) + { + this.id = id; + } + + public String getId() + { + return id; + } +} diff --git a/src/net/java/sip/communicator/service/resources/ResourceManagementServiceUtils.java b/src/net/java/sip/communicator/service/resources/ResourceManagementServiceUtils.java index d8570c7..c5d10ac 100644 --- a/src/net/java/sip/communicator/service/resources/ResourceManagementServiceUtils.java +++ b/src/net/java/sip/communicator/service/resources/ResourceManagementServiceUtils.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,74 +15,74 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.resources; - -import java.util.*; - -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * @author Lubomir Marinov - */ -public final class ResourceManagementServiceUtils -{ - - /** - * Constructs a new Locale instance from a specific locale - * identifier which can either be a two-letter language code or contain a - * two-letter language code and a two-letter country code in the form - * <language>_<country>. - * - * @param localeId the locale identifier describing the new Locale - * instance to be created - * @return a new Locale instance with language and country (if - * specified) matching the given locale identifier - */ - public static Locale getLocale(String localeId) - { - int underscoreIndex = localeId.indexOf('_'); - String language; - String country; - - if (underscoreIndex == -1) - { - language = localeId; - country = ""; - } - else - { - language = localeId.substring(0, underscoreIndex); - country = localeId.substring(underscoreIndex + 1); - } - return new Locale(language, country); - } - - /** - * Gets the ResourceManagementService instance registered in a - * specific BundleContext (if any). - * - * @param bundleContext the BundleContext to be checked for a - * registered ResourceManagementService - * @return a ResourceManagementService instance registered in - * the specified BundleContext if any; otherwise, null - */ - public static ResourceManagementService getService( - BundleContext bundleContext) - { - return - ServiceUtils.getService( - bundleContext, - ResourceManagementService.class); - } - - /** - * Prevents the creation of ResourceManagementServiceUtils - * instances. - */ - private ResourceManagementServiceUtils() - { - } -} +package net.java.sip.communicator.service.resources; + +import java.util.*; + +import net.java.sip.communicator.util.*; + +import org.jitsi.service.resources.*; +import org.osgi.framework.*; + +/** + * @author Lubomir Marinov + */ +public final class ResourceManagementServiceUtils +{ + + /** + * Constructs a new Locale instance from a specific locale + * identifier which can either be a two-letter language code or contain a + * two-letter language code and a two-letter country code in the form + * <language>_<country>. + * + * @param localeId the locale identifier describing the new Locale + * instance to be created + * @return a new Locale instance with language and country (if + * specified) matching the given locale identifier + */ + public static Locale getLocale(String localeId) + { + int underscoreIndex = localeId.indexOf('_'); + String language; + String country; + + if (underscoreIndex == -1) + { + language = localeId; + country = ""; + } + else + { + language = localeId.substring(0, underscoreIndex); + country = localeId.substring(underscoreIndex + 1); + } + return new Locale(language, country); + } + + /** + * Gets the ResourceManagementService instance registered in a + * specific BundleContext (if any). + * + * @param bundleContext the BundleContext to be checked for a + * registered ResourceManagementService + * @return a ResourceManagementService instance registered in + * the specified BundleContext if any; otherwise, null + */ + public static ResourceManagementService getService( + BundleContext bundleContext) + { + return + ServiceUtils.getService( + bundleContext, + ResourceManagementService.class); + } + + /** + * Prevents the creation of ResourceManagementServiceUtils + * instances. + */ + private ResourceManagementServiceUtils() + { + } +} diff --git a/src/net/java/sip/communicator/service/sysactivity/SystemActivityChangeListener.java b/src/net/java/sip/communicator/service/sysactivity/SystemActivityChangeListener.java index e94c49d..98aecdd 100644 --- a/src/net/java/sip/communicator/service/sysactivity/SystemActivityChangeListener.java +++ b/src/net/java/sip/communicator/service/sysactivity/SystemActivityChangeListener.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,28 +15,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.sysactivity; - -import java.util.*; - -import net.java.sip.communicator.service.sysactivity.event.*; - -/** - * The SystemActivityChangeListener is notified any time an event - * in the operating system occurs. - * - * @author Damian Minkov - */ -public interface SystemActivityChangeListener - extends EventListener -{ - /** - * This method gets called when a notification action for a particular event - * type has been changed (for example the corresponding descriptor has - * changed). - * - * @param event the NotificationActionTypeEvent, which is - * dispatched when an action has been changed. - */ - public void activityChanged(SystemActivityEvent event); -} +package net.java.sip.communicator.service.sysactivity; + +import java.util.*; + +import net.java.sip.communicator.service.sysactivity.event.*; + +/** + * The SystemActivityChangeListener is notified any time an event + * in the operating system occurs. + * + * @author Damian Minkov + */ +public interface SystemActivityChangeListener + extends EventListener +{ + /** + * This method gets called when a notification action for a particular event + * type has been changed (for example the corresponding descriptor has + * changed). + * + * @param event the NotificationActionTypeEvent, which is + * dispatched when an action has been changed. + */ + public void activityChanged(SystemActivityEvent event); +} diff --git a/src/net/java/sip/communicator/service/sysactivity/SystemActivityNotificationsService.java b/src/net/java/sip/communicator/service/sysactivity/SystemActivityNotificationsService.java index f7de167..c7069b0 100644 --- a/src/net/java/sip/communicator/service/sysactivity/SystemActivityNotificationsService.java +++ b/src/net/java/sip/communicator/service/sysactivity/SystemActivityNotificationsService.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,71 +15,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.sysactivity; - -/** - * Listens for some system specific events such as sleep, wake, network change, - * desktop activity, screensaver etc. and informs the registered listeners. - * - * @author Damian Minkov - */ -public interface SystemActivityNotificationsService -{ - /** - * Registers a listener that would be notified of changes that have occurred - * in the underlying system. - * - * @param listener the listener that we'd like to register for changes in - * the underlying system. - */ - public void addSystemActivityChangeListener( - SystemActivityChangeListener listener); - - /** - * Remove the specified listener so that it won't receive further - * notifications of changes that occur in the underlying system - * - * @param listener the listener to remove. - */ - public void removeSystemActivityChangeListener( - SystemActivityChangeListener listener); - - /** - * Registers a listener that would be notified for idle of the system - * for idleTime. - * - * @param idleTime the time in milliseconds after which we will consider - * system to be idle. This doesn't count when system seems idle as - * monitor is off or screensaver is on, or desktop is locked. - * @param listener the listener that we'd like to register for changes in - * the underlying system. - */ - public void addIdleSystemChangeListener( - long idleTime, - SystemActivityChangeListener listener); - - /** - * Remove the specified listener so that it won't receive further - * notifications for idle system. - * - * @param listener the listener to remove. - */ - public void removeIdleSystemChangeListener( - SystemActivityChangeListener listener); - - /** - * Can check whether an event id is supported on - * current operation system. - * @param eventID the event to check. - * @return whether the supplied event id is supported. - */ - public boolean isSupported(int eventID); - - /** - * The time since last user input. The time the system has been idle. - * Or -1 if there is no such information or error has occured. - * @return time the system has been idle. - */ - public long getTimeSinceLastInput(); - -} +package net.java.sip.communicator.service.sysactivity; + +/** + * Listens for some system specific events such as sleep, wake, network change, + * desktop activity, screensaver etc. and informs the registered listeners. + * + * @author Damian Minkov + */ +public interface SystemActivityNotificationsService +{ + /** + * Registers a listener that would be notified of changes that have occurred + * in the underlying system. + * + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addSystemActivityChangeListener( + SystemActivityChangeListener listener); + + /** + * Remove the specified listener so that it won't receive further + * notifications of changes that occur in the underlying system + * + * @param listener the listener to remove. + */ + public void removeSystemActivityChangeListener( + SystemActivityChangeListener listener); + + /** + * Registers a listener that would be notified for idle of the system + * for idleTime. + * + * @param idleTime the time in milliseconds after which we will consider + * system to be idle. This doesn't count when system seems idle as + * monitor is off or screensaver is on, or desktop is locked. + * @param listener the listener that we'd like to register for changes in + * the underlying system. + */ + public void addIdleSystemChangeListener( + long idleTime, + SystemActivityChangeListener listener); + + /** + * Remove the specified listener so that it won't receive further + * notifications for idle system. + * + * @param listener the listener to remove. + */ + public void removeIdleSystemChangeListener( + SystemActivityChangeListener listener); + + /** + * Can check whether an event id is supported on + * current operation system. + * @param eventID the event to check. + * @return whether the supplied event id is supported. + */ + public boolean isSupported(int eventID); + + /** + * The time since last user input. The time the system has been idle. + * Or -1 if there is no such information or error has occured. + * @return time the system has been idle. + */ + public long getTimeSinceLastInput(); + +} diff --git a/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java b/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java index fa5df51..47183d7 100644 --- a/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java +++ b/src/net/java/sip/communicator/service/sysactivity/event/SystemActivityEvent.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,136 +15,136 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.service.sysactivity.event; - -import java.util.*; - -/** - * An event class representing system activity that has occurred. - * The event id indicates the exact reason for this event. - * @author Damian Minkov - */ -public class SystemActivityEvent - extends EventObject -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Notify that computers is going to sleep. - */ - public static final int EVENT_SLEEP = 0; - - /** - * Notify that computer is wakeing up after stand by. - */ - public static final int EVENT_WAKE = 1; - - /** - * Computer display has stand by. - */ - public static final int EVENT_DISPLAY_SLEEP = 2; - - /** - * Computer display wakes up after stand by. - */ - public static final int EVENT_DISPLAY_WAKE = 3; - - /** - * Screensaver has been started. - */ - public static final int EVENT_SCREENSAVER_START = 4; - - /** - * Screensaver will stop. - */ - public static final int EVENT_SCREENSAVER_WILL_STOP = 5; - - /** - * Screensaver has been stopped. - */ - public static final int EVENT_SCREENSAVER_STOP = 6; - - /** - * Screen has been locked. - */ - public static final int EVENT_SCREEN_LOCKED = 7; - - /** - * Screen has been unlocked. - */ - public static final int EVENT_SCREEN_UNLOCKED = 8; - - /** - * A change in network configuration has occurred. - */ - public static final int EVENT_NETWORK_CHANGE = 9; - - /** - * A system idle event has occurred. - */ - public static final int EVENT_SYSTEM_IDLE = 10; - - /** - * A system was in idle state and now exits. - */ - public static final int EVENT_SYSTEM_IDLE_END = 11; - - /** - * A change in dns configuration has occurred. - */ - public static final int EVENT_DNS_CHANGE = 12; - - /** - * Informing that the machine is logging of or shutting down. - */ - public static final int EVENT_QUERY_ENDSESSION = 13; - - /** - * The log off or shutdown is in process for us, no matter - * what other process has replied, whether one of them has canceled - * or not the current end of session. It's like that cause we have answered - * that we will shutdown. - */ - public static final int EVENT_ENDSESSION = 14; - - /** - * The type of the event. - */ - private final int eventID; - - /** - * Constructs a prototypical Event. - * - * @param source The object on which the Event initially occurred. - * @param eventID the type of the event. - * @throws IllegalArgumentException if source is null. - */ - public SystemActivityEvent(Object source, int eventID) - { - super(source); - - this.eventID = eventID; - } - - /** - * Returns the type of the event. - * @return the event ID - */ - public int getEventID() - { - return this.eventID; - } - - /** - * Returns a String representation of this SystemActivityEvent object. - * - * @return A a String representation of this SystemActivityEvent object. - */ - @Override - public String toString() { - return getClass().getName() + "[eventID=" + eventID + "]"; - } -} +package net.java.sip.communicator.service.sysactivity.event; + +import java.util.*; + +/** + * An event class representing system activity that has occurred. + * The event id indicates the exact reason for this event. + * @author Damian Minkov + */ +public class SystemActivityEvent + extends EventObject +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * Notify that computers is going to sleep. + */ + public static final int EVENT_SLEEP = 0; + + /** + * Notify that computer is wakeing up after stand by. + */ + public static final int EVENT_WAKE = 1; + + /** + * Computer display has stand by. + */ + public static final int EVENT_DISPLAY_SLEEP = 2; + + /** + * Computer display wakes up after stand by. + */ + public static final int EVENT_DISPLAY_WAKE = 3; + + /** + * Screensaver has been started. + */ + public static final int EVENT_SCREENSAVER_START = 4; + + /** + * Screensaver will stop. + */ + public static final int EVENT_SCREENSAVER_WILL_STOP = 5; + + /** + * Screensaver has been stopped. + */ + public static final int EVENT_SCREENSAVER_STOP = 6; + + /** + * Screen has been locked. + */ + public static final int EVENT_SCREEN_LOCKED = 7; + + /** + * Screen has been unlocked. + */ + public static final int EVENT_SCREEN_UNLOCKED = 8; + + /** + * A change in network configuration has occurred. + */ + public static final int EVENT_NETWORK_CHANGE = 9; + + /** + * A system idle event has occurred. + */ + public static final int EVENT_SYSTEM_IDLE = 10; + + /** + * A system was in idle state and now exits. + */ + public static final int EVENT_SYSTEM_IDLE_END = 11; + + /** + * A change in dns configuration has occurred. + */ + public static final int EVENT_DNS_CHANGE = 12; + + /** + * Informing that the machine is logging of or shutting down. + */ + public static final int EVENT_QUERY_ENDSESSION = 13; + + /** + * The log off or shutdown is in process for us, no matter + * what other process has replied, whether one of them has canceled + * or not the current end of session. It's like that cause we have answered + * that we will shutdown. + */ + public static final int EVENT_ENDSESSION = 14; + + /** + * The type of the event. + */ + private final int eventID; + + /** + * Constructs a prototypical Event. + * + * @param source The object on which the Event initially occurred. + * @param eventID the type of the event. + * @throws IllegalArgumentException if source is null. + */ + public SystemActivityEvent(Object source, int eventID) + { + super(source); + + this.eventID = eventID; + } + + /** + * Returns the type of the event. + * @return the event ID + */ + public int getEventID() + { + return this.eventID; + } + + /** + * Returns a String representation of this SystemActivityEvent object. + * + * @return A a String representation of this SystemActivityEvent object. + */ + @Override + public String toString() { + return getClass().getName() + "[eventID=" + eventID + "]"; + } +} diff --git a/src/net/java/sip/communicator/util/GenericBuffer.java b/src/net/java/sip/communicator/util/GenericBuffer.java index 756d22f..3647174 100644 --- a/src/net/java/sip/communicator/util/GenericBuffer.java +++ b/src/net/java/sip/communicator/util/GenericBuffer.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,117 +15,117 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.util; - -import java.util.*; - -/** - * The GenericBuffer class provides a way to minimize the effort needed to - * buffer any kind of information. This class is particularly suited to - * optimizations based on reusing already computed data. - * - * @author Benoit Pradelle - */ -public class GenericBuffer -{ - private final Hashtable buffer; - - private int minAge = 0; - - private int curAge = 0; - - private final int maxCapacity; - - /** - * Sole constructor. - * - * @param bufferSize The buffer size. Adding data to a full buffer will - * cause the oldest data present in the buffer to be overwritten; - */ - public GenericBuffer(final int bufferSize) - { - assert bufferSize > 0; - - buffer = new Hashtable(bufferSize); - maxCapacity = bufferSize; - } - - /** - * Adds a value to the buffer. If the buffer is full, the oldest value in - * the buffer will be overwritten by this new value. - * - * @param value The value to add. Can't be null. - * @param context The context for which this value is valid. This basically - * represents the current value of all the variables which - * control the value is correct. The context is used to find this - * value in the buffer. If the context is already associated in - * the buffer with a value, nothing is added nor modified. - */ - public void addValue(final T value, final String context) - { - assert value != null && context != null; - - GenericBufferPair storage = buffer.get(context); - - if (storage == null) - { - storage = new GenericBufferPair(); - } - else - { - return; // don't override values - } - - // if the amount of data has reach the limit, search the oldest data - if (buffer.size() == maxCapacity) - { - for (Map.Entry e : buffer.entrySet()) - { - if (e.getValue().age == minAge) - { - buffer.remove(e.getKey()); - minAge++; - break; - } - } - } - - storage.age = curAge++; - storage.value = value; - - buffer.put(context, storage); - } - - /** - * Retrieves the value in the buffer corresponding to the context if it - * exists. - * - * @param context The context of the searched value. The context represents - * all the variables values for which this value is correct. - * @return The bufferized value with the searched context if it exists or - * null if no value is found. - */ - public T getValue(final String context) - { - assert context != null; - - GenericBufferPair res = buffer.get(context); - - if (res == null) - { - return null; - } - - return res.value; - } - - /** - * This class is a simple structure to store a pair context-value - */ - private class GenericBufferPair - { - public T value = null; - - public int age = 0; - } -} +package net.java.sip.communicator.util; + +import java.util.*; + +/** + * The GenericBuffer class provides a way to minimize the effort needed to + * buffer any kind of information. This class is particularly suited to + * optimizations based on reusing already computed data. + * + * @author Benoit Pradelle + */ +public class GenericBuffer +{ + private final Hashtable buffer; + + private int minAge = 0; + + private int curAge = 0; + + private final int maxCapacity; + + /** + * Sole constructor. + * + * @param bufferSize The buffer size. Adding data to a full buffer will + * cause the oldest data present in the buffer to be overwritten; + */ + public GenericBuffer(final int bufferSize) + { + assert bufferSize > 0; + + buffer = new Hashtable(bufferSize); + maxCapacity = bufferSize; + } + + /** + * Adds a value to the buffer. If the buffer is full, the oldest value in + * the buffer will be overwritten by this new value. + * + * @param value The value to add. Can't be null. + * @param context The context for which this value is valid. This basically + * represents the current value of all the variables which + * control the value is correct. The context is used to find this + * value in the buffer. If the context is already associated in + * the buffer with a value, nothing is added nor modified. + */ + public void addValue(final T value, final String context) + { + assert value != null && context != null; + + GenericBufferPair storage = buffer.get(context); + + if (storage == null) + { + storage = new GenericBufferPair(); + } + else + { + return; // don't override values + } + + // if the amount of data has reach the limit, search the oldest data + if (buffer.size() == maxCapacity) + { + for (Map.Entry e : buffer.entrySet()) + { + if (e.getValue().age == minAge) + { + buffer.remove(e.getKey()); + minAge++; + break; + } + } + } + + storage.age = curAge++; + storage.value = value; + + buffer.put(context, storage); + } + + /** + * Retrieves the value in the buffer corresponding to the context if it + * exists. + * + * @param context The context of the searched value. The context represents + * all the variables values for which this value is correct. + * @return The bufferized value with the searched context if it exists or + * null if no value is found. + */ + public T getValue(final String context) + { + assert context != null; + + GenericBufferPair res = buffer.get(context); + + if (res == null) + { + return null; + } + + return res.value; + } + + /** + * This class is a simple structure to store a pair context-value + */ + private class GenericBufferPair + { + public T value = null; + + public int age = 0; + } +} diff --git a/src/net/java/sip/communicator/util/account/AccountStatusUtils.java b/src/net/java/sip/communicator/util/account/AccountStatusUtils.java index 583fb0a..e5152b4 100644 --- a/src/net/java/sip/communicator/util/account/AccountStatusUtils.java +++ b/src/net/java/sip/communicator/util/account/AccountStatusUtils.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,196 +15,196 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.util.account; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.globalstatus.*; -import net.java.sip.communicator.util.*; - -import java.util.*; - -/** - * The AccountStatusUtils provides utility methods for account status - * management. - * - * @author Yana Stamcheva - */ -public class AccountStatusUtils -{ - private static GlobalStatusService globalStatusService; - - /** - * If the protocol provider supports presence operation set searches the - * last status which was selected, otherwise returns null. - * - * @param protocolProvider the protocol provider we're interested in. - * @return the last protocol provider presence status, or null if this - * provider doesn't support presence operation set - */ - public static Object getProtocolProviderLastStatus( - ProtocolProviderService protocolProvider) - { - if(getProtocolPresenceOpSet(protocolProvider) != null) - return getLastPresenceStatus(protocolProvider); - else - return getGlobalStatusService() - .getLastStatusString(protocolProvider); - } - - /** - * Returns the presence operation set for the given protocol provider. - * - * @param protocolProvider The protocol provider for which the - * presence operation set is searched. - * @return the presence operation set for the given protocol provider. - */ - public static OperationSetPresence getProtocolPresenceOpSet( - ProtocolProviderService protocolProvider) - { - OperationSet opSet - = protocolProvider.getOperationSet(OperationSetPresence.class); - - return - (opSet instanceof OperationSetPresence) - ? (OperationSetPresence) opSet - : null; - } - - /** - * Returns the last status that was stored in the configuration xml for the - * given protocol provider. - * - * @param protocolProvider the protocol provider - * @return the last status that was stored in the configuration xml for the - * given protocol provider - */ - public static PresenceStatus getLastPresenceStatus( - ProtocolProviderService protocolProvider) - { - if (getGlobalStatusService() != null) - return getGlobalStatusService().getLastPresenceStatus( - protocolProvider); - - return null; - } - - /** - * Returns the current status for protocol provider. - * - * @param protocolProvider the protocol provider - * @return the current status for protocol provider - */ - public static PresenceStatus getPresenceStatus( - ProtocolProviderService protocolProvider) - { - PresenceStatus status = null; - - OperationSetPresence opSet - = protocolProvider.getOperationSet(OperationSetPresence.class); - - if(opSet != null) - status = opSet.getPresenceStatus(); - - return status; - } - - /** - * Returns the online status of provider. - * @param protocolProvider the protocol provider - * @return the online status of provider. - */ - public static PresenceStatus getOnlineStatus( - ProtocolProviderService protocolProvider) - { - PresenceStatus onlineStatus = null; - - OperationSetPresence presence - = protocolProvider.getOperationSet(OperationSetPresence.class); - - // presence can be not supported - if(presence != null) - { - Iterator statusIterator - = presence.getSupportedStatusSet(); - while (statusIterator.hasNext()) - { - PresenceStatus status = statusIterator.next(); - int connectivity = status.getStatus(); - - if ((onlineStatus != null - && (onlineStatus.getStatus() < connectivity)) - || (onlineStatus == null - && (connectivity > 50 && connectivity < 80))) - { - onlineStatus = status; - } - } - } - - return onlineStatus; - } - - /** - * Returns the offline status of provider. - * @param protocolProvider the protocol provider - * @return the offline status of provider. - */ - public static PresenceStatus getOfflineStatus( - ProtocolProviderService protocolProvider) - { - PresenceStatus offlineStatus = null; - - OperationSetPresence presence - = protocolProvider.getOperationSet(OperationSetPresence.class); - - // presence can be not supported - if(presence != null) - { - Iterator statusIterator - = presence.getSupportedStatusSet(); - while (statusIterator.hasNext()) - { - PresenceStatus status = statusIterator.next(); - int connectivity = status.getStatus(); - - if (connectivity < 1) - { - offlineStatus = status; - } - } - } - - return offlineStatus; - } - - /** - * Returns the last contact status saved in the configuration. - * - * @param protocolProvider the protocol provider to which the status - * corresponds - * @return the last contact status saved in the configuration. - */ - public String getLastStatusString(ProtocolProviderService protocolProvider) - { - return getGlobalStatusService().getLastStatusString(protocolProvider); - } - - /** - * Returns the GlobalStatusService obtained from the bundle - * context. - * @return the GlobalStatusService obtained from the bundle - * context - */ - public static GlobalStatusService getGlobalStatusService() - { - if (globalStatusService == null) - { - globalStatusService - = ServiceUtils.getService( - UtilActivator.bundleContext, - GlobalStatusService.class); - } - - return globalStatusService; - } +package net.java.sip.communicator.util.account; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.globalstatus.*; +import net.java.sip.communicator.util.*; + +import java.util.*; + +/** + * The AccountStatusUtils provides utility methods for account status + * management. + * + * @author Yana Stamcheva + */ +public class AccountStatusUtils +{ + private static GlobalStatusService globalStatusService; + + /** + * If the protocol provider supports presence operation set searches the + * last status which was selected, otherwise returns null. + * + * @param protocolProvider the protocol provider we're interested in. + * @return the last protocol provider presence status, or null if this + * provider doesn't support presence operation set + */ + public static Object getProtocolProviderLastStatus( + ProtocolProviderService protocolProvider) + { + if(getProtocolPresenceOpSet(protocolProvider) != null) + return getLastPresenceStatus(protocolProvider); + else + return getGlobalStatusService() + .getLastStatusString(protocolProvider); + } + + /** + * Returns the presence operation set for the given protocol provider. + * + * @param protocolProvider The protocol provider for which the + * presence operation set is searched. + * @return the presence operation set for the given protocol provider. + */ + public static OperationSetPresence getProtocolPresenceOpSet( + ProtocolProviderService protocolProvider) + { + OperationSet opSet + = protocolProvider.getOperationSet(OperationSetPresence.class); + + return + (opSet instanceof OperationSetPresence) + ? (OperationSetPresence) opSet + : null; + } + + /** + * Returns the last status that was stored in the configuration xml for the + * given protocol provider. + * + * @param protocolProvider the protocol provider + * @return the last status that was stored in the configuration xml for the + * given protocol provider + */ + public static PresenceStatus getLastPresenceStatus( + ProtocolProviderService protocolProvider) + { + if (getGlobalStatusService() != null) + return getGlobalStatusService().getLastPresenceStatus( + protocolProvider); + + return null; + } + + /** + * Returns the current status for protocol provider. + * + * @param protocolProvider the protocol provider + * @return the current status for protocol provider + */ + public static PresenceStatus getPresenceStatus( + ProtocolProviderService protocolProvider) + { + PresenceStatus status = null; + + OperationSetPresence opSet + = protocolProvider.getOperationSet(OperationSetPresence.class); + + if(opSet != null) + status = opSet.getPresenceStatus(); + + return status; + } + + /** + * Returns the online status of provider. + * @param protocolProvider the protocol provider + * @return the online status of provider. + */ + public static PresenceStatus getOnlineStatus( + ProtocolProviderService protocolProvider) + { + PresenceStatus onlineStatus = null; + + OperationSetPresence presence + = protocolProvider.getOperationSet(OperationSetPresence.class); + + // presence can be not supported + if(presence != null) + { + Iterator statusIterator + = presence.getSupportedStatusSet(); + while (statusIterator.hasNext()) + { + PresenceStatus status = statusIterator.next(); + int connectivity = status.getStatus(); + + if ((onlineStatus != null + && (onlineStatus.getStatus() < connectivity)) + || (onlineStatus == null + && (connectivity > 50 && connectivity < 80))) + { + onlineStatus = status; + } + } + } + + return onlineStatus; + } + + /** + * Returns the offline status of provider. + * @param protocolProvider the protocol provider + * @return the offline status of provider. + */ + public static PresenceStatus getOfflineStatus( + ProtocolProviderService protocolProvider) + { + PresenceStatus offlineStatus = null; + + OperationSetPresence presence + = protocolProvider.getOperationSet(OperationSetPresence.class); + + // presence can be not supported + if(presence != null) + { + Iterator statusIterator + = presence.getSupportedStatusSet(); + while (statusIterator.hasNext()) + { + PresenceStatus status = statusIterator.next(); + int connectivity = status.getStatus(); + + if (connectivity < 1) + { + offlineStatus = status; + } + } + } + + return offlineStatus; + } + + /** + * Returns the last contact status saved in the configuration. + * + * @param protocolProvider the protocol provider to which the status + * corresponds + * @return the last contact status saved in the configuration. + */ + public String getLastStatusString(ProtocolProviderService protocolProvider) + { + return getGlobalStatusService().getLastStatusString(protocolProvider); + } + + /** + * Returns the GlobalStatusService obtained from the bundle + * context. + * @return the GlobalStatusService obtained from the bundle + * context + */ + public static GlobalStatusService getGlobalStatusService() + { + if (globalStatusService == null) + { + globalStatusService + = ServiceUtils.getService( + UtilActivator.bundleContext, + GlobalStatusService.class); + } + + return globalStatusService; + } } diff --git a/src/net/java/sip/communicator/util/account/AccountUtils.java b/src/net/java/sip/communicator/util/account/AccountUtils.java index ec69aca..82c9108 100644 --- a/src/net/java/sip/communicator/util/account/AccountUtils.java +++ b/src/net/java/sip/communicator/util/account/AccountUtils.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,305 +15,305 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.util.account; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The AccountUtils provides utility methods helping us to easily - * obtain an account or a groups of accounts or protocol providers by some - * specific criteria. - * - * @author Yana Stamcheva - */ -public class AccountUtils -{ - /** - * The logger. - */ - private static Logger logger = Logger.getLogger(AccountUtils.class); - - /** - * Returns an iterator over a list of all stored AccountID-s. - * - * @return an iterator over a list of all stored AccountID-s - */ - public static Collection getStoredAccounts() - { - AccountManager accountManager - = ServiceUtils.getService( UtilActivator.bundleContext, - AccountManager.class); - - return accountManager.getStoredAccounts(); - } - - /** - * Return the AccountID corresponding to the given string account - * identifier. - * - * @param accountID the account identifier string - * @return the AccountID corresponding to the given string account - * identifier - */ - public static AccountID getAccountForID(String accountID) - { - Collection allAccounts = getStoredAccounts(); - - for(AccountID account : allAccounts) - { - if(account.getAccountUniqueID().equals(accountID)) - return account; - } - return null; - } - - /** - * Returns a list of all currently registered providers, which support the - * given operationSetClass. - * - * @param opSetClass the operation set class for which we're looking - * for providers - * @return a list of all currently registered providers, which support the - * given operationSetClass - */ - public static List getRegisteredProviders( - Class opSetClass) - { - List opSetProviders - = new LinkedList(); - - for (ProtocolProviderFactory providerFactory - : UtilActivator.getProtocolProviderFactories().values()) - { - for (AccountID accountID : providerFactory.getRegisteredAccounts()) - { - ServiceReference ref - = providerFactory.getProviderForAccount(accountID); - - if (ref != null) - { - ProtocolProviderService protocolProvider - = UtilActivator.bundleContext.getService(ref); - - if ((protocolProvider.getOperationSet(opSetClass) != null) - && protocolProvider.isRegistered()) - { - opSetProviders.add(protocolProvider); - } - } - } - } - return opSetProviders; - } - - - /** - * Returns a list of all currently registered telephony providers for the - * given protocol name. - * @param protocolName the protocol name - * @param opSetClass the operation set class for which we're looking for - * providers - * @return a list of all currently registered providers for the given - * protocolName and supporting the given operationSetClass - */ - public static List getRegisteredProviders( - String protocolName, - Class opSetClass) - { - List opSetProviders - = new LinkedList(); - ProtocolProviderFactory providerFactory - = getProtocolProviderFactory(protocolName); - - if (providerFactory != null) - { - for (AccountID accountID : providerFactory.getRegisteredAccounts()) - { - ServiceReference ref - = providerFactory.getProviderForAccount(accountID); - - if (ref != null) - { - ProtocolProviderService protocolProvider - = UtilActivator.bundleContext.getService(ref); - - if ((protocolProvider.getOperationSet(opSetClass) != null) - && protocolProvider.isRegistered()) - { - opSetProviders.add(protocolProvider); - } - } - } - } - return opSetProviders; - } - - /** - * Returns a list of all registered protocol providers that could be used - * for the operation given by the operation set. Prefers the given preferred - * protocol provider and preferred protocol name if they're available and - * registered. - * - * @param opSet - * @param preferredProvider - * @param preferredProtocolName - * @return a list of all registered protocol providers that could be used - * for the operation given by the operation set - */ - public static List getOpSetRegisteredProviders( - Class opSet, - ProtocolProviderService preferredProvider, - String preferredProtocolName) - { - List providers - = new ArrayList(); - - if (preferredProvider != null) - { - if (preferredProvider.isRegistered()) - { - providers.add(preferredProvider); - } - // If we have a provider, but it's not registered we try to - // obtain all registered providers for the same protocol as the - // given preferred provider. - else - { - providers - = getRegisteredProviders( - preferredProvider.getProtocolName(), - opSet); - } - } - // If we don't have a preferred provider we try to obtain a - // preferred protocol name and all registered providers for it. - else - { - if (preferredProtocolName != null) - { - providers - = getRegisteredProviders(preferredProtocolName, opSet); - } - // If the protocol name is null we simply obtain all telephony - // providers. - else - { - providers = getRegisteredProviders(opSet); - } - } - - return providers; - } - - /** - * Returns the ProtocolProviderService corresponding to the given - * account identifier that is registered in the given factory - * @param accountID the identifier of the account - * @return the ProtocolProviderService corresponding to the given - * account identifier that is registered in the given factory - */ - public static ProtocolProviderService getRegisteredProviderForAccount( - AccountID accountID) - { - for (ProtocolProviderFactory factory - : UtilActivator.getProtocolProviderFactories().values()) - { - if (factory.getRegisteredAccounts().contains(accountID)) - { - ServiceReference ref - = factory.getProviderForAccount(accountID); - - if (ref != null) - { - return UtilActivator.bundleContext.getService(ref); - } - } - } - return null; - } - - /** - * Returns a ProtocolProviderFactory for a given protocol - * provider. - * @param protocolProvider the ProtocolProviderService, which - * factory we're looking for - * @return a ProtocolProviderFactory for a given protocol - * provider - */ - public static ProtocolProviderFactory getProtocolProviderFactory( - ProtocolProviderService protocolProvider) - { - return getProtocolProviderFactory(protocolProvider.getProtocolName()); - } - - /** - * Returns a ProtocolProviderFactory for a given protocol - * provider. - * @param protocolName the name of the protocol - * @return a ProtocolProviderFactory for a given protocol - * provider - */ - public static ProtocolProviderFactory getProtocolProviderFactory( - String protocolName) - { - String osgiFilter - = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; - ProtocolProviderFactory protocolProviderFactory = null; - - try - { - Collection> refs - = UtilActivator.bundleContext.getServiceReferences( - ProtocolProviderFactory.class, - osgiFilter); - - if ((refs != null) && !refs.isEmpty()) - { - protocolProviderFactory - = UtilActivator.bundleContext.getService( - refs.iterator().next()); - } - } - catch (InvalidSyntaxException ex) - { - logger.error("AccountUtils : " + ex); - } - return protocolProviderFactory; - } - - - /** - * Returns all registered protocol providers. - * - * @return a list of all registered providers - */ - public static Collection getRegisteredProviders() - { - List registeredProviders - = new LinkedList(); - - for (ProtocolProviderFactory providerFactory - : UtilActivator.getProtocolProviderFactories().values()) - { - for (AccountID accountID : providerFactory.getRegisteredAccounts()) - { - ServiceReference ref - = providerFactory.getProviderForAccount(accountID); - - if (ref != null) - { - ProtocolProviderService protocolProvider - = UtilActivator.bundleContext.getService(ref); - - registeredProviders.add(protocolProvider); - } - } - } - return registeredProviders; - } -} +package net.java.sip.communicator.util.account; + +import java.util.*; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * The AccountUtils provides utility methods helping us to easily + * obtain an account or a groups of accounts or protocol providers by some + * specific criteria. + * + * @author Yana Stamcheva + */ +public class AccountUtils +{ + /** + * The logger. + */ + private static Logger logger = Logger.getLogger(AccountUtils.class); + + /** + * Returns an iterator over a list of all stored AccountID-s. + * + * @return an iterator over a list of all stored AccountID-s + */ + public static Collection getStoredAccounts() + { + AccountManager accountManager + = ServiceUtils.getService( UtilActivator.bundleContext, + AccountManager.class); + + return accountManager.getStoredAccounts(); + } + + /** + * Return the AccountID corresponding to the given string account + * identifier. + * + * @param accountID the account identifier string + * @return the AccountID corresponding to the given string account + * identifier + */ + public static AccountID getAccountForID(String accountID) + { + Collection allAccounts = getStoredAccounts(); + + for(AccountID account : allAccounts) + { + if(account.getAccountUniqueID().equals(accountID)) + return account; + } + return null; + } + + /** + * Returns a list of all currently registered providers, which support the + * given operationSetClass. + * + * @param opSetClass the operation set class for which we're looking + * for providers + * @return a list of all currently registered providers, which support the + * given operationSetClass + */ + public static List getRegisteredProviders( + Class opSetClass) + { + List opSetProviders + = new LinkedList(); + + for (ProtocolProviderFactory providerFactory + : UtilActivator.getProtocolProviderFactories().values()) + { + for (AccountID accountID : providerFactory.getRegisteredAccounts()) + { + ServiceReference ref + = providerFactory.getProviderForAccount(accountID); + + if (ref != null) + { + ProtocolProviderService protocolProvider + = UtilActivator.bundleContext.getService(ref); + + if ((protocolProvider.getOperationSet(opSetClass) != null) + && protocolProvider.isRegistered()) + { + opSetProviders.add(protocolProvider); + } + } + } + } + return opSetProviders; + } + + + /** + * Returns a list of all currently registered telephony providers for the + * given protocol name. + * @param protocolName the protocol name + * @param opSetClass the operation set class for which we're looking for + * providers + * @return a list of all currently registered providers for the given + * protocolName and supporting the given operationSetClass + */ + public static List getRegisteredProviders( + String protocolName, + Class opSetClass) + { + List opSetProviders + = new LinkedList(); + ProtocolProviderFactory providerFactory + = getProtocolProviderFactory(protocolName); + + if (providerFactory != null) + { + for (AccountID accountID : providerFactory.getRegisteredAccounts()) + { + ServiceReference ref + = providerFactory.getProviderForAccount(accountID); + + if (ref != null) + { + ProtocolProviderService protocolProvider + = UtilActivator.bundleContext.getService(ref); + + if ((protocolProvider.getOperationSet(opSetClass) != null) + && protocolProvider.isRegistered()) + { + opSetProviders.add(protocolProvider); + } + } + } + } + return opSetProviders; + } + + /** + * Returns a list of all registered protocol providers that could be used + * for the operation given by the operation set. Prefers the given preferred + * protocol provider and preferred protocol name if they're available and + * registered. + * + * @param opSet + * @param preferredProvider + * @param preferredProtocolName + * @return a list of all registered protocol providers that could be used + * for the operation given by the operation set + */ + public static List getOpSetRegisteredProviders( + Class opSet, + ProtocolProviderService preferredProvider, + String preferredProtocolName) + { + List providers + = new ArrayList(); + + if (preferredProvider != null) + { + if (preferredProvider.isRegistered()) + { + providers.add(preferredProvider); + } + // If we have a provider, but it's not registered we try to + // obtain all registered providers for the same protocol as the + // given preferred provider. + else + { + providers + = getRegisteredProviders( + preferredProvider.getProtocolName(), + opSet); + } + } + // If we don't have a preferred provider we try to obtain a + // preferred protocol name and all registered providers for it. + else + { + if (preferredProtocolName != null) + { + providers + = getRegisteredProviders(preferredProtocolName, opSet); + } + // If the protocol name is null we simply obtain all telephony + // providers. + else + { + providers = getRegisteredProviders(opSet); + } + } + + return providers; + } + + /** + * Returns the ProtocolProviderService corresponding to the given + * account identifier that is registered in the given factory + * @param accountID the identifier of the account + * @return the ProtocolProviderService corresponding to the given + * account identifier that is registered in the given factory + */ + public static ProtocolProviderService getRegisteredProviderForAccount( + AccountID accountID) + { + for (ProtocolProviderFactory factory + : UtilActivator.getProtocolProviderFactories().values()) + { + if (factory.getRegisteredAccounts().contains(accountID)) + { + ServiceReference ref + = factory.getProviderForAccount(accountID); + + if (ref != null) + { + return UtilActivator.bundleContext.getService(ref); + } + } + } + return null; + } + + /** + * Returns a ProtocolProviderFactory for a given protocol + * provider. + * @param protocolProvider the ProtocolProviderService, which + * factory we're looking for + * @return a ProtocolProviderFactory for a given protocol + * provider + */ + public static ProtocolProviderFactory getProtocolProviderFactory( + ProtocolProviderService protocolProvider) + { + return getProtocolProviderFactory(protocolProvider.getProtocolName()); + } + + /** + * Returns a ProtocolProviderFactory for a given protocol + * provider. + * @param protocolName the name of the protocol + * @return a ProtocolProviderFactory for a given protocol + * provider + */ + public static ProtocolProviderFactory getProtocolProviderFactory( + String protocolName) + { + String osgiFilter + = "(" + ProtocolProviderFactory.PROTOCOL + "=" + protocolName + ")"; + ProtocolProviderFactory protocolProviderFactory = null; + + try + { + Collection> refs + = UtilActivator.bundleContext.getServiceReferences( + ProtocolProviderFactory.class, + osgiFilter); + + if ((refs != null) && !refs.isEmpty()) + { + protocolProviderFactory + = UtilActivator.bundleContext.getService( + refs.iterator().next()); + } + } + catch (InvalidSyntaxException ex) + { + logger.error("AccountUtils : " + ex); + } + return protocolProviderFactory; + } + + + /** + * Returns all registered protocol providers. + * + * @return a list of all registered providers + */ + public static Collection getRegisteredProviders() + { + List registeredProviders + = new LinkedList(); + + for (ProtocolProviderFactory providerFactory + : UtilActivator.getProtocolProviderFactories().values()) + { + for (AccountID accountID : providerFactory.getRegisteredAccounts()) + { + ServiceReference ref + = providerFactory.getProviderForAccount(accountID); + + if (ref != null) + { + ProtocolProviderService protocolProvider + = UtilActivator.bundleContext.getService(ref); + + registeredProviders.add(protocolProvider); + } + } + } + return registeredProviders; + } +} diff --git a/src/net/java/sip/communicator/util/account/LoginManager.java b/src/net/java/sip/communicator/util/account/LoginManager.java index 1dffaf8..09b3092 100644 --- a/src/net/java/sip/communicator/util/account/LoginManager.java +++ b/src/net/java/sip/communicator/util/account/LoginManager.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,577 +15,577 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.util.account; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.globalstatus.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The LoginManager manages the login operation. Here we obtain the - * ProtocolProviderFactory, we make the account installation and we - * handle all events related to the registration state. - *

    - * The LoginManager is the one that opens one or more - * LoginWindows for each ProtocolProviderFactory. The - * LoginWindow is where user could enter an identifier and password. - *

    - * Note that the behavior of this class will be changed when the Configuration - * Service is ready. - * - * @author Yana Stamcheva - */ -public class LoginManager - implements ServiceListener, - RegistrationStateChangeListener, - AccountManagerListener -{ - private static final Logger logger = Logger.getLogger(LoginManager.class); - - private boolean manuallyDisconnected = false; - - private final LoginRenderer loginRenderer; - - /** - * Creates an instance of the LoginManager, by specifying the main - * application window. - * - * @param loginRenderer the main application window - */ - public LoginManager(LoginRenderer loginRenderer) - { - this.loginRenderer = loginRenderer; - - UtilActivator.bundleContext.addServiceListener(this); - } - - /** - * Registers the given protocol provider. - * - * @param protocolProvider the ProtocolProviderService to register. - */ - public void login(ProtocolProviderService protocolProvider) - { - loginRenderer.startConnectingUI(protocolProvider); - - new RegisterProvider(protocolProvider, - loginRenderer.getSecurityAuthorityImpl(protocolProvider)).start(); - } - - /** - * Unregisters the given protocol provider. - * - * @param protocolProvider the ProtocolProviderService to unregister - */ - public static void logoff(ProtocolProviderService protocolProvider) - { - new UnregisterProvider(protocolProvider).start(); - } - - /** - * Shows login window for each registered account. - */ - public void runLogin() - { - // if someone is late registering catch it - UtilActivator.getAccountManager().addListener(this); - - for (ProtocolProviderFactory providerFactory : UtilActivator - .getProtocolProviderFactories().values()) - { - addAccountsForProtocolProviderFactory(providerFactory); - } - } - - /** - * Notifies that the loading of the stored accounts of a - * specific ProtocolProviderFactory has finished. - * - * @param event the AccountManagerEvent describing the - * AccountManager firing the notification and the - * other details of the specific notification. - */ - public void handleAccountManagerEvent(AccountManagerEvent event) - { - if(event.getType() - == AccountManagerEvent.STORED_ACCOUNTS_LOADED) - { - addAccountsForProtocolProviderFactory(event.getFactory()); - } - } - - /** - * Handles stored accounts for a protocol provider factory and add them - * to the UI and register them if needed. - * @param providerFactory the factory to handle. - */ - private void addAccountsForProtocolProviderFactory( - ProtocolProviderFactory providerFactory) - { - for (AccountID accountID : providerFactory.getRegisteredAccounts()) - { - ServiceReference serRef - = providerFactory.getProviderForAccount(accountID); - ProtocolProviderService protocolProvider - = UtilActivator.bundleContext.getService(serRef); - - handleProviderAdded(protocolProvider); - } - } - - /** - * The method is called by a ProtocolProvider implementation whenever a - * change in the registration state of the corresponding provider had - * occurred. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - RegistrationState newState = evt.getNewState(); - ProtocolProviderService protocolProvider = evt.getProvider(); - AccountID accountID = protocolProvider.getAccountID(); - - if (logger.isTraceEnabled()) - logger.trace("Protocol provider: " + protocolProvider - + " changed its state to: " + evt.getNewState().getStateName()); - - if (newState.equals(RegistrationState.REGISTERED) - || newState.equals(RegistrationState.UNREGISTERED) - || newState.equals(RegistrationState.EXPIRED) - || newState.equals(RegistrationState.AUTHENTICATION_FAILED) - || newState.equals(RegistrationState.CONNECTION_FAILED) - || newState.equals(RegistrationState.CHALLENGED_FOR_AUTHENTICATION) - || newState.equals(RegistrationState.REGISTERED)) - { - loginRenderer.stopConnectingUI(protocolProvider); - } - - if (newState.equals(RegistrationState.REGISTERED)) - { - loginRenderer.protocolProviderConnected(protocolProvider, - System.currentTimeMillis()); - } - else - { - String msgText; - if (newState.equals(RegistrationState.AUTHENTICATION_FAILED)) - { - switch (evt.getReasonCode()) - { - case RegistrationStateChangeEvent - .REASON_RECONNECTION_RATE_LIMIT_EXCEEDED: - - msgText = UtilActivator.getResources().getI18NString( - "service.gui.RECONNECTION_LIMIT_EXCEEDED", new String[] - { accountID.getUserID(), accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - break; - - case RegistrationStateChangeEvent.REASON_NON_EXISTING_USER_ID: - msgText = UtilActivator.getResources().getI18NString( - "service.gui.NON_EXISTING_USER_ID", - new String[] - { protocolProvider.getProtocolDisplayName() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - break; - case RegistrationStateChangeEvent.REASON_TLS_REQUIRED: - msgText = UtilActivator.getResources().getI18NString( - "service.gui.NON_SECURE_CONNECTION", - new String[] - { accountID.getAccountAddress() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - break; - default: - break; - } - - if (logger.isTraceEnabled()) - logger.trace(evt.getReason()); - } -// CONNECTION_FAILED events are now dispatched in reconnect plugin -// else if (newState.equals(RegistrationState.CONNECTION_FAILED)) -// { -// loginRenderer.protocolProviderConnectionFailed( -// protocolProvider, -// this); -// -// logger.trace(evt.getReason()); -// } - else if (newState.equals(RegistrationState.EXPIRED)) - { - msgText = UtilActivator.getResources().getI18NString( - "service.gui.CONNECTION_EXPIRED_MSG", - new String[] - { protocolProvider.getProtocolDisplayName() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - - logger.error(evt.getReason()); - } - else if (newState.equals(RegistrationState.UNREGISTERED)) - { - if (!manuallyDisconnected) - { - if (evt.getReasonCode() == RegistrationStateChangeEvent - .REASON_MULTIPLE_LOGINS) - { - msgText = UtilActivator.getResources().getI18NString( - "service.gui.MULTIPLE_LOGINS", - new String[] - { accountID.getUserID(), accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - } - else if (evt.getReasonCode() == RegistrationStateChangeEvent - .REASON_CLIENT_LIMIT_REACHED_FOR_IP) - { - msgText = UtilActivator.getResources().getI18NString( - "service.gui.LIMIT_REACHED_FOR_IP", new String[] - { protocolProvider.getProtocolDisplayName() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - } - else if (evt.getReasonCode() == RegistrationStateChangeEvent - .REASON_USER_REQUEST) - { - // do nothing - } - else - { - msgText = UtilActivator.getResources().getI18NString( - "service.gui.UNREGISTERED_MESSAGE", new String[] - { accountID.getUserID(), accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - msgText); - } - if (logger.isTraceEnabled()) - logger.trace(evt.getReason()); - } - } - } - } - - /** - * Implements the ServiceListener method. Verifies whether the - * passed event concerns a ProtocolProviderService and adds the - * corresponding UI controls. - * - * @param event The ServiceEvent object. - */ - public void serviceChanged(ServiceEvent event) - { - ServiceReference serviceRef = event.getServiceReference(); - - // if the event is caused by a bundle being stopped, we don't want to - // know - if (serviceRef.getBundle().getState() == Bundle.STOPPING) - return; - - Object service = UtilActivator.bundleContext.getService(serviceRef); - - // we don't care if the source service is not a protocol provider - if (!(service instanceof ProtocolProviderService)) - return; - - switch (event.getType()) - { - case ServiceEvent.REGISTERED: - handleProviderAdded((ProtocolProviderService) service); - break; - case ServiceEvent.UNREGISTERING: - handleProviderRemoved((ProtocolProviderService) service); - break; - } - } - - /** - * Adds all UI components (status selector box, etc) related to the given - * protocol provider. - * - * @param protocolProvider the ProtocolProviderService - */ - private void handleProviderAdded(ProtocolProviderService protocolProvider) - { - if (logger.isTraceEnabled()) - logger.trace("The following protocol provider was just added: " - + protocolProvider.getAccountID().getAccountAddress()); - - synchronized(loginRenderer) - { - if(!loginRenderer.containsProtocolProviderUI(protocolProvider)) - { - protocolProvider.addRegistrationStateChangeListener(this); - loginRenderer.addProtocolProviderUI(protocolProvider); - } - // we have already added this provider and scheduled - // a login if needed - // we've done our work, if it fails or something else - // reconnect or other plugins will take care - else - return; - } - - Object status = AccountStatusUtils - .getProtocolProviderLastStatus(protocolProvider); - - if (status == null - || status.equals(GlobalStatusEnum.ONLINE_STATUS) - || ((status instanceof PresenceStatus) && (((PresenceStatus) status) - .getStatus() >= PresenceStatus.ONLINE_THRESHOLD))) - { - login(protocolProvider); - } - } - - /** - * Removes all UI components related to the given protocol provider. - * - * @param protocolProvider the ProtocolProviderService - */ - private void handleProviderRemoved(ProtocolProviderService protocolProvider) - { - loginRenderer.removeProtocolProviderUI(protocolProvider); - } - - /** - * Returns true to indicate the jitsi has been manually - * disconnected, false - otherwise. - * - * @return true to indicate the jitsi has been manually - * disconnected, false - otherwise - */ - public boolean isManuallyDisconnected() - { - return manuallyDisconnected; - } - - /** - * Sets the manually disconnected property. - * - * @param manuallyDisconnected true to indicate the jitsi has been - * manually disconnected, false - otherwise - */ - public void setManuallyDisconnected(boolean manuallyDisconnected) - { - this.manuallyDisconnected = manuallyDisconnected; - } - - /** - * Registers a protocol provider in a separate thread. - */ - private class RegisterProvider - extends Thread - { - private final ProtocolProviderService protocolProvider; - - private final SecurityAuthority secAuth; - - RegisterProvider( ProtocolProviderService protocolProvider, - SecurityAuthority secAuth) - { - this.protocolProvider = protocolProvider; - this.secAuth = secAuth; - - if(logger.isTraceEnabled()) - logger.trace("Registering provider: " - + protocolProvider.getAccountID().getAccountAddress(), - new Exception( - "Just tracing, provider registering, not an error!")); - } - - /** - * Registers the contained protocol provider and process all possible - * errors that may occur during the registration process. - */ - @Override - public void run() - { - try - { - protocolProvider.register(secAuth); - } - catch (OperationFailedException ex) - { - handleOperationFailedException(ex); - } - catch (Throwable ex) - { - logger.error("Failed to register protocol provider. ", ex); - - AccountID accountID = protocolProvider.getAccountID(); - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - UtilActivator.getResources() - .getI18NString("service.gui.LOGIN_GENERAL_ERROR", - new String[] - { accountID.getUserID(), - accountID.getProtocolName(), - accountID.getService() })); - } - } - - private void handleOperationFailedException(OperationFailedException ex) - { - String errorMessage = ""; - - switch (ex.getErrorCode()) - { - case OperationFailedException.GENERAL_ERROR: - { - logger.error("Provider could not be registered" - + " due to the following general error: ", ex); - - AccountID accountID = protocolProvider.getAccountID(); - errorMessage = - UtilActivator.getResources().getI18NString( - "service.gui.LOGIN_GENERAL_ERROR", - new String[] - { accountID.getUserID(), - accountID.getProtocolName(), - accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), errorMessage, ex); - } - break; - case OperationFailedException.INTERNAL_ERROR: - { - logger.error("Provider could not be registered" - + " due to the following internal error: ", ex); - - AccountID accountID = protocolProvider.getAccountID(); - errorMessage = - UtilActivator.getResources().getI18NString( - "service.gui.LOGIN_INTERNAL_ERROR", - new String[] - { accountID.getUserID(), accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources().getI18NString( - "service.gui.ERROR"), errorMessage, ex); - } - break; - case OperationFailedException.NETWORK_FAILURE: - { - if (logger.isInfoEnabled()) - { - logger.info("Provider could not be registered" - + " due to a network failure: " + ex); - } - - loginRenderer.protocolProviderConnectionFailed( - protocolProvider, - LoginManager.this); - } - break; - case OperationFailedException.INVALID_ACCOUNT_PROPERTIES: - { - logger.error("Provider could not be registered" - + " due to an invalid account property: ", ex); - - AccountID accountID = protocolProvider.getAccountID(); - errorMessage = - UtilActivator.getResources().getI18NString( - "service.gui.LOGIN_INVALID_PROPERTIES_ERROR", - new String[] - { accountID.getUserID(), accountID.getService() }); - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - errorMessage, ex); - } - break; - default: - logger.error("Provider could not be registered.", ex); - } - } - } - - /** - * Unregisters a protocol provider in a separate thread. - */ - private static class UnregisterProvider - extends Thread - { - ProtocolProviderService protocolProvider; - - UnregisterProvider(ProtocolProviderService protocolProvider) - { - this.protocolProvider = protocolProvider; - } - - /** - * Unregisters the contained protocol provider and process all possible - * errors that may occur during the un-registration process. - */ - @Override - public void run() - { - try - { - protocolProvider.unregister(true); - } - catch (OperationFailedException ex) - { - int errorCode = ex.getErrorCode(); - - if (errorCode == OperationFailedException.GENERAL_ERROR) - { - logger.error("Provider could not be unregistered" - + " due to the following general error: " + ex); - } - else if (errorCode == OperationFailedException.INTERNAL_ERROR) - { - logger.error("Provider could not be unregistered" - + " due to the following internal error: " + ex); - } - else if (errorCode == OperationFailedException.NETWORK_FAILURE) - { - logger.error("Provider could not be unregistered" - + " due to a network failure: " + ex); - } - - UtilActivator.getAlertUIService().showAlertDialog( - UtilActivator.getResources() - .getI18NString("service.gui.ERROR"), - UtilActivator.getResources() - .getI18NString("service.gui.LOGOFF_NOT_SUCCEEDED", - new String[] - { protocolProvider.getAccountID().getUserID(), - protocolProvider.getAccountID().getService() })); - } - } - } -} +package net.java.sip.communicator.util.account; + +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.globalstatus.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * The LoginManager manages the login operation. Here we obtain the + * ProtocolProviderFactory, we make the account installation and we + * handle all events related to the registration state. + *

    + * The LoginManager is the one that opens one or more + * LoginWindows for each ProtocolProviderFactory. The + * LoginWindow is where user could enter an identifier and password. + *

    + * Note that the behavior of this class will be changed when the Configuration + * Service is ready. + * + * @author Yana Stamcheva + */ +public class LoginManager + implements ServiceListener, + RegistrationStateChangeListener, + AccountManagerListener +{ + private static final Logger logger = Logger.getLogger(LoginManager.class); + + private boolean manuallyDisconnected = false; + + private final LoginRenderer loginRenderer; + + /** + * Creates an instance of the LoginManager, by specifying the main + * application window. + * + * @param loginRenderer the main application window + */ + public LoginManager(LoginRenderer loginRenderer) + { + this.loginRenderer = loginRenderer; + + UtilActivator.bundleContext.addServiceListener(this); + } + + /** + * Registers the given protocol provider. + * + * @param protocolProvider the ProtocolProviderService to register. + */ + public void login(ProtocolProviderService protocolProvider) + { + loginRenderer.startConnectingUI(protocolProvider); + + new RegisterProvider(protocolProvider, + loginRenderer.getSecurityAuthorityImpl(protocolProvider)).start(); + } + + /** + * Unregisters the given protocol provider. + * + * @param protocolProvider the ProtocolProviderService to unregister + */ + public static void logoff(ProtocolProviderService protocolProvider) + { + new UnregisterProvider(protocolProvider).start(); + } + + /** + * Shows login window for each registered account. + */ + public void runLogin() + { + // if someone is late registering catch it + UtilActivator.getAccountManager().addListener(this); + + for (ProtocolProviderFactory providerFactory : UtilActivator + .getProtocolProviderFactories().values()) + { + addAccountsForProtocolProviderFactory(providerFactory); + } + } + + /** + * Notifies that the loading of the stored accounts of a + * specific ProtocolProviderFactory has finished. + * + * @param event the AccountManagerEvent describing the + * AccountManager firing the notification and the + * other details of the specific notification. + */ + public void handleAccountManagerEvent(AccountManagerEvent event) + { + if(event.getType() + == AccountManagerEvent.STORED_ACCOUNTS_LOADED) + { + addAccountsForProtocolProviderFactory(event.getFactory()); + } + } + + /** + * Handles stored accounts for a protocol provider factory and add them + * to the UI and register them if needed. + * @param providerFactory the factory to handle. + */ + private void addAccountsForProtocolProviderFactory( + ProtocolProviderFactory providerFactory) + { + for (AccountID accountID : providerFactory.getRegisteredAccounts()) + { + ServiceReference serRef + = providerFactory.getProviderForAccount(accountID); + ProtocolProviderService protocolProvider + = UtilActivator.bundleContext.getService(serRef); + + handleProviderAdded(protocolProvider); + } + } + + /** + * The method is called by a ProtocolProvider implementation whenever a + * change in the registration state of the corresponding provider had + * occurred. + * + * @param evt ProviderStatusChangeEvent the event describing the status + * change. + */ + public void registrationStateChanged(RegistrationStateChangeEvent evt) + { + RegistrationState newState = evt.getNewState(); + ProtocolProviderService protocolProvider = evt.getProvider(); + AccountID accountID = protocolProvider.getAccountID(); + + if (logger.isTraceEnabled()) + logger.trace("Protocol provider: " + protocolProvider + + " changed its state to: " + evt.getNewState().getStateName()); + + if (newState.equals(RegistrationState.REGISTERED) + || newState.equals(RegistrationState.UNREGISTERED) + || newState.equals(RegistrationState.EXPIRED) + || newState.equals(RegistrationState.AUTHENTICATION_FAILED) + || newState.equals(RegistrationState.CONNECTION_FAILED) + || newState.equals(RegistrationState.CHALLENGED_FOR_AUTHENTICATION) + || newState.equals(RegistrationState.REGISTERED)) + { + loginRenderer.stopConnectingUI(protocolProvider); + } + + if (newState.equals(RegistrationState.REGISTERED)) + { + loginRenderer.protocolProviderConnected(protocolProvider, + System.currentTimeMillis()); + } + else + { + String msgText; + if (newState.equals(RegistrationState.AUTHENTICATION_FAILED)) + { + switch (evt.getReasonCode()) + { + case RegistrationStateChangeEvent + .REASON_RECONNECTION_RATE_LIMIT_EXCEEDED: + + msgText = UtilActivator.getResources().getI18NString( + "service.gui.RECONNECTION_LIMIT_EXCEEDED", new String[] + { accountID.getUserID(), accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + break; + + case RegistrationStateChangeEvent.REASON_NON_EXISTING_USER_ID: + msgText = UtilActivator.getResources().getI18NString( + "service.gui.NON_EXISTING_USER_ID", + new String[] + { protocolProvider.getProtocolDisplayName() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + break; + case RegistrationStateChangeEvent.REASON_TLS_REQUIRED: + msgText = UtilActivator.getResources().getI18NString( + "service.gui.NON_SECURE_CONNECTION", + new String[] + { accountID.getAccountAddress() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + break; + default: + break; + } + + if (logger.isTraceEnabled()) + logger.trace(evt.getReason()); + } +// CONNECTION_FAILED events are now dispatched in reconnect plugin +// else if (newState.equals(RegistrationState.CONNECTION_FAILED)) +// { +// loginRenderer.protocolProviderConnectionFailed( +// protocolProvider, +// this); +// +// logger.trace(evt.getReason()); +// } + else if (newState.equals(RegistrationState.EXPIRED)) + { + msgText = UtilActivator.getResources().getI18NString( + "service.gui.CONNECTION_EXPIRED_MSG", + new String[] + { protocolProvider.getProtocolDisplayName() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + + logger.error(evt.getReason()); + } + else if (newState.equals(RegistrationState.UNREGISTERED)) + { + if (!manuallyDisconnected) + { + if (evt.getReasonCode() == RegistrationStateChangeEvent + .REASON_MULTIPLE_LOGINS) + { + msgText = UtilActivator.getResources().getI18NString( + "service.gui.MULTIPLE_LOGINS", + new String[] + { accountID.getUserID(), accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + } + else if (evt.getReasonCode() == RegistrationStateChangeEvent + .REASON_CLIENT_LIMIT_REACHED_FOR_IP) + { + msgText = UtilActivator.getResources().getI18NString( + "service.gui.LIMIT_REACHED_FOR_IP", new String[] + { protocolProvider.getProtocolDisplayName() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + } + else if (evt.getReasonCode() == RegistrationStateChangeEvent + .REASON_USER_REQUEST) + { + // do nothing + } + else + { + msgText = UtilActivator.getResources().getI18NString( + "service.gui.UNREGISTERED_MESSAGE", new String[] + { accountID.getUserID(), accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + msgText); + } + if (logger.isTraceEnabled()) + logger.trace(evt.getReason()); + } + } + } + } + + /** + * Implements the ServiceListener method. Verifies whether the + * passed event concerns a ProtocolProviderService and adds the + * corresponding UI controls. + * + * @param event The ServiceEvent object. + */ + public void serviceChanged(ServiceEvent event) + { + ServiceReference serviceRef = event.getServiceReference(); + + // if the event is caused by a bundle being stopped, we don't want to + // know + if (serviceRef.getBundle().getState() == Bundle.STOPPING) + return; + + Object service = UtilActivator.bundleContext.getService(serviceRef); + + // we don't care if the source service is not a protocol provider + if (!(service instanceof ProtocolProviderService)) + return; + + switch (event.getType()) + { + case ServiceEvent.REGISTERED: + handleProviderAdded((ProtocolProviderService) service); + break; + case ServiceEvent.UNREGISTERING: + handleProviderRemoved((ProtocolProviderService) service); + break; + } + } + + /** + * Adds all UI components (status selector box, etc) related to the given + * protocol provider. + * + * @param protocolProvider the ProtocolProviderService + */ + private void handleProviderAdded(ProtocolProviderService protocolProvider) + { + if (logger.isTraceEnabled()) + logger.trace("The following protocol provider was just added: " + + protocolProvider.getAccountID().getAccountAddress()); + + synchronized(loginRenderer) + { + if(!loginRenderer.containsProtocolProviderUI(protocolProvider)) + { + protocolProvider.addRegistrationStateChangeListener(this); + loginRenderer.addProtocolProviderUI(protocolProvider); + } + // we have already added this provider and scheduled + // a login if needed + // we've done our work, if it fails or something else + // reconnect or other plugins will take care + else + return; + } + + Object status = AccountStatusUtils + .getProtocolProviderLastStatus(protocolProvider); + + if (status == null + || status.equals(GlobalStatusEnum.ONLINE_STATUS) + || ((status instanceof PresenceStatus) && (((PresenceStatus) status) + .getStatus() >= PresenceStatus.ONLINE_THRESHOLD))) + { + login(protocolProvider); + } + } + + /** + * Removes all UI components related to the given protocol provider. + * + * @param protocolProvider the ProtocolProviderService + */ + private void handleProviderRemoved(ProtocolProviderService protocolProvider) + { + loginRenderer.removeProtocolProviderUI(protocolProvider); + } + + /** + * Returns true to indicate the jitsi has been manually + * disconnected, false - otherwise. + * + * @return true to indicate the jitsi has been manually + * disconnected, false - otherwise + */ + public boolean isManuallyDisconnected() + { + return manuallyDisconnected; + } + + /** + * Sets the manually disconnected property. + * + * @param manuallyDisconnected true to indicate the jitsi has been + * manually disconnected, false - otherwise + */ + public void setManuallyDisconnected(boolean manuallyDisconnected) + { + this.manuallyDisconnected = manuallyDisconnected; + } + + /** + * Registers a protocol provider in a separate thread. + */ + private class RegisterProvider + extends Thread + { + private final ProtocolProviderService protocolProvider; + + private final SecurityAuthority secAuth; + + RegisterProvider( ProtocolProviderService protocolProvider, + SecurityAuthority secAuth) + { + this.protocolProvider = protocolProvider; + this.secAuth = secAuth; + + if(logger.isTraceEnabled()) + logger.trace("Registering provider: " + + protocolProvider.getAccountID().getAccountAddress(), + new Exception( + "Just tracing, provider registering, not an error!")); + } + + /** + * Registers the contained protocol provider and process all possible + * errors that may occur during the registration process. + */ + @Override + public void run() + { + try + { + protocolProvider.register(secAuth); + } + catch (OperationFailedException ex) + { + handleOperationFailedException(ex); + } + catch (Throwable ex) + { + logger.error("Failed to register protocol provider. ", ex); + + AccountID accountID = protocolProvider.getAccountID(); + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + UtilActivator.getResources() + .getI18NString("service.gui.LOGIN_GENERAL_ERROR", + new String[] + { accountID.getUserID(), + accountID.getProtocolName(), + accountID.getService() })); + } + } + + private void handleOperationFailedException(OperationFailedException ex) + { + String errorMessage = ""; + + switch (ex.getErrorCode()) + { + case OperationFailedException.GENERAL_ERROR: + { + logger.error("Provider could not be registered" + + " due to the following general error: ", ex); + + AccountID accountID = protocolProvider.getAccountID(); + errorMessage = + UtilActivator.getResources().getI18NString( + "service.gui.LOGIN_GENERAL_ERROR", + new String[] + { accountID.getUserID(), + accountID.getProtocolName(), + accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), errorMessage, ex); + } + break; + case OperationFailedException.INTERNAL_ERROR: + { + logger.error("Provider could not be registered" + + " due to the following internal error: ", ex); + + AccountID accountID = protocolProvider.getAccountID(); + errorMessage = + UtilActivator.getResources().getI18NString( + "service.gui.LOGIN_INTERNAL_ERROR", + new String[] + { accountID.getUserID(), accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources().getI18NString( + "service.gui.ERROR"), errorMessage, ex); + } + break; + case OperationFailedException.NETWORK_FAILURE: + { + if (logger.isInfoEnabled()) + { + logger.info("Provider could not be registered" + + " due to a network failure: " + ex); + } + + loginRenderer.protocolProviderConnectionFailed( + protocolProvider, + LoginManager.this); + } + break; + case OperationFailedException.INVALID_ACCOUNT_PROPERTIES: + { + logger.error("Provider could not be registered" + + " due to an invalid account property: ", ex); + + AccountID accountID = protocolProvider.getAccountID(); + errorMessage = + UtilActivator.getResources().getI18NString( + "service.gui.LOGIN_INVALID_PROPERTIES_ERROR", + new String[] + { accountID.getUserID(), accountID.getService() }); + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + errorMessage, ex); + } + break; + default: + logger.error("Provider could not be registered.", ex); + } + } + } + + /** + * Unregisters a protocol provider in a separate thread. + */ + private static class UnregisterProvider + extends Thread + { + ProtocolProviderService protocolProvider; + + UnregisterProvider(ProtocolProviderService protocolProvider) + { + this.protocolProvider = protocolProvider; + } + + /** + * Unregisters the contained protocol provider and process all possible + * errors that may occur during the un-registration process. + */ + @Override + public void run() + { + try + { + protocolProvider.unregister(true); + } + catch (OperationFailedException ex) + { + int errorCode = ex.getErrorCode(); + + if (errorCode == OperationFailedException.GENERAL_ERROR) + { + logger.error("Provider could not be unregistered" + + " due to the following general error: " + ex); + } + else if (errorCode == OperationFailedException.INTERNAL_ERROR) + { + logger.error("Provider could not be unregistered" + + " due to the following internal error: " + ex); + } + else if (errorCode == OperationFailedException.NETWORK_FAILURE) + { + logger.error("Provider could not be unregistered" + + " due to a network failure: " + ex); + } + + UtilActivator.getAlertUIService().showAlertDialog( + UtilActivator.getResources() + .getI18NString("service.gui.ERROR"), + UtilActivator.getResources() + .getI18NString("service.gui.LOGOFF_NOT_SUCCEEDED", + new String[] + { protocolProvider.getAccountID().getUserID(), + protocolProvider.getAccountID().getService() })); + } + } + } +} diff --git a/src/net/java/sip/communicator/util/account/LoginRenderer.java b/src/net/java/sip/communicator/util/account/LoginRenderer.java index ee39940..e1ae850 100644 --- a/src/net/java/sip/communicator/util/account/LoginRenderer.java +++ b/src/net/java/sip/communicator/util/account/LoginRenderer.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,94 +15,94 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.util.account; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The LoginRenderer is the renderer of all login related operations. - * - * @author Yana Stamcheva - */ -public interface LoginRenderer -{ - /** - * Adds the user interface related to the given protocol provider. - * - * @param protocolProvider the protocol provider for which we add the user - * interface - */ - public void addProtocolProviderUI( - ProtocolProviderService protocolProvider); - - /** - * Removes the user interface related to the given protocol provider. - * - * @param protocolProvider the protocol provider to remove - */ - public void removeProtocolProviderUI( - ProtocolProviderService protocolProvider); - - /** - * Starts the connecting user interface for the given protocol provider. - * - * @param protocolProvider the protocol provider for which we add the - * connecting user interface - */ - public void startConnectingUI(ProtocolProviderService protocolProvider); - - /** - * Stops the connecting user interface for the given protocol provider. - * - * @param protocolProvider the protocol provider for which we remove the - * connecting user interface - */ - public void stopConnectingUI(ProtocolProviderService protocolProvider); - - /** - * Indicates that the given protocol provider is now connected. - * - * @param protocolProvider the ProtocolProviderService that is - * connected - * @param date the date on which the event occured - */ - public void protocolProviderConnected( - ProtocolProviderService protocolProvider, - long date); - - /** - * Indicates that a protocol provider connection has failed. - * - * @param protocolProvider the ProtocolProviderService, which - * connection failed - * @param loginManagerCallback the LoginManager implementation, - * which is managing the process - */ - public void protocolProviderConnectionFailed( - ProtocolProviderService protocolProvider, - LoginManager loginManagerCallback); - - /** - * Returns the SecurityAuthority implementation related to this - * login renderer. - * - * @param protocolProvider the specific ProtocolProviderService, - * for which we're obtaining a security authority - * @return the SecurityAuthority implementation related to this - * login renderer - */ - public SecurityAuthority getSecurityAuthorityImpl( - ProtocolProviderService protocolProvider); - - /** - * Indicates if the given protocolProvider related user interface - * is already rendered. - * - * @param protocolProvider the ProtocolProviderService, which - * related user interface we're looking for - * @return true if the given protocolProvider related user - * interface is already rendered - */ - public boolean containsProtocolProviderUI( - ProtocolProviderService protocolProvider); +package net.java.sip.communicator.util.account; + +import net.java.sip.communicator.service.protocol.*; + +/** + * The LoginRenderer is the renderer of all login related operations. + * + * @author Yana Stamcheva + */ +public interface LoginRenderer +{ + /** + * Adds the user interface related to the given protocol provider. + * + * @param protocolProvider the protocol provider for which we add the user + * interface + */ + public void addProtocolProviderUI( + ProtocolProviderService protocolProvider); + + /** + * Removes the user interface related to the given protocol provider. + * + * @param protocolProvider the protocol provider to remove + */ + public void removeProtocolProviderUI( + ProtocolProviderService protocolProvider); + + /** + * Starts the connecting user interface for the given protocol provider. + * + * @param protocolProvider the protocol provider for which we add the + * connecting user interface + */ + public void startConnectingUI(ProtocolProviderService protocolProvider); + + /** + * Stops the connecting user interface for the given protocol provider. + * + * @param protocolProvider the protocol provider for which we remove the + * connecting user interface + */ + public void stopConnectingUI(ProtocolProviderService protocolProvider); + + /** + * Indicates that the given protocol provider is now connected. + * + * @param protocolProvider the ProtocolProviderService that is + * connected + * @param date the date on which the event occured + */ + public void protocolProviderConnected( + ProtocolProviderService protocolProvider, + long date); + + /** + * Indicates that a protocol provider connection has failed. + * + * @param protocolProvider the ProtocolProviderService, which + * connection failed + * @param loginManagerCallback the LoginManager implementation, + * which is managing the process + */ + public void protocolProviderConnectionFailed( + ProtocolProviderService protocolProvider, + LoginManager loginManagerCallback); + + /** + * Returns the SecurityAuthority implementation related to this + * login renderer. + * + * @param protocolProvider the specific ProtocolProviderService, + * for which we're obtaining a security authority + * @return the SecurityAuthority implementation related to this + * login renderer + */ + public SecurityAuthority getSecurityAuthorityImpl( + ProtocolProviderService protocolProvider); + + /** + * Indicates if the given protocolProvider related user interface + * is already rendered. + * + * @param protocolProvider the ProtocolProviderService, which + * related user interface we're looking for + * @return true if the given protocolProvider related user + * interface is already rendered + */ + public boolean containsProtocolProviderUI( + ProtocolProviderService protocolProvider); } -- cgit v1.1 From 4dcdaf941846f0105b41d9f535617d729a8742a8 Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Tue, 23 Feb 2016 16:45:20 -0600 Subject: Fixes a typo, reported by @kamenik. --- .../impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java index 52368bf..24ee50d 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java @@ -161,7 +161,7 @@ public class ColibriConferenceIQ throw new NullPointerException("channelBundle"); return - channelBundles.contains(channelBundles) + channelBundles.contains(channelBundle) ? false : channelBundles.add(channelBundle); } -- cgit v1.1 From 443ff86a3929de619a432e5b45942142cfe84a01 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Wed, 24 Feb 2016 11:22:47 +0100 Subject: Add .gitattributes to prevent future EOL problems Signed-off-by: Etienne CHAMPETIER --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..488f808 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.java text eol=lf diff=java -- cgit v1.1 From 033ff2d89c62950f6c0e68d3feffa7feabd4aae1 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 28 Feb 2016 21:39:40 +0100 Subject: Allow messaging and server account info without presence Neither the IM nor the server stored account info capabilities of the account are related to the presence capabilities. Add the support to the provider even if presence is disabled. Closes #215 --- .../sip/ProtocolProviderServiceSipImpl.java | 70 +++++++++++----------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index 0fbcf23..d0460fb 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -610,50 +610,50 @@ public class ProtocolProviderServiceSipImpl addSupportedOperationSet( OperationSetPresence.class, opSetPersPresence); + } - // Only init messaging and typing if enabled. - boolean isMessagingDisabled - = SipActivator.getConfigurationService() - .getBoolean(IS_MESSAGING_DISABLED, false); + // Only init messaging and typing if enabled. + boolean isMessagingDisabled + = SipActivator.getConfigurationService() + .getBoolean(IS_MESSAGING_DISABLED, false); - if (!isMessagingDisabled) - { - // init instant messaging - this.opSetBasicIM = - new OperationSetBasicInstantMessagingSipImpl(this); + if (!isMessagingDisabled) + { + // init instant messaging + this.opSetBasicIM = + new OperationSetBasicInstantMessagingSipImpl(this); - addSupportedOperationSet( - OperationSetBasicInstantMessaging.class, - opSetBasicIM); + addSupportedOperationSet( + OperationSetBasicInstantMessaging.class, + opSetBasicIM); - // init typing notifications - this.opSetTypingNotif - = new OperationSetTypingNotificationsSipImpl( - this, opSetBasicIM); - addSupportedOperationSet( - OperationSetTypingNotifications.class, - opSetTypingNotif); + // init typing notifications + this.opSetTypingNotif + = new OperationSetTypingNotificationsSipImpl( + this, opSetBasicIM); + addSupportedOperationSet( + OperationSetTypingNotifications.class, + opSetTypingNotif); - addSupportedOperationSet( - OperationSetInstantMessageTransform.class, - new OperationSetInstantMessageTransformImpl()); - } + addSupportedOperationSet( + OperationSetInstantMessageTransform.class, + new OperationSetInstantMessageTransformImpl()); + } - this.opSetSSAccountInfo = - new OperationSetServerStoredAccountInfoSipImpl(this); + this.opSetSSAccountInfo = + new OperationSetServerStoredAccountInfoSipImpl(this); - // Set the display name. - opSetSSAccountInfo.setOurDisplayName(ourDisplayName); + // Set the display name. + opSetSSAccountInfo.setOurDisplayName(ourDisplayName); - // init avatar - addSupportedOperationSet( - OperationSetServerStoredAccountInfo.class, - opSetSSAccountInfo); + // init avatar + addSupportedOperationSet( + OperationSetServerStoredAccountInfo.class, + opSetSSAccountInfo); - addSupportedOperationSet( - OperationSetAvatar.class, - new OperationSetAvatarSipImpl(this, opSetSSAccountInfo)); - } + addSupportedOperationSet( + OperationSetAvatar.class, + new OperationSetAvatarSipImpl(this, opSetSSAccountInfo)); // MWI is enabled by default if(accountID.getAccountPropertyBoolean( -- cgit v1.1 From be0540e2b75cc30d437daad88cb3467580eff0cc Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 28 Feb 2016 21:54:06 +0100 Subject: Normalize line endings See also #227 --- .../impl/protocol/sip/net/ProxyConnection.java | 360 +-- .../impl/protocol/sip/net/RFC5922Matcher.java | 418 +-- .../sysactivity/SystemActivityNotifications.java | 502 ++-- .../plugin/contactinfo/ContactInfoActivator.java | 416 +-- .../plugin/desktoputil/X509CertificatePanel.java | 976 +++---- .../communicator/plugin/otr/ScOtrEngineImpl.java | 2654 ++++++++++---------- .../muc/ChatRoomProviderWrapperListener.java | 80 +- .../service/protocol/AccountManager.java | 2166 ++++++++-------- .../PopupMessageHandlerSLick.java | 104 +- .../slick/protocol/sip/TestAutoProxyDetection.java | 970 +++---- 10 files changed, 4323 insertions(+), 4323 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/net/ProxyConnection.java b/src/net/java/sip/communicator/impl/protocol/sip/net/ProxyConnection.java index 99fcfb2..f7079f4 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/net/ProxyConnection.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/net/ProxyConnection.java @@ -1,180 +1,180 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.sip.net; - -import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_AUTO_CONFIG; - -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.sip.*; -import net.java.sip.communicator.service.dns.*; - -/** - * Abstract class for the determining the address for the SIP proxy. - * - * @author Ingo Bauersachs - */ -public abstract class ProxyConnection -{ - private List returnedAddresses = new LinkedList(); - - protected String transport; - protected InetSocketAddress socketAddress; - protected final SipAccountIDImpl account; - - /** - * Creates a new instance of this class. - * @param account the account of this SIP protocol instance - */ - protected ProxyConnection(SipAccountIDImpl account) - { - this.account = account; - } - - /** - * Gets the address to use for the next connection attempt. - * @return the address of the last lookup. - */ - public final InetSocketAddress getAddress() - { - return socketAddress; - } - - /** - * Gets the transport to use for the next connection attempt. - * @return the transport of the last lookup. - */ - public final String getTransport() - { - return transport; - } - - /** - * In case we are using an outbound proxy this method returns - * a suitable string for use with Router. - * The method returns null otherwise. - * - * @return the string of our outbound proxy if we are using one and - * null otherwise. - */ - public final String getOutboundProxyString() - { - if(socketAddress == null) - return null; - - InetAddress proxyAddress = socketAddress.getAddress(); - StringBuilder proxyStringBuffer - = new StringBuilder(proxyAddress.getHostAddress()); - - if(proxyAddress instanceof Inet6Address) - { - proxyStringBuffer.insert(0, '['); - proxyStringBuffer.append(']'); - } - - proxyStringBuffer.append(':'); - proxyStringBuffer.append(socketAddress.getPort()); - proxyStringBuffer.append('/'); - proxyStringBuffer.append(transport); - - return proxyStringBuffer.toString(); - } - - /** - * Compares an InetAddress against the active outbound proxy. The comparison - * is by reference, not equals. - * - * @param addressToTest The addres to test. - * @return True when the InetAddress is the same as the outbound proxy. - */ - public final boolean isSameInetAddress(InetAddress addressToTest) - { - // if the proxy is not yet initialized then this is not the provider - // that caused this comparison - if(socketAddress == null) - return false; - return addressToTest == socketAddress.getAddress(); - } - - /** - * Retrieves the next address to use from DNS. Duplicate results are - * suppressed. - * - * @return True if a new address is available through {@link #getAddress()}, - * false if the last address was reached. A new lookup from scratch - * can be started by calling {@link #reset()}. - * @throws DnssecException if there is a problem related to DNSSEC - */ - public final boolean getNextAddress() throws DnssecException - { - boolean result; - String key = null; - do - { - result = getNextAddressFromDns(); - if(result && socketAddress != null) - { - key = getOutboundProxyString(); - if(!returnedAddresses.contains(key)) - { - returnedAddresses.add(key); - break; - } - } - } - while(result && returnedAddresses.contains(key)); - return result; - } - - /** - * Implementations must use this method to get the next address, but do not - * have to care about duplicate addresses. - * - * @return True when a further address was available. - * @throws DnssecException when a DNSSEC validation failure occured. - */ - protected abstract boolean getNextAddressFromDns() - throws DnssecException; - - /** - * Resets the lookup to it's initial state. Overriders methods have to call - * this method through a super-call. - */ - public void reset() - { - returnedAddresses.clear(); - } - - /** - * Factory method to create a proxy connection based on the account settings - * of the protocol provider. - * - * @param pps the protocol provider that needs a SIP server connection. - * @return An instance of a derived class. - */ - public static ProxyConnection create(ProtocolProviderServiceSipImpl pps) - { - if (pps.getAccountID().getAccountPropertyBoolean(PROXY_AUTO_CONFIG, - true)) - return new AutoProxyConnection((SipAccountIDImpl) pps.getAccountID(), - pps.getDefaultTransport()); - else - return new ManualProxyConnection((SipAccountIDImpl) pps.getAccountID()); - } -} +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.sip.net; + +import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.PROXY_AUTO_CONFIG; + +import java.net.*; +import java.util.*; + +import net.java.sip.communicator.impl.protocol.sip.*; +import net.java.sip.communicator.service.dns.*; + +/** + * Abstract class for the determining the address for the SIP proxy. + * + * @author Ingo Bauersachs + */ +public abstract class ProxyConnection +{ + private List returnedAddresses = new LinkedList(); + + protected String transport; + protected InetSocketAddress socketAddress; + protected final SipAccountIDImpl account; + + /** + * Creates a new instance of this class. + * @param account the account of this SIP protocol instance + */ + protected ProxyConnection(SipAccountIDImpl account) + { + this.account = account; + } + + /** + * Gets the address to use for the next connection attempt. + * @return the address of the last lookup. + */ + public final InetSocketAddress getAddress() + { + return socketAddress; + } + + /** + * Gets the transport to use for the next connection attempt. + * @return the transport of the last lookup. + */ + public final String getTransport() + { + return transport; + } + + /** + * In case we are using an outbound proxy this method returns + * a suitable string for use with Router. + * The method returns null otherwise. + * + * @return the string of our outbound proxy if we are using one and + * null otherwise. + */ + public final String getOutboundProxyString() + { + if(socketAddress == null) + return null; + + InetAddress proxyAddress = socketAddress.getAddress(); + StringBuilder proxyStringBuffer + = new StringBuilder(proxyAddress.getHostAddress()); + + if(proxyAddress instanceof Inet6Address) + { + proxyStringBuffer.insert(0, '['); + proxyStringBuffer.append(']'); + } + + proxyStringBuffer.append(':'); + proxyStringBuffer.append(socketAddress.getPort()); + proxyStringBuffer.append('/'); + proxyStringBuffer.append(transport); + + return proxyStringBuffer.toString(); + } + + /** + * Compares an InetAddress against the active outbound proxy. The comparison + * is by reference, not equals. + * + * @param addressToTest The addres to test. + * @return True when the InetAddress is the same as the outbound proxy. + */ + public final boolean isSameInetAddress(InetAddress addressToTest) + { + // if the proxy is not yet initialized then this is not the provider + // that caused this comparison + if(socketAddress == null) + return false; + return addressToTest == socketAddress.getAddress(); + } + + /** + * Retrieves the next address to use from DNS. Duplicate results are + * suppressed. + * + * @return True if a new address is available through {@link #getAddress()}, + * false if the last address was reached. A new lookup from scratch + * can be started by calling {@link #reset()}. + * @throws DnssecException if there is a problem related to DNSSEC + */ + public final boolean getNextAddress() throws DnssecException + { + boolean result; + String key = null; + do + { + result = getNextAddressFromDns(); + if(result && socketAddress != null) + { + key = getOutboundProxyString(); + if(!returnedAddresses.contains(key)) + { + returnedAddresses.add(key); + break; + } + } + } + while(result && returnedAddresses.contains(key)); + return result; + } + + /** + * Implementations must use this method to get the next address, but do not + * have to care about duplicate addresses. + * + * @return True when a further address was available. + * @throws DnssecException when a DNSSEC validation failure occured. + */ + protected abstract boolean getNextAddressFromDns() + throws DnssecException; + + /** + * Resets the lookup to it's initial state. Overriders methods have to call + * this method through a super-call. + */ + public void reset() + { + returnedAddresses.clear(); + } + + /** + * Factory method to create a proxy connection based on the account settings + * of the protocol provider. + * + * @param pps the protocol provider that needs a SIP server connection. + * @return An instance of a derived class. + */ + public static ProxyConnection create(ProtocolProviderServiceSipImpl pps) + { + if (pps.getAccountID().getAccountPropertyBoolean(PROXY_AUTO_CONFIG, + true)) + return new AutoProxyConnection((SipAccountIDImpl) pps.getAccountID(), + pps.getDefaultTransport()); + else + return new ManualProxyConnection((SipAccountIDImpl) pps.getAccountID()); + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/sip/net/RFC5922Matcher.java b/src/net/java/sip/communicator/impl/protocol/sip/net/RFC5922Matcher.java index 0027ec5..262b717 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/net/RFC5922Matcher.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/net/RFC5922Matcher.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,211 +15,211 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.impl.protocol.sip.net; - -import java.security.cert.*; -import java.text.*; -import java.util.*; -import java.util.regex.*; - -import javax.sip.address.*; - -import net.java.sip.communicator.impl.protocol.sip.*; -import net.java.sip.communicator.service.certificate.*; -import net.java.sip.communicator.util.*; - -/** - * Matcher that extracts certificate identities according to RFC5922, Section - * 7.1 and compares them with the rules from Section 7.2 and 7.3. - * @see #PNAME_STRICT_RFC5922 for wildcard handling; the default is false - * - * @author Ingo Bauersachs - */ -public class RFC5922Matcher - implements CertificateMatcher -{ - /** - * When set to true, enables strict validation of the hostname according to - * RFC5922 Section - * 7.2 - */ - public final static String PNAME_STRICT_RFC5922 = - "net.java.sip.communicator.sip.tls.STRICT_RFC5922"; - - private ProtocolProviderServiceSipImpl provider; - - /** - * Creates a new instance of this class. - * @param provider The SIP Provider to which this matcher belongs. - */ - public RFC5922Matcher(ProtocolProviderServiceSipImpl provider) - { - this.provider = provider; - } - - /** Our class logger. */ - private static final Logger logger = Logger - .getLogger(CertificateMatcher.class); - - /* - * (non-Javadoc) - * - * @see - * net.java.sip.communicator.service.certificate.CertificateMatcher#verify - * (java.lang.Iterable, java.security.cert.X509Certificate) - */ - public void verify(Iterable identitiesToTest, X509Certificate cert) - throws CertificateException - { - boolean strict = SipActivator.getConfigurationService() - .getBoolean(PNAME_STRICT_RFC5922, false); - - // if any of the identities is contained in the certificate we're good - boolean oneMatched = false; - Iterable certIdentities = extractCertIdentities(cert); - for (String identity : identitiesToTest) - { - // check if the intended hostname is contained in one of the - // hostnames of the certificate according to - // http://tools.ietf.org/html/rfc5922#section-7.2 - for(String dnsName : certIdentities) - { - try - { - if(NetworkUtils.compareDnsNames(dnsName, identity) == 0) - { - // one of the hostnames matched, we're good to go - return; - } - - if(!strict - // is a wildcard name - && dnsName.startsWith("*.") - // contains at least two dots (*.example.com) - && identity.indexOf(".") < identity.lastIndexOf(".") - // compare *.example.com stripped to example.com with - // - foo.example.com stripped to example.com - // - foo.bar.example.com to bar.example.com - && NetworkUtils.compareDnsNames( - dnsName.substring(2), - identity.substring(identity.indexOf(".")+1)) == 0) - { - // the wildcard matched, we're good to go - return; - } - } - catch (ParseException e) - {} // we don't care - this hostname did not match - } - } - if (!oneMatched) - throw new CertificateException("None of <" + identitiesToTest - + "> matched by the rules of RFC5922 to the cert with CN=" - + cert.getSubjectDN()); - } - - private Iterable extractCertIdentities(X509Certificate cert) - { - List certIdentities = new ArrayList(); - Collection> subjAltNames = null; - try - { - subjAltNames = cert.getSubjectAlternativeNames(); - } - catch (CertificateParsingException ex) - { - logger.error("Error parsing TLS certificate", ex); - } - // subjAltName types are defined in rfc2459 - final Integer dnsNameType = 2; - final Integer uriNameType = 6; - if (subjAltNames != null) - { - if (logger.isDebugEnabled()) - logger.debug("found subjAltNames: " + subjAltNames); - - // First look for a URI in the subjectAltName field - for (List altName : subjAltNames) - { - // 0th position is the alt name type - // 1st position is the alt name data - if (altName.get(0).equals(uriNameType)) - { - SipURI altNameUri; - try - { - altNameUri = - provider.getAddressFactory().createSipURI( - (String) altName.get(1)); - // only sip URIs are allowed - if (!"sip".equals(altNameUri.getScheme())) - continue; - // user certificates are not allowed - if (altNameUri.getUser() != null) - continue; - String altHostName = altNameUri.getHost(); - if (logger.isDebugEnabled()) - { - logger.debug("found uri " + altName.get(1) - + ", hostName " + altHostName); - } - certIdentities.add(altHostName); - } - catch (ParseException e) - { - logger.error("certificate contains invalid uri: " - + altName.get(1)); - } - } - - } - // DNS An implementation MUST accept a domain name system - // identifier as a SIP domain identity if and only if no other - // identity is found that matches the "sip" URI type described - // above. - if (certIdentities.isEmpty()) - { - for (List altName : subjAltNames) - { - if (altName.get(0).equals(dnsNameType)) - { - if (logger.isDebugEnabled()) - logger.debug("found dns " + altName.get(1)); - certIdentities.add(altName.get(1).toString()); - } - } - } - } - else - { - // If and only if the subjectAltName does not appear in the - // certificate, the implementation MAY examine the CN field of the - // certificate. If a valid DNS name is found there, the - // implementation MAY accept this value as a SIP domain identity. - String dname = cert.getSubjectDN().getName(); - String cname = ""; - try - { - Pattern EXTRACT_CN = - Pattern.compile(".*CN\\s*=\\s*([\\w*\\.]+).*"); - Matcher matcher = EXTRACT_CN.matcher(dname); - if (matcher.matches()) - { - cname = matcher.group(1); - if (logger.isDebugEnabled()) - { - logger.debug("found CN: " + cname + " from DN: " - + dname); - } - certIdentities.add(cname); - } - } - catch (Exception ex) - { - logger.error("exception while extracting CN", ex); - } - } - return certIdentities; - } -} +package net.java.sip.communicator.impl.protocol.sip.net; + +import java.security.cert.*; +import java.text.*; +import java.util.*; +import java.util.regex.*; + +import javax.sip.address.*; + +import net.java.sip.communicator.impl.protocol.sip.*; +import net.java.sip.communicator.service.certificate.*; +import net.java.sip.communicator.util.*; + +/** + * Matcher that extracts certificate identities according to RFC5922, Section + * 7.1 and compares them with the rules from Section 7.2 and 7.3. + * @see #PNAME_STRICT_RFC5922 for wildcard handling; the default is false + * + * @author Ingo Bauersachs + */ +public class RFC5922Matcher + implements CertificateMatcher +{ + /** + * When set to true, enables strict validation of the hostname according to + * RFC5922 Section + * 7.2 + */ + public final static String PNAME_STRICT_RFC5922 = + "net.java.sip.communicator.sip.tls.STRICT_RFC5922"; + + private ProtocolProviderServiceSipImpl provider; + + /** + * Creates a new instance of this class. + * @param provider The SIP Provider to which this matcher belongs. + */ + public RFC5922Matcher(ProtocolProviderServiceSipImpl provider) + { + this.provider = provider; + } + + /** Our class logger. */ + private static final Logger logger = Logger + .getLogger(CertificateMatcher.class); + + /* + * (non-Javadoc) + * + * @see + * net.java.sip.communicator.service.certificate.CertificateMatcher#verify + * (java.lang.Iterable, java.security.cert.X509Certificate) + */ + public void verify(Iterable identitiesToTest, X509Certificate cert) + throws CertificateException + { + boolean strict = SipActivator.getConfigurationService() + .getBoolean(PNAME_STRICT_RFC5922, false); + + // if any of the identities is contained in the certificate we're good + boolean oneMatched = false; + Iterable certIdentities = extractCertIdentities(cert); + for (String identity : identitiesToTest) + { + // check if the intended hostname is contained in one of the + // hostnames of the certificate according to + // http://tools.ietf.org/html/rfc5922#section-7.2 + for(String dnsName : certIdentities) + { + try + { + if(NetworkUtils.compareDnsNames(dnsName, identity) == 0) + { + // one of the hostnames matched, we're good to go + return; + } + + if(!strict + // is a wildcard name + && dnsName.startsWith("*.") + // contains at least two dots (*.example.com) + && identity.indexOf(".") < identity.lastIndexOf(".") + // compare *.example.com stripped to example.com with + // - foo.example.com stripped to example.com + // - foo.bar.example.com to bar.example.com + && NetworkUtils.compareDnsNames( + dnsName.substring(2), + identity.substring(identity.indexOf(".")+1)) == 0) + { + // the wildcard matched, we're good to go + return; + } + } + catch (ParseException e) + {} // we don't care - this hostname did not match + } + } + if (!oneMatched) + throw new CertificateException("None of <" + identitiesToTest + + "> matched by the rules of RFC5922 to the cert with CN=" + + cert.getSubjectDN()); + } + + private Iterable extractCertIdentities(X509Certificate cert) + { + List certIdentities = new ArrayList(); + Collection> subjAltNames = null; + try + { + subjAltNames = cert.getSubjectAlternativeNames(); + } + catch (CertificateParsingException ex) + { + logger.error("Error parsing TLS certificate", ex); + } + // subjAltName types are defined in rfc2459 + final Integer dnsNameType = 2; + final Integer uriNameType = 6; + if (subjAltNames != null) + { + if (logger.isDebugEnabled()) + logger.debug("found subjAltNames: " + subjAltNames); + + // First look for a URI in the subjectAltName field + for (List altName : subjAltNames) + { + // 0th position is the alt name type + // 1st position is the alt name data + if (altName.get(0).equals(uriNameType)) + { + SipURI altNameUri; + try + { + altNameUri = + provider.getAddressFactory().createSipURI( + (String) altName.get(1)); + // only sip URIs are allowed + if (!"sip".equals(altNameUri.getScheme())) + continue; + // user certificates are not allowed + if (altNameUri.getUser() != null) + continue; + String altHostName = altNameUri.getHost(); + if (logger.isDebugEnabled()) + { + logger.debug("found uri " + altName.get(1) + + ", hostName " + altHostName); + } + certIdentities.add(altHostName); + } + catch (ParseException e) + { + logger.error("certificate contains invalid uri: " + + altName.get(1)); + } + } + + } + // DNS An implementation MUST accept a domain name system + // identifier as a SIP domain identity if and only if no other + // identity is found that matches the "sip" URI type described + // above. + if (certIdentities.isEmpty()) + { + for (List altName : subjAltNames) + { + if (altName.get(0).equals(dnsNameType)) + { + if (logger.isDebugEnabled()) + logger.debug("found dns " + altName.get(1)); + certIdentities.add(altName.get(1).toString()); + } + } + } + } + else + { + // If and only if the subjectAltName does not appear in the + // certificate, the implementation MAY examine the CN field of the + // certificate. If a valid DNS name is found there, the + // implementation MAY accept this value as a SIP domain identity. + String dname = cert.getSubjectDN().getName(); + String cname = ""; + try + { + Pattern EXTRACT_CN = + Pattern.compile(".*CN\\s*=\\s*([\\w*\\.]+).*"); + Matcher matcher = EXTRACT_CN.matcher(dname); + if (matcher.matches()) + { + cname = matcher.group(1); + if (logger.isDebugEnabled()) + { + logger.debug("found CN: " + cname + " from DN: " + + dname); + } + certIdentities.add(cname); + } + } + catch (Exception ex) + { + logger.error("exception while extracting CN", ex); + } + } + return certIdentities; + } +} diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java index f4f6ede..6d9edda 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java @@ -1,251 +1,251 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.sysactivity; - -import net.java.sip.communicator.util.Logger; -import org.jitsi.util.*; - -/** - * @author Damian Minkov - */ -public class SystemActivityNotifications -{ - /** - * The Logger used by the SystemActivityNotifications - * class to log debugging information. - */ - private static final Logger logger - = Logger.getLogger(SystemActivityNotifications.class); - - /** - * Computer display has stand by. - */ - public static final int NOTIFY_DISPLAY_SLEEP = 2; - - /** - * Computer display wakes up after stand by. - */ - public static final int NOTIFY_DISPLAY_WAKE = 3; - - /** - * A change in dns configuration has occurred. - */ - public static final int NOTIFY_DNS_CHANGE = 10; - - /** - * All processes have been informed about ending session, now notify for - * the actual end session. - */ - public static final int NOTIFY_ENDSESSION = 12; - - /** - * A change in network configuration has occurred. - */ - public static final int NOTIFY_NETWORK_CHANGE = 9; - - /** - * Notifies for start of process of ending desktop session, - * logoff or shutdown. - */ - public static final int NOTIFY_QUERY_ENDSESSION = 11; - - /** - * Screen has been locked. - */ - public static final int NOTIFY_SCREEN_LOCKED = 7; - - /** - * Screen has been unlocked. - */ - public static final int NOTIFY_SCREEN_UNLOCKED = 8; - - /** - * Screensaver has been started. - */ - public static final int NOTIFY_SCREENSAVER_START = 4; - - /** - * Screensaver has been stopped. - */ - public static final int NOTIFY_SCREENSAVER_STOP = 6; - - /** - * Screensaver will stop. - */ - public static final int NOTIFY_SCREENSAVER_WILL_STOP = 5; - - /** - * Notify that computers is going to sleep. - */ - public static final int NOTIFY_SLEEP = 0; - - /** - * Notify that computer is wakeing up after stand by. - */ - public static final int NOTIFY_WAKE = 1; - - /** - * The native instance. - */ - private static long ptr; - - /** - * Init native library. - */ - static - { - try - { - // Don't load native library on Android to prevent the exception - if(!org.jitsi.util.OSUtils.IS_ANDROID) - { - JNIUtils.loadLibrary("sysactivitynotifications", - SystemActivityNotifications.class.getClassLoader()); - - ptr = allocAndInit(); - if (ptr == -1) - ptr = 0; - } - } - catch (Throwable t) - { - if (t instanceof ThreadDeath) - throw (ThreadDeath) t; - else - logger.warn("Failed to initialize native counterpart", t); - } - } - - /** - * Allocate native resources and gets a pointer. - * - * @return - */ - private static native long allocAndInit(); - - /** - * Returns the when was last input in milliseconds. The time when there was - * any activity on the computer. - * - * @return the last input in milliseconds - */ - public static native long getLastInput(); - - /** - * Whether native library is loaded. - * - * @return whether native library is loaded. - */ - public static boolean isLoaded() - { - return (ptr != 0); - } - - /** - * Release native resources. - * - * @param ptr - */ - private static native void release(long ptr); - - /** - * Sets notifier delegate. - * - * @param ptr - * @param delegate - */ - public static native void setDelegate( - long ptr, - NotificationsDelegate delegate); - - /** - * Sets delegate. - * - * @param delegate - */ - public static void setDelegate(NotificationsDelegate delegate) - { - if (ptr != 0) - setDelegate(ptr, delegate); - } - - /** - * Start. - */ - public static void start() - { - if (ptr != 0) - start(ptr); - } - - /** - * Start processing. - * - * @param ptr - */ - private static native void start(long ptr); - - /** - * Stop. - */ - public static void stop() - { - if (ptr != 0) - { - stop(ptr); - release(ptr); - ptr = 0; - } - } - - /** - * Stop processing. - * - * @param ptr - */ - private static native void stop(long ptr); - - /** - * Delegate class to be notified about changes. - */ - public interface NotificationsDelegate - { - /** - * Callback method when receiving notifications. - * - * @param type - */ - public void notify(int type); - - /** - * Callback method when receiving special network notifications. - * - * @param family family of network change (ipv6, ipv4) - * @param luidIndex unique index of interface - * @param name name of the interface - * @param type of the interface - * @param connected whether interface is connected or not. - */ - public void notifyNetworkChange( - int family, - long luidIndex, - String name, - long type, - boolean connected); - } -} +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.sysactivity; + +import net.java.sip.communicator.util.Logger; +import org.jitsi.util.*; + +/** + * @author Damian Minkov + */ +public class SystemActivityNotifications +{ + /** + * The Logger used by the SystemActivityNotifications + * class to log debugging information. + */ + private static final Logger logger + = Logger.getLogger(SystemActivityNotifications.class); + + /** + * Computer display has stand by. + */ + public static final int NOTIFY_DISPLAY_SLEEP = 2; + + /** + * Computer display wakes up after stand by. + */ + public static final int NOTIFY_DISPLAY_WAKE = 3; + + /** + * A change in dns configuration has occurred. + */ + public static final int NOTIFY_DNS_CHANGE = 10; + + /** + * All processes have been informed about ending session, now notify for + * the actual end session. + */ + public static final int NOTIFY_ENDSESSION = 12; + + /** + * A change in network configuration has occurred. + */ + public static final int NOTIFY_NETWORK_CHANGE = 9; + + /** + * Notifies for start of process of ending desktop session, + * logoff or shutdown. + */ + public static final int NOTIFY_QUERY_ENDSESSION = 11; + + /** + * Screen has been locked. + */ + public static final int NOTIFY_SCREEN_LOCKED = 7; + + /** + * Screen has been unlocked. + */ + public static final int NOTIFY_SCREEN_UNLOCKED = 8; + + /** + * Screensaver has been started. + */ + public static final int NOTIFY_SCREENSAVER_START = 4; + + /** + * Screensaver has been stopped. + */ + public static final int NOTIFY_SCREENSAVER_STOP = 6; + + /** + * Screensaver will stop. + */ + public static final int NOTIFY_SCREENSAVER_WILL_STOP = 5; + + /** + * Notify that computers is going to sleep. + */ + public static final int NOTIFY_SLEEP = 0; + + /** + * Notify that computer is wakeing up after stand by. + */ + public static final int NOTIFY_WAKE = 1; + + /** + * The native instance. + */ + private static long ptr; + + /** + * Init native library. + */ + static + { + try + { + // Don't load native library on Android to prevent the exception + if(!org.jitsi.util.OSUtils.IS_ANDROID) + { + JNIUtils.loadLibrary("sysactivitynotifications", + SystemActivityNotifications.class.getClassLoader()); + + ptr = allocAndInit(); + if (ptr == -1) + ptr = 0; + } + } + catch (Throwable t) + { + if (t instanceof ThreadDeath) + throw (ThreadDeath) t; + else + logger.warn("Failed to initialize native counterpart", t); + } + } + + /** + * Allocate native resources and gets a pointer. + * + * @return + */ + private static native long allocAndInit(); + + /** + * Returns the when was last input in milliseconds. The time when there was + * any activity on the computer. + * + * @return the last input in milliseconds + */ + public static native long getLastInput(); + + /** + * Whether native library is loaded. + * + * @return whether native library is loaded. + */ + public static boolean isLoaded() + { + return (ptr != 0); + } + + /** + * Release native resources. + * + * @param ptr + */ + private static native void release(long ptr); + + /** + * Sets notifier delegate. + * + * @param ptr + * @param delegate + */ + public static native void setDelegate( + long ptr, + NotificationsDelegate delegate); + + /** + * Sets delegate. + * + * @param delegate + */ + public static void setDelegate(NotificationsDelegate delegate) + { + if (ptr != 0) + setDelegate(ptr, delegate); + } + + /** + * Start. + */ + public static void start() + { + if (ptr != 0) + start(ptr); + } + + /** + * Start processing. + * + * @param ptr + */ + private static native void start(long ptr); + + /** + * Stop. + */ + public static void stop() + { + if (ptr != 0) + { + stop(ptr); + release(ptr); + ptr = 0; + } + } + + /** + * Stop processing. + * + * @param ptr + */ + private static native void stop(long ptr); + + /** + * Delegate class to be notified about changes. + */ + public interface NotificationsDelegate + { + /** + * Callback method when receiving notifications. + * + * @param type + */ + public void notify(int type); + + /** + * Callback method when receiving special network notifications. + * + * @param family family of network change (ipv6, ipv4) + * @param luidIndex unique index of interface + * @param name name of the interface + * @param type of the interface + * @param connected whether interface is connected or not. + */ + public void notifyNetworkChange( + int family, + long luidIndex, + String name, + long type, + boolean connected); + } +} diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java index ce1fc18..7783de8 100644 --- a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java +++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java @@ -1,208 +1,208 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.contactinfo; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * The Activator of the Contact Info bundle. - * - * @author Adam Goldstein - * @author Yana Stamcheva - */ -public class ContactInfoActivator implements BundleActivator -{ - private Logger logger = Logger.getLogger(ContactInfoActivator.class); - - /** - * Indicates if the contact info button is enabled in the chat window. - */ - private static final String ENABLED_IN_CHAT_WINDOW_PROP - = "net.java.sip.communicator.plugin.contactinfo." + - "ENABLED_IN_CHAT_WINDOW_PROP"; - - /** - * Indicates if the contact info button is enabled in the call window. - */ - private static final String ENABLED_IN_CALL_WINDOW_PROP - = "net.java.sip.communicator.plugin.contactinfo." + - "ENABLED_IN_CALL_WINDOW_PROP"; - - private static BrowserLauncherService browserLauncherService; - - /** - * The image loader service implementation. - */ - private static ImageLoaderService imageLoaderService = null; - - /** - * The contact list service implementation. - */ - private static MetaContactListService metaCListService; - - static BundleContext bundleContext; - - /** - * Starts this bundle. - */ - public void start(BundleContext bc) throws Exception - { - bundleContext = bc; - - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new ContactInfoPluginComponentFactory( - Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU), - containerFilter); - - if(getConfigService().getBoolean(ENABLED_IN_CHAT_WINDOW_PROP, false)) - { - containerFilter = new Hashtable(); - containerFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_CHAT_TOOL_BAR.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new ContactInfoPluginComponentFactory( - Container.CONTAINER_CHAT_TOOL_BAR), - containerFilter); - } - - if(getConfigService().getBoolean(ENABLED_IN_CALL_WINDOW_PROP, false)) - { - containerFilter = new Hashtable(); - containerFilter.put( - Container.CONTAINER_ID, - Container.CONTAINER_CALL_DIALOG.getID()); - - bundleContext.registerService( - PluginComponentFactory.class.getName(), - new ContactInfoPluginComponentFactory( - Container.CONTAINER_CALL_DIALOG), - containerFilter); - } - - if (logger.isInfoEnabled()) - logger.info("CONTACT INFO... [REGISTERED]"); - } - - public void stop(BundleContext bc) throws Exception - { - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - ServiceReference serviceReference = bundleContext - .getServiceReference(BrowserLauncherService.class.getName()); - - browserLauncherService = (BrowserLauncherService) bundleContext - .getService(serviceReference); - } - - return browserLauncherService; - } - - /** - * Returns the imageLoaderService instance, if missing query osgi for it. - * @return the imageLoaderService. - */ - public static ImageLoaderService getImageLoaderService() - { - if(imageLoaderService == null) - { - imageLoaderService - = ServiceUtils.getService( - bundleContext, - ImageLoaderService.class); - } - - return imageLoaderService; - } - - /** - * Returns the MetaContactListService obtained from the bundle - * context. - * @return the MetaContactListService obtained from the bundle - * context - */ - public static MetaContactListService getContactListService() - { - if (metaCListService == null) - { - metaCListService - = ServiceUtils.getService( - bundleContext, - MetaContactListService.class); - } - return metaCListService; - } - - /** - * Returns a reference to a ConfigurationService implementation currently - * registered in the bundle context or null if no such implementation was - * found. - * - * @return a currently valid implementation of the ConfigurationService. - */ - public static ConfigurationService getConfigService() - { - return ServiceUtils.getService(bundleContext, - ConfigurationService.class); - } - - /** - * Contact info create factory. - */ - private class ContactInfoPluginComponentFactory - extends PluginComponentFactory - { - ContactInfoPluginComponentFactory(Container c) - { - super(c); - } - - @Override - protected PluginComponent getPluginInstance() - { - return new ContactInfoMenuItem(getContainer(), this); - } - } -} +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.plugin.contactinfo; + +import java.util.*; + +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * The Activator of the Contact Info bundle. + * + * @author Adam Goldstein + * @author Yana Stamcheva + */ +public class ContactInfoActivator implements BundleActivator +{ + private Logger logger = Logger.getLogger(ContactInfoActivator.class); + + /** + * Indicates if the contact info button is enabled in the chat window. + */ + private static final String ENABLED_IN_CHAT_WINDOW_PROP + = "net.java.sip.communicator.plugin.contactinfo." + + "ENABLED_IN_CHAT_WINDOW_PROP"; + + /** + * Indicates if the contact info button is enabled in the call window. + */ + private static final String ENABLED_IN_CALL_WINDOW_PROP + = "net.java.sip.communicator.plugin.contactinfo." + + "ENABLED_IN_CALL_WINDOW_PROP"; + + private static BrowserLauncherService browserLauncherService; + + /** + * The image loader service implementation. + */ + private static ImageLoaderService imageLoaderService = null; + + /** + * The contact list service implementation. + */ + private static MetaContactListService metaCListService; + + static BundleContext bundleContext; + + /** + * Starts this bundle. + */ + public void start(BundleContext bc) throws Exception + { + bundleContext = bc; + + Hashtable containerFilter + = new Hashtable(); + containerFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new ContactInfoPluginComponentFactory( + Container.CONTAINER_CONTACT_RIGHT_BUTTON_MENU), + containerFilter); + + if(getConfigService().getBoolean(ENABLED_IN_CHAT_WINDOW_PROP, false)) + { + containerFilter = new Hashtable(); + containerFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_CHAT_TOOL_BAR.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new ContactInfoPluginComponentFactory( + Container.CONTAINER_CHAT_TOOL_BAR), + containerFilter); + } + + if(getConfigService().getBoolean(ENABLED_IN_CALL_WINDOW_PROP, false)) + { + containerFilter = new Hashtable(); + containerFilter.put( + Container.CONTAINER_ID, + Container.CONTAINER_CALL_DIALOG.getID()); + + bundleContext.registerService( + PluginComponentFactory.class.getName(), + new ContactInfoPluginComponentFactory( + Container.CONTAINER_CALL_DIALOG), + containerFilter); + } + + if (logger.isInfoEnabled()) + logger.info("CONTACT INFO... [REGISTERED]"); + } + + public void stop(BundleContext bc) throws Exception + { + } + + /** + * Returns the BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService obtained from the bundle + * context + */ + public static BrowserLauncherService getBrowserLauncher() + { + if (browserLauncherService == null) + { + ServiceReference serviceReference = bundleContext + .getServiceReference(BrowserLauncherService.class.getName()); + + browserLauncherService = (BrowserLauncherService) bundleContext + .getService(serviceReference); + } + + return browserLauncherService; + } + + /** + * Returns the imageLoaderService instance, if missing query osgi for it. + * @return the imageLoaderService. + */ + public static ImageLoaderService getImageLoaderService() + { + if(imageLoaderService == null) + { + imageLoaderService + = ServiceUtils.getService( + bundleContext, + ImageLoaderService.class); + } + + return imageLoaderService; + } + + /** + * Returns the MetaContactListService obtained from the bundle + * context. + * @return the MetaContactListService obtained from the bundle + * context + */ + public static MetaContactListService getContactListService() + { + if (metaCListService == null) + { + metaCListService + = ServiceUtils.getService( + bundleContext, + MetaContactListService.class); + } + return metaCListService; + } + + /** + * Returns a reference to a ConfigurationService implementation currently + * registered in the bundle context or null if no such implementation was + * found. + * + * @return a currently valid implementation of the ConfigurationService. + */ + public static ConfigurationService getConfigService() + { + return ServiceUtils.getService(bundleContext, + ConfigurationService.class); + } + + /** + * Contact info create factory. + */ + private class ContactInfoPluginComponentFactory + extends PluginComponentFactory + { + ContactInfoPluginComponentFactory(Container c) + { + super(c); + } + + @Override + protected PluginComponent getPluginInstance() + { + return new ContactInfoMenuItem(getContainer(), this); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java index a1284cd..9d13fe2 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,490 +15,490 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.desktoputil; - -import java.awt.*; -import java.security.*; -import java.security.cert.*; -import java.security.cert.Certificate; -import java.security.interfaces.*; -import java.util.*; - -import javax.naming.*; -import javax.naming.ldap.*; -import javax.security.auth.x500.*; -import javax.swing.*; -import javax.swing.border.*; -import javax.swing.event.*; -import javax.swing.text.*; -import javax.swing.tree.*; - -import org.jitsi.service.resources.*; - -/** - * Panel that shows the content of an X509Certificate. - */ -public class X509CertificatePanel - extends TransparentPanel -{ - private static final long serialVersionUID = -8368302061995971947L; - - private final JEditorPane infoTextPane = new JEditorPane(); - - private final ResourceManagementService R - = DesktopUtilActivator.getResources(); - - /** - * Constructs a X509 certificate panel from a single certificate. - * If a chain is available instead use the second constructor. - * This constructor is kept for backwards compatibility and for convenience - * when there is only one certificate of interest. - * - * @param certificate X509Certificate object - */ - public X509CertificatePanel(Certificate certificate) - { - this(new Certificate[] - { - certificate - }); - } - - /** - * Constructs a X509 certificate panel. - * - * @param certificates X509Certificate objects - */ - public X509CertificatePanel(Certificate[] certificates) - { - setLayout(new BorderLayout(5, 5)); - - // Certificate chain list - TransparentPanel topPanel = new TransparentPanel(new BorderLayout()); - topPanel.add(new JLabel("" - + R.getI18NString("service.gui.CERT_INFO_CHAIN") - + ""), BorderLayout.NORTH); - - DefaultMutableTreeNode top = new DefaultMutableTreeNode(); - DefaultMutableTreeNode previous = top; - for (int i = certificates.length - 1; i >= 0; i--) - { - Certificate cert = certificates[i]; - DefaultMutableTreeNode next = new DefaultMutableTreeNode(cert); - previous.add(next); - previous = next; - } - JTree tree = new JTree(top); - tree.setBorder(new BevelBorder(BevelBorder.LOWERED)); - tree.setRootVisible(false); - tree.setExpandsSelectedPaths(true); - tree.getSelectionModel().setSelectionMode( - TreeSelectionModel.SINGLE_TREE_SELECTION); - tree.setCellRenderer(new DefaultTreeCellRenderer() - { - - @Override - public Component getTreeCellRendererComponent(JTree tree, - Object value, boolean sel, boolean expanded, boolean leaf, - int row, boolean hasFocus) - { - JLabel component = (JLabel) super.getTreeCellRendererComponent( - tree, value, sel, expanded, leaf, row, hasFocus); - if (value instanceof DefaultMutableTreeNode) - { - Object o = ((DefaultMutableTreeNode) value).getUserObject(); - if (o instanceof X509Certificate) - { - component.setText( - getSimplifiedName((X509Certificate) o)); - } - else - { - // We don't know how to represent this certificate type, - // let's use the first 20 characters - String text = o.toString(); - if (text.length() > 20) - { - text = text.substring(0, 20); - } - component.setText(text); - } - } - return component; - } - - }); - tree.getSelectionModel().addTreeSelectionListener( - new TreeSelectionListener() - { - - @Override - public void valueChanged(TreeSelectionEvent e) - { - valueChangedPerformed(e); - } - }); - tree.setSelectionPath(new TreePath((( - (DefaultTreeModel)tree.getModel()).getPathToRoot(previous)))); - topPanel.add(tree, BorderLayout.CENTER); - - add(topPanel, BorderLayout.NORTH); - - // Certificate details pane - Caret caret = infoTextPane.getCaret(); - if (caret instanceof DefaultCaret) - { - ((DefaultCaret) caret).setUpdatePolicy(DefaultCaret.NEVER_UPDATE); - } - - /* - * Make JEditorPane respect our default font because we will be using it - * to just display text. - */ - infoTextPane.putClientProperty( - JEditorPane.HONOR_DISPLAY_PROPERTIES, - true); - - infoTextPane.setOpaque(false); - infoTextPane.setEditable(false); - infoTextPane.setContentType("text/html"); - infoTextPane.setText(toString(certificates[0])); - - final JScrollPane certScroll = new JScrollPane(infoTextPane); - certScroll.setPreferredSize(new Dimension(300, 500)); - add(certScroll, BorderLayout.CENTER); - } - - /** - * Creates a String representation of the given object. - * @param certificate to print - * @return the String representation - */ - private String toString(Object certificate) - { - final StringBuilder sb = new StringBuilder(); - sb.append("\n"); - - if (certificate instanceof X509Certificate) - { - renderX509(sb, (X509Certificate) certificate); - } - else - { - sb.append("

    \n");
    -            sb.append(certificate.toString());
    -            sb.append("
    \n"); - } - - sb.append(""); - return sb.toString(); - } - - /** - * Appends an HTML representation of the given X509Certificate. - * @param sb StringBuilder to append to - * @param certificate to print - */ - private void renderX509(StringBuilder sb, X509Certificate certificate) - { - X500Principal issuer = certificate.getIssuerX500Principal(); - X500Principal subject = certificate.getSubjectX500Principal(); - - sb.append("\n"); - - // subject - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_TO")); - try - { - for(Rdn name : new LdapName(subject.getName()).getRdns()) - { - String nameType = name.getType(); - String lblKey = "service.gui.CERT_INFO_" + nameType; - String lbl = R.getI18NString(lblKey); - - if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) - lbl = nameType; - - final String value; - Object nameValue = name.getValue(); - - if (nameValue instanceof byte[]) - { - byte[] nameValueAsByteArray = (byte[]) nameValue; - - value - = getHex(nameValueAsByteArray) + " (" - + new String(nameValueAsByteArray) + ")"; - } - else - value = nameValue.toString(); - - addField(sb, lbl, value); - } - } - catch (InvalidNameException ine) - { - addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), - subject.getName()); - } - - // issuer - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_BY")); - try - { - for(Rdn name : new LdapName(issuer.getName()).getRdns()) - { - String nameType = name.getType(); - String lblKey = "service.gui.CERT_INFO_" + nameType; - String lbl = R.getI18NString(lblKey); - - if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) - lbl = nameType; - - final String value; - Object nameValue = name.getValue(); - - if (nameValue instanceof byte[]) - { - byte[] nameValueAsByteArray = (byte[]) nameValue; - - value - = getHex(nameValueAsByteArray) + " (" - + new String(nameValueAsByteArray) + ")"; - } - else - value = nameValue.toString(); - - addField(sb, lbl, value); - } - } - catch (InvalidNameException ine) - { - addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), - issuer.getName()); - } - - // validity - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_VALIDITY")); - addField(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_ON"), - certificate.getNotBefore().toString()); - addField(sb, R.getI18NString("service.gui.CERT_INFO_EXPIRES_ON"), - certificate.getNotAfter().toString()); - - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_FINGERPRINTS")); - try - { - String sha1String = getThumbprint(certificate, "SHA1"); - String md5String = getThumbprint(certificate, "MD5"); - - addField(sb, "SHA1:", sha1String); - addField(sb, "MD5:", md5String); - } - catch (CertificateException e) - { - // do nothing as we cannot show this value - } - - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_CERT_DETAILS")); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_SER_NUM"), - certificate.getSerialNumber().toString()); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_VER"), - String.valueOf(certificate.getVersion())); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN_ALG"), - String.valueOf(certificate.getSigAlgName())); - - addTitle(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY_INFO")); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_ALG"), - certificate.getPublicKey().getAlgorithm()); - - if(certificate.getPublicKey().getAlgorithm().equals("RSA")) - { - RSAPublicKey key = (RSAPublicKey)certificate.getPublicKey(); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY"), - R.getI18NString( - "service.gui.CERT_INFO_KEY_BYTES_PRINT", - new String[]{ - String.valueOf(key.getModulus().toByteArray().length-1), - key.getModulus().toString(16) - })); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_EXP"), - key.getPublicExponent().toString()); - - addField(sb, R.getI18NString("service.gui.CERT_INFO_KEY_SIZE"), - R.getI18NString( - "service.gui.CERT_INFO_KEY_BITS_PRINT", - new String[]{ - String.valueOf(key.getModulus().bitLength())})); - } - else if(certificate.getPublicKey().getAlgorithm().equals("DSA")) - { - DSAPublicKey key = - (DSAPublicKey)certificate.getPublicKey(); - - addField(sb, "Y:", key.getY().toString(16)); - } - - addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN"), - R.getI18NString( - "service.gui.CERT_INFO_KEY_BYTES_PRINT", - new String[]{ - String.valueOf(certificate.getSignature().length), - getHex(certificate.getSignature()) - })); - - sb.append("
    \n"); - } - - /** - * Add a title. - * - * @param sb StringBuilder to append to - * @param title to print - */ - private void addTitle(StringBuilder sb, String title) - { - sb.append("

    ") - .append(title).append("

    \n"); - } - - /** - * Add a field. - * @param sb StringBuilder to append to - * @param field name of the certificate field - * @param value to print - */ - private void addField(StringBuilder sb, String field, String value) - { - sb.append("") - .append("") - .append(field).append("") - .append("").append(value).append("") - .append("\n"); - } - - /** - * Converts the byte array to hex string. - * @param raw the data. - * @return the hex string. - */ - private String getHex( byte [] raw ) - { - if (raw == null) - return null; - - StringBuilder hex = new StringBuilder(2 * raw.length); - Formatter f = new Formatter(hex); - try - { - for (byte b : raw) - f.format("%02x", b); - } - finally - { - f.close(); - } - return hex.toString(); - } - - /** - * Calculates the hash of the certificate known as the "thumbprint" - * and returns it as a string representation. - * - * @param cert The certificate to hash. - * @param algorithm The hash algorithm to use. - * @return The SHA-1 hash of the certificate. - * @throws CertificateException - */ - private static String getThumbprint(X509Certificate cert, String algorithm) - throws CertificateException - { - MessageDigest digest; - try - { - digest = MessageDigest.getInstance(algorithm); - } - catch (NoSuchAlgorithmException e) - { - throw new CertificateException(e); - } - byte[] encodedCert = cert.getEncoded(); - StringBuilder sb = new StringBuilder(encodedCert.length * 2); - Formatter f = new Formatter(sb); - try - { - for (byte b : digest.digest(encodedCert)) - f.format("%02x", b); - } - finally - { - f.close(); - } - return sb.toString(); - } - - /** - * Construct a "simplified name" based on the subject DN from the - * certificate. The purpose is to have something shorter to display in the - * list. The name used is one of the following DN parts, if - * available, otherwise the complete DN: - * 'CN', 'OU' or else 'O'. - * @param cert to read subject DN from - * @return the simplified name - */ - private static String getSimplifiedName(X509Certificate cert) - { - final HashMap parts = new HashMap(); - try - { - for (Rdn name : new LdapName( - cert.getSubjectX500Principal().getName()).getRdns()) - { - if (name.getType() != null && name.getValue() != null) - { - parts.put(name.getType(), name.getValue().toString()); - } - } - } - catch (InvalidNameException ignored) // NOPMD - { - } - - String result = parts.get("CN"); - if (result == null) - { - result = parts.get("OU"); - } - if (result == null) - { - result = parts.get("O"); - } - if (result == null) - { - result = cert.getSubjectX500Principal().getName(); - } - return result; - } - - /** - * Called when the selection changed in the tree. - * Loads the selected certificate. - * @param e the event - */ - private void valueChangedPerformed(TreeSelectionEvent e) - { - Object o = e.getNewLeadSelectionPath().getLastPathComponent(); - if (o instanceof DefaultMutableTreeNode) - { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) o; - infoTextPane.setText(toString(node.getUserObject())); - } - } -} +package net.java.sip.communicator.plugin.desktoputil; + +import java.awt.*; +import java.security.*; +import java.security.cert.*; +import java.security.cert.Certificate; +import java.security.interfaces.*; +import java.util.*; + +import javax.naming.*; +import javax.naming.ldap.*; +import javax.security.auth.x500.*; +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.event.*; +import javax.swing.text.*; +import javax.swing.tree.*; + +import org.jitsi.service.resources.*; + +/** + * Panel that shows the content of an X509Certificate. + */ +public class X509CertificatePanel + extends TransparentPanel +{ + private static final long serialVersionUID = -8368302061995971947L; + + private final JEditorPane infoTextPane = new JEditorPane(); + + private final ResourceManagementService R + = DesktopUtilActivator.getResources(); + + /** + * Constructs a X509 certificate panel from a single certificate. + * If a chain is available instead use the second constructor. + * This constructor is kept for backwards compatibility and for convenience + * when there is only one certificate of interest. + * + * @param certificate X509Certificate object + */ + public X509CertificatePanel(Certificate certificate) + { + this(new Certificate[] + { + certificate + }); + } + + /** + * Constructs a X509 certificate panel. + * + * @param certificates X509Certificate objects + */ + public X509CertificatePanel(Certificate[] certificates) + { + setLayout(new BorderLayout(5, 5)); + + // Certificate chain list + TransparentPanel topPanel = new TransparentPanel(new BorderLayout()); + topPanel.add(new JLabel("" + + R.getI18NString("service.gui.CERT_INFO_CHAIN") + + ""), BorderLayout.NORTH); + + DefaultMutableTreeNode top = new DefaultMutableTreeNode(); + DefaultMutableTreeNode previous = top; + for (int i = certificates.length - 1; i >= 0; i--) + { + Certificate cert = certificates[i]; + DefaultMutableTreeNode next = new DefaultMutableTreeNode(cert); + previous.add(next); + previous = next; + } + JTree tree = new JTree(top); + tree.setBorder(new BevelBorder(BevelBorder.LOWERED)); + tree.setRootVisible(false); + tree.setExpandsSelectedPaths(true); + tree.getSelectionModel().setSelectionMode( + TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.setCellRenderer(new DefaultTreeCellRenderer() + { + + @Override + public Component getTreeCellRendererComponent(JTree tree, + Object value, boolean sel, boolean expanded, boolean leaf, + int row, boolean hasFocus) + { + JLabel component = (JLabel) super.getTreeCellRendererComponent( + tree, value, sel, expanded, leaf, row, hasFocus); + if (value instanceof DefaultMutableTreeNode) + { + Object o = ((DefaultMutableTreeNode) value).getUserObject(); + if (o instanceof X509Certificate) + { + component.setText( + getSimplifiedName((X509Certificate) o)); + } + else + { + // We don't know how to represent this certificate type, + // let's use the first 20 characters + String text = o.toString(); + if (text.length() > 20) + { + text = text.substring(0, 20); + } + component.setText(text); + } + } + return component; + } + + }); + tree.getSelectionModel().addTreeSelectionListener( + new TreeSelectionListener() + { + + @Override + public void valueChanged(TreeSelectionEvent e) + { + valueChangedPerformed(e); + } + }); + tree.setSelectionPath(new TreePath((( + (DefaultTreeModel)tree.getModel()).getPathToRoot(previous)))); + topPanel.add(tree, BorderLayout.CENTER); + + add(topPanel, BorderLayout.NORTH); + + // Certificate details pane + Caret caret = infoTextPane.getCaret(); + if (caret instanceof DefaultCaret) + { + ((DefaultCaret) caret).setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + } + + /* + * Make JEditorPane respect our default font because we will be using it + * to just display text. + */ + infoTextPane.putClientProperty( + JEditorPane.HONOR_DISPLAY_PROPERTIES, + true); + + infoTextPane.setOpaque(false); + infoTextPane.setEditable(false); + infoTextPane.setContentType("text/html"); + infoTextPane.setText(toString(certificates[0])); + + final JScrollPane certScroll = new JScrollPane(infoTextPane); + certScroll.setPreferredSize(new Dimension(300, 500)); + add(certScroll, BorderLayout.CENTER); + } + + /** + * Creates a String representation of the given object. + * @param certificate to print + * @return the String representation + */ + private String toString(Object certificate) + { + final StringBuilder sb = new StringBuilder(); + sb.append("\n"); + + if (certificate instanceof X509Certificate) + { + renderX509(sb, (X509Certificate) certificate); + } + else + { + sb.append("
    \n");
    +            sb.append(certificate.toString());
    +            sb.append("
    \n"); + } + + sb.append(""); + return sb.toString(); + } + + /** + * Appends an HTML representation of the given X509Certificate. + * @param sb StringBuilder to append to + * @param certificate to print + */ + private void renderX509(StringBuilder sb, X509Certificate certificate) + { + X500Principal issuer = certificate.getIssuerX500Principal(); + X500Principal subject = certificate.getSubjectX500Principal(); + + sb.append("\n"); + + // subject + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_TO")); + try + { + for(Rdn name : new LdapName(subject.getName()).getRdns()) + { + String nameType = name.getType(); + String lblKey = "service.gui.CERT_INFO_" + nameType; + String lbl = R.getI18NString(lblKey); + + if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) + lbl = nameType; + + final String value; + Object nameValue = name.getValue(); + + if (nameValue instanceof byte[]) + { + byte[] nameValueAsByteArray = (byte[]) nameValue; + + value + = getHex(nameValueAsByteArray) + " (" + + new String(nameValueAsByteArray) + ")"; + } + else + value = nameValue.toString(); + + addField(sb, lbl, value); + } + } + catch (InvalidNameException ine) + { + addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), + subject.getName()); + } + + // issuer + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_BY")); + try + { + for(Rdn name : new LdapName(issuer.getName()).getRdns()) + { + String nameType = name.getType(); + String lblKey = "service.gui.CERT_INFO_" + nameType; + String lbl = R.getI18NString(lblKey); + + if ((lbl == null) || ("!" + lblKey + "!").equals(lbl)) + lbl = nameType; + + final String value; + Object nameValue = name.getValue(); + + if (nameValue instanceof byte[]) + { + byte[] nameValueAsByteArray = (byte[]) nameValue; + + value + = getHex(nameValueAsByteArray) + " (" + + new String(nameValueAsByteArray) + ")"; + } + else + value = nameValue.toString(); + + addField(sb, lbl, value); + } + } + catch (InvalidNameException ine) + { + addField(sb, R.getI18NString("service.gui.CERT_INFO_CN"), + issuer.getName()); + } + + // validity + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_VALIDITY")); + addField(sb, R.getI18NString("service.gui.CERT_INFO_ISSUED_ON"), + certificate.getNotBefore().toString()); + addField(sb, R.getI18NString("service.gui.CERT_INFO_EXPIRES_ON"), + certificate.getNotAfter().toString()); + + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_FINGERPRINTS")); + try + { + String sha1String = getThumbprint(certificate, "SHA1"); + String md5String = getThumbprint(certificate, "MD5"); + + addField(sb, "SHA1:", sha1String); + addField(sb, "MD5:", md5String); + } + catch (CertificateException e) + { + // do nothing as we cannot show this value + } + + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_CERT_DETAILS")); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_SER_NUM"), + certificate.getSerialNumber().toString()); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_VER"), + String.valueOf(certificate.getVersion())); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN_ALG"), + String.valueOf(certificate.getSigAlgName())); + + addTitle(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY_INFO")); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_ALG"), + certificate.getPublicKey().getAlgorithm()); + + if(certificate.getPublicKey().getAlgorithm().equals("RSA")) + { + RSAPublicKey key = (RSAPublicKey)certificate.getPublicKey(); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY"), + R.getI18NString( + "service.gui.CERT_INFO_KEY_BYTES_PRINT", + new String[]{ + String.valueOf(key.getModulus().toByteArray().length-1), + key.getModulus().toString(16) + })); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_EXP"), + key.getPublicExponent().toString()); + + addField(sb, R.getI18NString("service.gui.CERT_INFO_KEY_SIZE"), + R.getI18NString( + "service.gui.CERT_INFO_KEY_BITS_PRINT", + new String[]{ + String.valueOf(key.getModulus().bitLength())})); + } + else if(certificate.getPublicKey().getAlgorithm().equals("DSA")) + { + DSAPublicKey key = + (DSAPublicKey)certificate.getPublicKey(); + + addField(sb, "Y:", key.getY().toString(16)); + } + + addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN"), + R.getI18NString( + "service.gui.CERT_INFO_KEY_BYTES_PRINT", + new String[]{ + String.valueOf(certificate.getSignature().length), + getHex(certificate.getSignature()) + })); + + sb.append("
    \n"); + } + + /** + * Add a title. + * + * @param sb StringBuilder to append to + * @param title to print + */ + private void addTitle(StringBuilder sb, String title) + { + sb.append("

    ") + .append(title).append("

    \n"); + } + + /** + * Add a field. + * @param sb StringBuilder to append to + * @param field name of the certificate field + * @param value to print + */ + private void addField(StringBuilder sb, String field, String value) + { + sb.append("") + .append("") + .append(field).append("") + .append("").append(value).append("") + .append("\n"); + } + + /** + * Converts the byte array to hex string. + * @param raw the data. + * @return the hex string. + */ + private String getHex( byte [] raw ) + { + if (raw == null) + return null; + + StringBuilder hex = new StringBuilder(2 * raw.length); + Formatter f = new Formatter(hex); + try + { + for (byte b : raw) + f.format("%02x", b); + } + finally + { + f.close(); + } + return hex.toString(); + } + + /** + * Calculates the hash of the certificate known as the "thumbprint" + * and returns it as a string representation. + * + * @param cert The certificate to hash. + * @param algorithm The hash algorithm to use. + * @return The SHA-1 hash of the certificate. + * @throws CertificateException + */ + private static String getThumbprint(X509Certificate cert, String algorithm) + throws CertificateException + { + MessageDigest digest; + try + { + digest = MessageDigest.getInstance(algorithm); + } + catch (NoSuchAlgorithmException e) + { + throw new CertificateException(e); + } + byte[] encodedCert = cert.getEncoded(); + StringBuilder sb = new StringBuilder(encodedCert.length * 2); + Formatter f = new Formatter(sb); + try + { + for (byte b : digest.digest(encodedCert)) + f.format("%02x", b); + } + finally + { + f.close(); + } + return sb.toString(); + } + + /** + * Construct a "simplified name" based on the subject DN from the + * certificate. The purpose is to have something shorter to display in the + * list. The name used is one of the following DN parts, if + * available, otherwise the complete DN: + * 'CN', 'OU' or else 'O'. + * @param cert to read subject DN from + * @return the simplified name + */ + private static String getSimplifiedName(X509Certificate cert) + { + final HashMap parts = new HashMap(); + try + { + for (Rdn name : new LdapName( + cert.getSubjectX500Principal().getName()).getRdns()) + { + if (name.getType() != null && name.getValue() != null) + { + parts.put(name.getType(), name.getValue().toString()); + } + } + } + catch (InvalidNameException ignored) // NOPMD + { + } + + String result = parts.get("CN"); + if (result == null) + { + result = parts.get("OU"); + } + if (result == null) + { + result = parts.get("O"); + } + if (result == null) + { + result = cert.getSubjectX500Principal().getName(); + } + return result; + } + + /** + * Called when the selection changed in the tree. + * Loads the selected certificate. + * @param e the event + */ + private void valueChangedPerformed(TreeSelectionEvent e) + { + Object o = e.getNewLeadSelectionPath().getLastPathComponent(); + if (o instanceof DefaultMutableTreeNode) + { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) o; + infoTextPane.setText(toString(node.getUserObject())); + } + } +} diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java index bce2fe7..c330879 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,1330 +15,1330 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.plugin.otr; - -import java.net.*; -import java.security.*; -import java.util.*; -import java.util.concurrent.*; - -import net.java.otr4j.*; -import net.java.otr4j.crypto.*; -import net.java.otr4j.session.*; -import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; -import net.java.sip.communicator.plugin.otr.authdialog.*; -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * - * @author George Politis - * @author Lyubomir Marinov - * @author Pawel Domas - * @author Marin Dzhigarov - * @author Danny van Heumen - */ -public class ScOtrEngineImpl - implements ScOtrEngine, - ChatLinkClickedListener, - ServiceListener -{ - private class ScOtrEngineHost - implements OtrEngineHost - { - @Override - public KeyPair getLocalKeyPair(SessionID sessionID) - { - AccountID accountID = - OtrActivator.getAccountIDByUID(sessionID.getAccountID()); - KeyPair keyPair = - OtrActivator.scOtrKeyManager.loadKeyPair(accountID); - if (keyPair == null) - OtrActivator.scOtrKeyManager.generateKeyPair(accountID); - - return OtrActivator.scOtrKeyManager.loadKeyPair(accountID); - } - - @Override - public OtrPolicy getSessionPolicy(SessionID sessionID) - { - return getContactPolicy(getOtrContact(sessionID).contact); - } - - @Override - public void injectMessage(SessionID sessionID, String messageText) - { - OtrContact otrContact = getOtrContact(sessionID); - Contact contact = otrContact.contact; - ContactResource resource = null; - - if (contact.supportResources()) - { - Collection resources = contact.getResources(); - if (resources != null) - { - for (ContactResource r : resources) - { - if (r.equals(otrContact.resource)) - { - resource = r; - break; - } - } - } - } - - OperationSetBasicInstantMessaging imOpSet - = contact - .getProtocolProvider() - .getOperationSet( - OperationSetBasicInstantMessaging.class); - - // This is a dirty way of detecting whether the injected message - // contains HTML markup. If this is the case then we should create - // the message with the appropriate content type so that the remote - // party can properly display the HTML. - // When otr4j injects QueryMessages it calls - // OtrEngineHost.getFallbackMessage() which is currently the only - // host method that uses HTML so we can simply check if the injected - // message contains the string that getFallbackMessage() returns. - String otrHtmlFallbackMessage - = ""; - String contentType - = messageText.contains(otrHtmlFallbackMessage) - ? OperationSetBasicInstantMessaging.HTML_MIME_TYPE - : OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE; - Message message - = imOpSet.createMessage( - messageText, - contentType, - OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, - null); - - injectedMessageUIDs.add(message.getMessageUID()); - imOpSet.sendInstantMessage(contact, resource, message); - } - - @Override - public void showError(SessionID sessionID, String err) - { - ScOtrEngineImpl.this.showError(sessionID, err); - } - - public void showWarning(SessionID sessionID, String warn) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.SYSTEM_MESSAGE, warn, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public void unreadableMessageReceived(SessionID sessionID) - throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - - Contact contact = otrContact.contact; - String error = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.unreadablemsgreceived", - new String[] - {contact.getDisplayName() + resourceName}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.ERROR_MESSAGE, error, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public void unencryptedMessageReceived(SessionID sessionID, String msg) - throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - String warn = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.unencryptedmsgreceived"); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.SYSTEM_MESSAGE, warn, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public void smpError(SessionID sessionID, int tlvType, boolean cheated) - throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - logger.debug("SMP error occurred" - + ". Contact: " + contact.getDisplayName() - + ". TLV type: " + tlvType - + ". Cheated: " + cheated); - - String error = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.smperror"); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.ERROR_MESSAGE, error, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.setProgressFail(); - progressDialog.setVisible(true); - } - - @Override - public void smpAborted(SessionID sessionID) throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - Session session = otrEngine.getSession(sessionID); - if (session.isSmpInProgress()) - { - String warn = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.smpaborted", - new String[] {contact.getDisplayName()}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.SYSTEM_MESSAGE, warn, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - - SmpProgressDialog progressDialog = - progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.setProgressFail(); - progressDialog.setVisible(true); - } - } - - @Override - public void finishedSessionMessage(SessionID sessionID, String msgText) - throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - Contact contact = otrContact.contact; - String error = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.sessionfinishederror", - new String[] - {msgText, contact.getDisplayName() + resourceName}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.ERROR_MESSAGE, error, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public void requireEncryptedMessage(SessionID sessionID, String msgText) - throws OtrException - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - String error = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.requireencryption", - new String[] - {msgText}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.ERROR_MESSAGE, error, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public byte[] getLocalFingerprintRaw(SessionID sessionID) - { - AccountID accountID = - OtrActivator.getAccountIDByUID(sessionID.getAccountID()); - return - OtrActivator.scOtrKeyManager.getLocalFingerprintRaw(accountID); - } - - @Override - public void askForSecret( - SessionID sessionID, InstanceTag receiverTag, String question) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - SmpAuthenticateBuddyDialog dialog = - new SmpAuthenticateBuddyDialog( - otrContact, receiverTag, question); - dialog.setVisible(true); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.init(); - progressDialog.setVisible(true); - } - - @Override - public void verify( - SessionID sessionID, String fingerprint, boolean approved) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - OtrActivator.scOtrKeyManager.verify(otrContact, fingerprint); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.setProgressSuccess(); - progressDialog.setVisible(true); - } - - @Override - public void unverify(SessionID sessionID, String fingerprint) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - OtrActivator.scOtrKeyManager.unverify(otrContact, fingerprint); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.setProgressFail(); - progressDialog.setVisible(true); - } - - @Override - public String getReplyForUnreadableMessage(SessionID sessionID) - { - AccountID accountID = - OtrActivator.getAccountIDByUID(sessionID.getAccountID()); - - return OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.unreadablemsgreply", - new String[] {accountID.getDisplayName(), - accountID.getDisplayName()}); - } - - @Override - public String getFallbackMessage(SessionID sessionID) - { - AccountID accountID = - OtrActivator.getAccountIDByUID(sessionID.getAccountID()); - - return OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.fallbackmessage", - new String[] {accountID.getDisplayName()}); - } - - @Override - public void multipleInstancesDetected(SessionID sessionID) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - Contact contact = otrContact.contact; - String message = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.multipleinstancesdetected", - new String[] - {contact.getDisplayName() + resourceName}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), - new Date(), Chat.SYSTEM_MESSAGE, - message, - OperationSetBasicInstantMessaging.HTML_MIME_TYPE); - } - - @Override - public void messageFromAnotherInstanceReceived(SessionID sessionID) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - Contact contact = otrContact.contact; - String message = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.msgfromanotherinstance", - new String[] - {contact.getDisplayName() + resourceName}); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), - new Date(), Chat.SYSTEM_MESSAGE, - message, - OperationSetBasicInstantMessaging.HTML_MIME_TYPE); - } - - /** - * Provide fragmenter instructions according to the Instant Messaging - * transport channel of the contact's protocol. - */ - @Override - public FragmenterInstructions getFragmenterInstructions( - final SessionID sessionID) - { - final OtrContact otrContact = getOtrContact(sessionID); - final OperationSetBasicInstantMessagingTransport transport = - otrContact.contact.getProtocolProvider().getOperationSet( - OperationSetBasicInstantMessagingTransport.class); - if (transport == null) - { - // There is no operation set for querying transport parameters. - // Assuming transport capabilities are unlimited. - if (logger.isDebugEnabled()) - { - logger.debug("No implementation of " - + "BasicInstantMessagingTransport available. Assuming " - + "OTR defaults for OTR fragmentation instructions."); - } - return null; - } - int messageSize = transport.getMaxMessageSize(otrContact.contact); - if (messageSize - == OperationSetBasicInstantMessagingTransport.UNLIMITED) - { - messageSize = FragmenterInstructions.UNLIMITED; - } - int numberOfMessages = - transport.getMaxNumberOfMessages(otrContact.contact); - if (numberOfMessages - == OperationSetBasicInstantMessagingTransport.UNLIMITED) - { - numberOfMessages = FragmenterInstructions.UNLIMITED; - } - if (logger.isDebugEnabled()) - { - logger.debug("OTR fragmentation instructions for sending a " - + "message to " + otrContact.contact.getDisplayName() - + " (" + otrContact.contact.getAddress() - + "). Maximum number of " + "messages: " + numberOfMessages - + ", maximum message size: " + messageSize); - } - return new FragmenterInstructions(numberOfMessages, messageSize); - } - } - - /** - * The max timeout period elapsed prior to establishing a TIMED_OUT session. - */ - private static final int SESSION_TIMEOUT = - OtrActivator.configService.getInt( - "net.java.sip.communicator.plugin.otr.SESSION_STATUS_TIMEOUT", - 30000); - - /** - * Manages the scheduling of TimerTasks that are used to set Contact's - * ScSessionStatus (to TIMED_OUT) after a period of time. - */ - private ScSessionStatusScheduler scheduler = new ScSessionStatusScheduler(); - - /** - * This mapping is used for taking care of keeping SessionStatus and - * ScSessionStatus in sync for every Session object. - */ - private Map scSessionStatusMap = - new ConcurrentHashMap(); - - private static final Map contactsMap = - new Hashtable(); - - private static final Map progressDialogMap = - new ConcurrentHashMap(); - - public static OtrContact getOtrContact(SessionID sessionID) - { - return contactsMap.get(new ScSessionID(sessionID)); - } - - /** - * Returns the ScSessionID for given UUID. - * @param guid the UUID identifying ScSessionID. - * @return the ScSessionID for given UUID or null - * if no matching session found. - */ - public static ScSessionID getScSessionForGuid(UUID guid) - { - for(ScSessionID scSessionID : contactsMap.keySet()) - { - if(scSessionID.getGUID().equals(guid)) - { - return scSessionID; - } - } - return null; - } - - public static SessionID getSessionID(OtrContact otrContact) - { - ProtocolProviderService pps = otrContact.contact.getProtocolProvider(); - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - SessionID sessionID - = new SessionID( - pps.getAccountID().getAccountUniqueID(), - otrContact.contact.getAddress() + resourceName, - pps.getProtocolName()); - - synchronized (contactsMap) - { - if(contactsMap.containsKey(new ScSessionID(sessionID))) - return sessionID; - - ScSessionID scSessionID = new ScSessionID(sessionID); - - contactsMap.put(scSessionID, otrContact); - } - - return sessionID; - } - - private final OtrConfigurator configurator = new OtrConfigurator(); - - private final List injectedMessageUIDs = new Vector(); - - private final List listeners = - new Vector(); - - /** - * The logger - */ - private final Logger logger = Logger.getLogger(ScOtrEngineImpl.class); - - private final OtrEngineHost otrEngineHost = new ScOtrEngineHost(); - - private final OtrSessionManager otrEngine; - - public ScOtrEngineImpl() - { - otrEngine = new OtrSessionManagerImpl(otrEngineHost); - - // Clears the map after previous instance - // This is required because of OSGi restarts in the same VM on Android - contactsMap.clear(); - scSessionStatusMap.clear(); - - this.otrEngine.addOtrEngineListener(new OtrEngineListener() - { - @Override - public void sessionStatusChanged(SessionID sessionID) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - String resourceName = otrContact.resource != null ? - "/" + otrContact.resource.getResourceName() : ""; - Contact contact = otrContact.contact; - // Cancels any scheduled tasks that will change the - // ScSessionStatus for this Contact - scheduler.cancel(otrContact); - - ScSessionStatus scSessionStatus = getSessionStatus(otrContact); - String message = ""; - final Session session = otrEngine.getSession(sessionID); - switch (session.getSessionStatus()) - { - case ENCRYPTED: - scSessionStatus = ScSessionStatus.ENCRYPTED; - scSessionStatusMap.put(sessionID, scSessionStatus); - PublicKey remotePubKey = session.getRemotePublicKey(); - - String remoteFingerprint = null; - try - { - remoteFingerprint = - new OtrCryptoEngineImpl(). - getFingerprint(remotePubKey); - } - catch (OtrCryptoException e) - { - logger.debug( - "Could not get the fingerprint from the " - + "public key of contact: " + contact); - } - - List allFingerprintsOfContact = - OtrActivator.scOtrKeyManager. - getAllRemoteFingerprints(contact); - if (allFingerprintsOfContact != null) - { - if (!allFingerprintsOfContact.contains( - remoteFingerprint)) - { - OtrActivator.scOtrKeyManager.saveFingerprint( - contact, remoteFingerprint); - } - } - - if (!OtrActivator.scOtrKeyManager.isVerified( - contact, remoteFingerprint)) - { - OtrActivator.scOtrKeyManager.unverify( - otrContact, remoteFingerprint); - UUID sessionGuid = null; - for(ScSessionID scSessionID : contactsMap.keySet()) - { - if(scSessionID.getSessionID().equals(sessionID)) - { - sessionGuid = scSessionID.getGUID(); - break; - } - } - - OtrActivator.uiService.getChat(contact) - .addChatLinkClickedListener(ScOtrEngineImpl.this); - - String unverifiedSessionWarning - = OtrActivator.resourceService.getI18NString( - "plugin.otr.activator" - + ".unverifiedsessionwarning", - new String[] - { - contact.getDisplayName() + resourceName, - this.getClass().getName(), - "AUTHENTIFICATION", - sessionGuid.toString() - }); - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), - new Date(), Chat.SYSTEM_MESSAGE, - unverifiedSessionWarning, - OperationSetBasicInstantMessaging.HTML_MIME_TYPE); - - } - - // show info whether history is on or off - String otrAndHistoryMessage; - if(!OtrActivator.getMessageHistoryService() - .isHistoryLoggingEnabled() || - !isHistoryLoggingEnabled(contact)) - { - otrAndHistoryMessage = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.historyoff", - new String[]{ - OtrActivator.resourceService - .getSettingsString( - "service.gui.APPLICATION_NAME"), - this.getClass().getName(), - "showHistoryPopupMenu" - }); - } - else - { - otrAndHistoryMessage = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.historyon", - new String[]{ - OtrActivator.resourceService - .getSettingsString( - "service.gui.APPLICATION_NAME"), - this.getClass().getName(), - "showHistoryPopupMenu" - }); - } - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), - new Date(), Chat.SYSTEM_MESSAGE, - otrAndHistoryMessage, - OperationSetBasicInstantMessaging.HTML_MIME_TYPE); - - message = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.multipleinstancesdetected", - new String[] - {contact.getDisplayName()}); - - if (contact.supportResources() - && contact.getResources() != null - && contact.getResources().size() > 1) - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), - new Date(), Chat.SYSTEM_MESSAGE, - message, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - - message - = OtrActivator.resourceService.getI18NString( - OtrActivator.scOtrKeyManager.isVerified( - contact, remoteFingerprint) - ? "plugin.otr.activator.sessionstared" - : "plugin.otr.activator" - + ".unverifiedsessionstared", - new String[] - {contact.getDisplayName() + resourceName}); - - break; - case FINISHED: - scSessionStatus = ScSessionStatus.FINISHED; - scSessionStatusMap.put(sessionID, scSessionStatus); - message = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.sessionfinished", - new String[] - {contact.getDisplayName() + resourceName}); - break; - case PLAINTEXT: - scSessionStatus = ScSessionStatus.PLAINTEXT; - scSessionStatusMap.put(sessionID, scSessionStatus); - message = - OtrActivator.resourceService.getI18NString( - "plugin.otr.activator.sessionlost", new String[] - {contact.getDisplayName() + resourceName}); - break; - } - - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.SYSTEM_MESSAGE, message, - OperationSetBasicInstantMessaging.HTML_MIME_TYPE); - - for (ScOtrEngineListener l : getListeners()) - l.sessionStatusChanged(otrContact); - } - - @Override - public void multipleInstancesDetected(SessionID sessionID) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - for (ScOtrEngineListener l : getListeners()) - l.multipleInstancesDetected(otrContact); - } - - @Override - public void outgoingSessionChanged(SessionID sessionID) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - for (ScOtrEngineListener l : getListeners()) - l.outgoingSessionChanged(otrContact); - } - }); - } - - /** - * Checks whether history is enabled for the metacontact containing - * the contact. - * @param contact the contact to check. - * @return whether chat logging is enabled while chatting - * with contact. - */ - private boolean isHistoryLoggingEnabled(Contact contact) - { - MetaContact metaContact = OtrActivator - .getContactListService().findMetaContactByContact(contact); - if(metaContact != null) - return OtrActivator.getMessageHistoryService() - .isHistoryLoggingEnabled(metaContact.getMetaUID()); - else - return true; - } - - @Override - public void addListener(ScOtrEngineListener l) - { - synchronized (listeners) - { - if (!listeners.contains(l)) - listeners.add(l); - } - } - - @Override - public void chatLinkClicked(URI url) - { - String action = url.getPath(); - if(action.equals("/AUTHENTIFICATION")) - { - UUID guid = UUID.fromString(url.getQuery()); - - if(guid == null) - throw new RuntimeException( - "No UUID found in OTR authenticate URL"); - - // Looks for registered action handler - OtrActionHandler actionHandler - = ServiceUtils.getService( - OtrActivator.bundleContext, - OtrActionHandler.class); - - if(actionHandler != null) - { - actionHandler.onAuthenticateLinkClicked(guid); - } - else - { - logger.error("No OtrActionHandler registered"); - } - } - } - - @Override - public void endSession(OtrContact otrContact) - { - SessionID sessionID = getSessionID(otrContact); - try - { - setSessionStatus(otrContact, ScSessionStatus.PLAINTEXT); - - otrEngine.getSession(sessionID).endSession(); - } - catch (OtrException e) - { - showError(sessionID, e.getMessage()); - } - } - - @Override - public OtrPolicy getContactPolicy(Contact contact) - { - ProtocolProviderService pps = contact.getProtocolProvider(); - SessionID sessionID - = new SessionID( - pps.getAccountID().getAccountUniqueID(), - contact.getAddress(), - pps.getProtocolName()); - int policy = - this.configurator.getPropertyInt(sessionID + "contact_policy", - -1); - if (policy < 0) - return getGlobalPolicy(); - else - return new OtrPolicyImpl(policy); - } - - @Override - public OtrPolicy getGlobalPolicy() - { - /* - * SEND_WHITESPACE_TAG bit will be lowered until we stabilize the OTR. - */ - int defaultScOtrPolicy = - OtrPolicy.OTRL_POLICY_DEFAULT & ~OtrPolicy.SEND_WHITESPACE_TAG; - return new OtrPolicyImpl(this.configurator.getPropertyInt( - "GLOBAL_POLICY", defaultScOtrPolicy)); - } - - /** - * Gets a copy of the list of ScOtrEngineListeners registered with - * this instance which may safely be iterated without the risk of a - * ConcurrentModificationException. - * - * @return a copy of the list of ScOtrEngineListeners registered - * with this instance which may safely be iterated without the risk of a - * ConcurrentModificationException - */ - private ScOtrEngineListener[] getListeners() - { - synchronized (listeners) - { - return listeners.toArray(new ScOtrEngineListener[listeners.size()]); - } - } - - /** - * Manages the scheduling of TimerTasks that are used to set Contact's - * ScSessionStatus after a period of time. - * - * @author Marin Dzhigarov - */ - private class ScSessionStatusScheduler - { - private final Timer timer = new Timer(); - - private final Map tasks = - new ConcurrentHashMap(); - - public void scheduleScSessionStatusChange( - final OtrContact otrContact, final ScSessionStatus status) - { - cancel(otrContact); - - TimerTask task - = new TimerTask() - { - @Override - public void run() - { - setSessionStatus(otrContact, status); - } - }; - timer.schedule(task, SESSION_TIMEOUT); - tasks.put(otrContact, task); - } - - public void cancel(final OtrContact otrContact) - { - TimerTask task = tasks.get(otrContact); - if (task != null) - task.cancel(); - tasks.remove(otrContact); - } - - public void serviceChanged(ServiceEvent ev) - { - Object service - = OtrActivator.bundleContext.getService( - ev.getServiceReference()); - - if (!(service instanceof ProtocolProviderService)) - return; - - if (ev.getType() == ServiceEvent.UNREGISTERING) - { - ProtocolProviderService provider - = (ProtocolProviderService) service; - - Iterator i = tasks.keySet().iterator(); - - while (i.hasNext()) - { - OtrContact otrContact = i.next(); - if (provider.equals( - otrContact.contact.getProtocolProvider())) - { - cancel(otrContact); - i.remove(); - } - } - } - } - } - - private void setSessionStatus(OtrContact contact, ScSessionStatus status) - { - scSessionStatusMap.put(getSessionID(contact), status); - scheduler.cancel(contact); - for (ScOtrEngineListener l : getListeners()) - l.sessionStatusChanged(contact); - } - - @Override - public ScSessionStatus getSessionStatus(OtrContact contact) - { - SessionID sessionID = getSessionID(contact); - SessionStatus sessionStatus = otrEngine.getSession(sessionID).getSessionStatus(); - ScSessionStatus scSessionStatus = null; - if (!scSessionStatusMap.containsKey(sessionID)) - { - switch (sessionStatus) - { - case PLAINTEXT: - scSessionStatus = ScSessionStatus.PLAINTEXT; - break; - case ENCRYPTED: - scSessionStatus = ScSessionStatus.ENCRYPTED; - break; - case FINISHED: - scSessionStatus = ScSessionStatus.FINISHED; - break; - } - scSessionStatusMap.put(sessionID, scSessionStatus); - } - return scSessionStatusMap.get(sessionID); - } - - @Override - public boolean isMessageUIDInjected(String mUID) - { - return injectedMessageUIDs.contains(mUID); - } - - @Override - public void launchHelp() - { - ServiceReference ref = - OtrActivator.bundleContext - .getServiceReference(BrowserLauncherService.class.getName()); - - if (ref == null) - return; - - BrowserLauncherService service = - (BrowserLauncherService) OtrActivator.bundleContext.getService(ref); - - service.openURL(OtrActivator.resourceService - .getI18NString("plugin.otr.authbuddydialog.HELP_URI")); - } - - @Override - public void refreshSession(OtrContact otrContact) - { - SessionID sessionID = getSessionID(otrContact); - try - { - otrEngine.getSession(sessionID).refreshSession(); - } - catch (OtrException e) - { - logger.error("Error refreshing session", e); - showError(sessionID, e.getMessage()); - } - } - - @Override - public void removeListener(ScOtrEngineListener l) - { - synchronized (listeners) - { - listeners.remove(l); - } - } - - /** - * Cleans the contactsMap when ProtocolProviderService - * gets unregistered. - */ - @Override - public void serviceChanged(ServiceEvent ev) - { - Object service - = OtrActivator.bundleContext.getService(ev.getServiceReference()); - - if (!(service instanceof ProtocolProviderService)) - return; - - if (ev.getType() == ServiceEvent.UNREGISTERING) - { - if (logger.isDebugEnabled()) - { - logger.debug( - "Unregistering a ProtocolProviderService, cleaning" - + " OTR's ScSessionID to Contact map."); - logger.debug( - "Unregistering a ProtocolProviderService, cleaning" - + " OTR's Contact to SpmProgressDialog map."); - } - - ProtocolProviderService provider - = (ProtocolProviderService) service; - - synchronized(contactsMap) - { - Iterator i = contactsMap.values().iterator(); - - while (i.hasNext()) +package net.java.sip.communicator.plugin.otr; + +import java.net.*; +import java.security.*; +import java.util.*; +import java.util.concurrent.*; + +import net.java.otr4j.*; +import net.java.otr4j.crypto.*; +import net.java.otr4j.session.*; +import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; +import net.java.sip.communicator.plugin.otr.authdialog.*; +import net.java.sip.communicator.service.browserlauncher.*; +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * + * @author George Politis + * @author Lyubomir Marinov + * @author Pawel Domas + * @author Marin Dzhigarov + * @author Danny van Heumen + */ +public class ScOtrEngineImpl + implements ScOtrEngine, + ChatLinkClickedListener, + ServiceListener +{ + private class ScOtrEngineHost + implements OtrEngineHost + { + @Override + public KeyPair getLocalKeyPair(SessionID sessionID) + { + AccountID accountID = + OtrActivator.getAccountIDByUID(sessionID.getAccountID()); + KeyPair keyPair = + OtrActivator.scOtrKeyManager.loadKeyPair(accountID); + if (keyPair == null) + OtrActivator.scOtrKeyManager.generateKeyPair(accountID); + + return OtrActivator.scOtrKeyManager.loadKeyPair(accountID); + } + + @Override + public OtrPolicy getSessionPolicy(SessionID sessionID) + { + return getContactPolicy(getOtrContact(sessionID).contact); + } + + @Override + public void injectMessage(SessionID sessionID, String messageText) + { + OtrContact otrContact = getOtrContact(sessionID); + Contact contact = otrContact.contact; + ContactResource resource = null; + + if (contact.supportResources()) + { + Collection resources = contact.getResources(); + if (resources != null) + { + for (ContactResource r : resources) + { + if (r.equals(otrContact.resource)) + { + resource = r; + break; + } + } + } + } + + OperationSetBasicInstantMessaging imOpSet + = contact + .getProtocolProvider() + .getOperationSet( + OperationSetBasicInstantMessaging.class); + + // This is a dirty way of detecting whether the injected message + // contains HTML markup. If this is the case then we should create + // the message with the appropriate content type so that the remote + // party can properly display the HTML. + // When otr4j injects QueryMessages it calls + // OtrEngineHost.getFallbackMessage() which is currently the only + // host method that uses HTML so we can simply check if the injected + // message contains the string that getFallbackMessage() returns. + String otrHtmlFallbackMessage + = ""; + String contentType + = messageText.contains(otrHtmlFallbackMessage) + ? OperationSetBasicInstantMessaging.HTML_MIME_TYPE + : OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE; + Message message + = imOpSet.createMessage( + messageText, + contentType, + OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, + null); + + injectedMessageUIDs.add(message.getMessageUID()); + imOpSet.sendInstantMessage(contact, resource, message); + } + + @Override + public void showError(SessionID sessionID, String err) + { + ScOtrEngineImpl.this.showError(sessionID, err); + } + + public void showWarning(SessionID sessionID, String warn) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.SYSTEM_MESSAGE, warn, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public void unreadableMessageReceived(SessionID sessionID) + throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + + Contact contact = otrContact.contact; + String error = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.unreadablemsgreceived", + new String[] + {contact.getDisplayName() + resourceName}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.ERROR_MESSAGE, error, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public void unencryptedMessageReceived(SessionID sessionID, String msg) + throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + String warn = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.unencryptedmsgreceived"); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.SYSTEM_MESSAGE, warn, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public void smpError(SessionID sessionID, int tlvType, boolean cheated) + throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + logger.debug("SMP error occurred" + + ". Contact: " + contact.getDisplayName() + + ". TLV type: " + tlvType + + ". Cheated: " + cheated); + + String error = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.smperror"); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.ERROR_MESSAGE, error, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.setProgressFail(); + progressDialog.setVisible(true); + } + + @Override + public void smpAborted(SessionID sessionID) throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + Session session = otrEngine.getSession(sessionID); + if (session.isSmpInProgress()) + { + String warn = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.smpaborted", + new String[] {contact.getDisplayName()}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.SYSTEM_MESSAGE, warn, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + + SmpProgressDialog progressDialog = + progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.setProgressFail(); + progressDialog.setVisible(true); + } + } + + @Override + public void finishedSessionMessage(SessionID sessionID, String msgText) + throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + Contact contact = otrContact.contact; + String error = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.sessionfinishederror", + new String[] + {msgText, contact.getDisplayName() + resourceName}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.ERROR_MESSAGE, error, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public void requireEncryptedMessage(SessionID sessionID, String msgText) + throws OtrException + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + String error = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.requireencryption", + new String[] + {msgText}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.ERROR_MESSAGE, error, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public byte[] getLocalFingerprintRaw(SessionID sessionID) + { + AccountID accountID = + OtrActivator.getAccountIDByUID(sessionID.getAccountID()); + return + OtrActivator.scOtrKeyManager.getLocalFingerprintRaw(accountID); + } + + @Override + public void askForSecret( + SessionID sessionID, InstanceTag receiverTag, String question) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + SmpAuthenticateBuddyDialog dialog = + new SmpAuthenticateBuddyDialog( + otrContact, receiverTag, question); + dialog.setVisible(true); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.init(); + progressDialog.setVisible(true); + } + + @Override + public void verify( + SessionID sessionID, String fingerprint, boolean approved) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + OtrActivator.scOtrKeyManager.verify(otrContact, fingerprint); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.setProgressSuccess(); + progressDialog.setVisible(true); + } + + @Override + public void unverify(SessionID sessionID, String fingerprint) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + OtrActivator.scOtrKeyManager.unverify(otrContact, fingerprint); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.setProgressFail(); + progressDialog.setVisible(true); + } + + @Override + public String getReplyForUnreadableMessage(SessionID sessionID) + { + AccountID accountID = + OtrActivator.getAccountIDByUID(sessionID.getAccountID()); + + return OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.unreadablemsgreply", + new String[] {accountID.getDisplayName(), + accountID.getDisplayName()}); + } + + @Override + public String getFallbackMessage(SessionID sessionID) + { + AccountID accountID = + OtrActivator.getAccountIDByUID(sessionID.getAccountID()); + + return OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.fallbackmessage", + new String[] {accountID.getDisplayName()}); + } + + @Override + public void multipleInstancesDetected(SessionID sessionID) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + Contact contact = otrContact.contact; + String message = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.multipleinstancesdetected", + new String[] + {contact.getDisplayName() + resourceName}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), + new Date(), Chat.SYSTEM_MESSAGE, + message, + OperationSetBasicInstantMessaging.HTML_MIME_TYPE); + } + + @Override + public void messageFromAnotherInstanceReceived(SessionID sessionID) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + Contact contact = otrContact.contact; + String message = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.msgfromanotherinstance", + new String[] + {contact.getDisplayName() + resourceName}); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), + new Date(), Chat.SYSTEM_MESSAGE, + message, + OperationSetBasicInstantMessaging.HTML_MIME_TYPE); + } + + /** + * Provide fragmenter instructions according to the Instant Messaging + * transport channel of the contact's protocol. + */ + @Override + public FragmenterInstructions getFragmenterInstructions( + final SessionID sessionID) + { + final OtrContact otrContact = getOtrContact(sessionID); + final OperationSetBasicInstantMessagingTransport transport = + otrContact.contact.getProtocolProvider().getOperationSet( + OperationSetBasicInstantMessagingTransport.class); + if (transport == null) + { + // There is no operation set for querying transport parameters. + // Assuming transport capabilities are unlimited. + if (logger.isDebugEnabled()) + { + logger.debug("No implementation of " + + "BasicInstantMessagingTransport available. Assuming " + + "OTR defaults for OTR fragmentation instructions."); + } + return null; + } + int messageSize = transport.getMaxMessageSize(otrContact.contact); + if (messageSize + == OperationSetBasicInstantMessagingTransport.UNLIMITED) + { + messageSize = FragmenterInstructions.UNLIMITED; + } + int numberOfMessages = + transport.getMaxNumberOfMessages(otrContact.contact); + if (numberOfMessages + == OperationSetBasicInstantMessagingTransport.UNLIMITED) + { + numberOfMessages = FragmenterInstructions.UNLIMITED; + } + if (logger.isDebugEnabled()) + { + logger.debug("OTR fragmentation instructions for sending a " + + "message to " + otrContact.contact.getDisplayName() + + " (" + otrContact.contact.getAddress() + + "). Maximum number of " + "messages: " + numberOfMessages + + ", maximum message size: " + messageSize); + } + return new FragmenterInstructions(numberOfMessages, messageSize); + } + } + + /** + * The max timeout period elapsed prior to establishing a TIMED_OUT session. + */ + private static final int SESSION_TIMEOUT = + OtrActivator.configService.getInt( + "net.java.sip.communicator.plugin.otr.SESSION_STATUS_TIMEOUT", + 30000); + + /** + * Manages the scheduling of TimerTasks that are used to set Contact's + * ScSessionStatus (to TIMED_OUT) after a period of time. + */ + private ScSessionStatusScheduler scheduler = new ScSessionStatusScheduler(); + + /** + * This mapping is used for taking care of keeping SessionStatus and + * ScSessionStatus in sync for every Session object. + */ + private Map scSessionStatusMap = + new ConcurrentHashMap(); + + private static final Map contactsMap = + new Hashtable(); + + private static final Map progressDialogMap = + new ConcurrentHashMap(); + + public static OtrContact getOtrContact(SessionID sessionID) + { + return contactsMap.get(new ScSessionID(sessionID)); + } + + /** + * Returns the ScSessionID for given UUID. + * @param guid the UUID identifying ScSessionID. + * @return the ScSessionID for given UUID or null + * if no matching session found. + */ + public static ScSessionID getScSessionForGuid(UUID guid) + { + for(ScSessionID scSessionID : contactsMap.keySet()) + { + if(scSessionID.getGUID().equals(guid)) + { + return scSessionID; + } + } + return null; + } + + public static SessionID getSessionID(OtrContact otrContact) + { + ProtocolProviderService pps = otrContact.contact.getProtocolProvider(); + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + SessionID sessionID + = new SessionID( + pps.getAccountID().getAccountUniqueID(), + otrContact.contact.getAddress() + resourceName, + pps.getProtocolName()); + + synchronized (contactsMap) + { + if(contactsMap.containsKey(new ScSessionID(sessionID))) + return sessionID; + + ScSessionID scSessionID = new ScSessionID(sessionID); + + contactsMap.put(scSessionID, otrContact); + } + + return sessionID; + } + + private final OtrConfigurator configurator = new OtrConfigurator(); + + private final List injectedMessageUIDs = new Vector(); + + private final List listeners = + new Vector(); + + /** + * The logger + */ + private final Logger logger = Logger.getLogger(ScOtrEngineImpl.class); + + private final OtrEngineHost otrEngineHost = new ScOtrEngineHost(); + + private final OtrSessionManager otrEngine; + + public ScOtrEngineImpl() + { + otrEngine = new OtrSessionManagerImpl(otrEngineHost); + + // Clears the map after previous instance + // This is required because of OSGi restarts in the same VM on Android + contactsMap.clear(); + scSessionStatusMap.clear(); + + this.otrEngine.addOtrEngineListener(new OtrEngineListener() + { + @Override + public void sessionStatusChanged(SessionID sessionID) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + String resourceName = otrContact.resource != null ? + "/" + otrContact.resource.getResourceName() : ""; + Contact contact = otrContact.contact; + // Cancels any scheduled tasks that will change the + // ScSessionStatus for this Contact + scheduler.cancel(otrContact); + + ScSessionStatus scSessionStatus = getSessionStatus(otrContact); + String message = ""; + final Session session = otrEngine.getSession(sessionID); + switch (session.getSessionStatus()) + { + case ENCRYPTED: + scSessionStatus = ScSessionStatus.ENCRYPTED; + scSessionStatusMap.put(sessionID, scSessionStatus); + PublicKey remotePubKey = session.getRemotePublicKey(); + + String remoteFingerprint = null; + try + { + remoteFingerprint = + new OtrCryptoEngineImpl(). + getFingerprint(remotePubKey); + } + catch (OtrCryptoException e) + { + logger.debug( + "Could not get the fingerprint from the " + + "public key of contact: " + contact); + } + + List allFingerprintsOfContact = + OtrActivator.scOtrKeyManager. + getAllRemoteFingerprints(contact); + if (allFingerprintsOfContact != null) + { + if (!allFingerprintsOfContact.contains( + remoteFingerprint)) + { + OtrActivator.scOtrKeyManager.saveFingerprint( + contact, remoteFingerprint); + } + } + + if (!OtrActivator.scOtrKeyManager.isVerified( + contact, remoteFingerprint)) + { + OtrActivator.scOtrKeyManager.unverify( + otrContact, remoteFingerprint); + UUID sessionGuid = null; + for(ScSessionID scSessionID : contactsMap.keySet()) + { + if(scSessionID.getSessionID().equals(sessionID)) + { + sessionGuid = scSessionID.getGUID(); + break; + } + } + + OtrActivator.uiService.getChat(contact) + .addChatLinkClickedListener(ScOtrEngineImpl.this); + + String unverifiedSessionWarning + = OtrActivator.resourceService.getI18NString( + "plugin.otr.activator" + + ".unverifiedsessionwarning", + new String[] + { + contact.getDisplayName() + resourceName, + this.getClass().getName(), + "AUTHENTIFICATION", + sessionGuid.toString() + }); + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), + new Date(), Chat.SYSTEM_MESSAGE, + unverifiedSessionWarning, + OperationSetBasicInstantMessaging.HTML_MIME_TYPE); + + } + + // show info whether history is on or off + String otrAndHistoryMessage; + if(!OtrActivator.getMessageHistoryService() + .isHistoryLoggingEnabled() || + !isHistoryLoggingEnabled(contact)) + { + otrAndHistoryMessage = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.historyoff", + new String[]{ + OtrActivator.resourceService + .getSettingsString( + "service.gui.APPLICATION_NAME"), + this.getClass().getName(), + "showHistoryPopupMenu" + }); + } + else + { + otrAndHistoryMessage = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.historyon", + new String[]{ + OtrActivator.resourceService + .getSettingsString( + "service.gui.APPLICATION_NAME"), + this.getClass().getName(), + "showHistoryPopupMenu" + }); + } + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), + new Date(), Chat.SYSTEM_MESSAGE, + otrAndHistoryMessage, + OperationSetBasicInstantMessaging.HTML_MIME_TYPE); + + message = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.multipleinstancesdetected", + new String[] + {contact.getDisplayName()}); + + if (contact.supportResources() + && contact.getResources() != null + && contact.getResources().size() > 1) + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), + new Date(), Chat.SYSTEM_MESSAGE, + message, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + + message + = OtrActivator.resourceService.getI18NString( + OtrActivator.scOtrKeyManager.isVerified( + contact, remoteFingerprint) + ? "plugin.otr.activator.sessionstared" + : "plugin.otr.activator" + + ".unverifiedsessionstared", + new String[] + {contact.getDisplayName() + resourceName}); + + break; + case FINISHED: + scSessionStatus = ScSessionStatus.FINISHED; + scSessionStatusMap.put(sessionID, scSessionStatus); + message = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.sessionfinished", + new String[] + {contact.getDisplayName() + resourceName}); + break; + case PLAINTEXT: + scSessionStatus = ScSessionStatus.PLAINTEXT; + scSessionStatusMap.put(sessionID, scSessionStatus); + message = + OtrActivator.resourceService.getI18NString( + "plugin.otr.activator.sessionlost", new String[] + {contact.getDisplayName() + resourceName}); + break; + } + + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.SYSTEM_MESSAGE, message, + OperationSetBasicInstantMessaging.HTML_MIME_TYPE); + + for (ScOtrEngineListener l : getListeners()) + l.sessionStatusChanged(otrContact); + } + + @Override + public void multipleInstancesDetected(SessionID sessionID) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + for (ScOtrEngineListener l : getListeners()) + l.multipleInstancesDetected(otrContact); + } + + @Override + public void outgoingSessionChanged(SessionID sessionID) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + for (ScOtrEngineListener l : getListeners()) + l.outgoingSessionChanged(otrContact); + } + }); + } + + /** + * Checks whether history is enabled for the metacontact containing + * the contact. + * @param contact the contact to check. + * @return whether chat logging is enabled while chatting + * with contact. + */ + private boolean isHistoryLoggingEnabled(Contact contact) + { + MetaContact metaContact = OtrActivator + .getContactListService().findMetaContactByContact(contact); + if(metaContact != null) + return OtrActivator.getMessageHistoryService() + .isHistoryLoggingEnabled(metaContact.getMetaUID()); + else + return true; + } + + @Override + public void addListener(ScOtrEngineListener l) + { + synchronized (listeners) + { + if (!listeners.contains(l)) + listeners.add(l); + } + } + + @Override + public void chatLinkClicked(URI url) + { + String action = url.getPath(); + if(action.equals("/AUTHENTIFICATION")) + { + UUID guid = UUID.fromString(url.getQuery()); + + if(guid == null) + throw new RuntimeException( + "No UUID found in OTR authenticate URL"); + + // Looks for registered action handler + OtrActionHandler actionHandler + = ServiceUtils.getService( + OtrActivator.bundleContext, + OtrActionHandler.class); + + if(actionHandler != null) + { + actionHandler.onAuthenticateLinkClicked(guid); + } + else + { + logger.error("No OtrActionHandler registered"); + } + } + } + + @Override + public void endSession(OtrContact otrContact) + { + SessionID sessionID = getSessionID(otrContact); + try + { + setSessionStatus(otrContact, ScSessionStatus.PLAINTEXT); + + otrEngine.getSession(sessionID).endSession(); + } + catch (OtrException e) + { + showError(sessionID, e.getMessage()); + } + } + + @Override + public OtrPolicy getContactPolicy(Contact contact) + { + ProtocolProviderService pps = contact.getProtocolProvider(); + SessionID sessionID + = new SessionID( + pps.getAccountID().getAccountUniqueID(), + contact.getAddress(), + pps.getProtocolName()); + int policy = + this.configurator.getPropertyInt(sessionID + "contact_policy", + -1); + if (policy < 0) + return getGlobalPolicy(); + else + return new OtrPolicyImpl(policy); + } + + @Override + public OtrPolicy getGlobalPolicy() + { + /* + * SEND_WHITESPACE_TAG bit will be lowered until we stabilize the OTR. + */ + int defaultScOtrPolicy = + OtrPolicy.OTRL_POLICY_DEFAULT & ~OtrPolicy.SEND_WHITESPACE_TAG; + return new OtrPolicyImpl(this.configurator.getPropertyInt( + "GLOBAL_POLICY", defaultScOtrPolicy)); + } + + /** + * Gets a copy of the list of ScOtrEngineListeners registered with + * this instance which may safely be iterated without the risk of a + * ConcurrentModificationException. + * + * @return a copy of the list of ScOtrEngineListeners registered + * with this instance which may safely be iterated without the risk of a + * ConcurrentModificationException + */ + private ScOtrEngineListener[] getListeners() + { + synchronized (listeners) + { + return listeners.toArray(new ScOtrEngineListener[listeners.size()]); + } + } + + /** + * Manages the scheduling of TimerTasks that are used to set Contact's + * ScSessionStatus after a period of time. + * + * @author Marin Dzhigarov + */ + private class ScSessionStatusScheduler + { + private final Timer timer = new Timer(); + + private final Map tasks = + new ConcurrentHashMap(); + + public void scheduleScSessionStatusChange( + final OtrContact otrContact, final ScSessionStatus status) + { + cancel(otrContact); + + TimerTask task + = new TimerTask() + { + @Override + public void run() + { + setSessionStatus(otrContact, status); + } + }; + timer.schedule(task, SESSION_TIMEOUT); + tasks.put(otrContact, task); + } + + public void cancel(final OtrContact otrContact) + { + TimerTask task = tasks.get(otrContact); + if (task != null) + task.cancel(); + tasks.remove(otrContact); + } + + public void serviceChanged(ServiceEvent ev) + { + Object service + = OtrActivator.bundleContext.getService( + ev.getServiceReference()); + + if (!(service instanceof ProtocolProviderService)) + return; + + if (ev.getType() == ServiceEvent.UNREGISTERING) + { + ProtocolProviderService provider + = (ProtocolProviderService) service; + + Iterator i = tasks.keySet().iterator(); + + while (i.hasNext()) + { + OtrContact otrContact = i.next(); + if (provider.equals( + otrContact.contact.getProtocolProvider())) + { + cancel(otrContact); + i.remove(); + } + } + } + } + } + + private void setSessionStatus(OtrContact contact, ScSessionStatus status) + { + scSessionStatusMap.put(getSessionID(contact), status); + scheduler.cancel(contact); + for (ScOtrEngineListener l : getListeners()) + l.sessionStatusChanged(contact); + } + + @Override + public ScSessionStatus getSessionStatus(OtrContact contact) + { + SessionID sessionID = getSessionID(contact); + SessionStatus sessionStatus = otrEngine.getSession(sessionID).getSessionStatus(); + ScSessionStatus scSessionStatus = null; + if (!scSessionStatusMap.containsKey(sessionID)) + { + switch (sessionStatus) + { + case PLAINTEXT: + scSessionStatus = ScSessionStatus.PLAINTEXT; + break; + case ENCRYPTED: + scSessionStatus = ScSessionStatus.ENCRYPTED; + break; + case FINISHED: + scSessionStatus = ScSessionStatus.FINISHED; + break; + } + scSessionStatusMap.put(sessionID, scSessionStatus); + } + return scSessionStatusMap.get(sessionID); + } + + @Override + public boolean isMessageUIDInjected(String mUID) + { + return injectedMessageUIDs.contains(mUID); + } + + @Override + public void launchHelp() + { + ServiceReference ref = + OtrActivator.bundleContext + .getServiceReference(BrowserLauncherService.class.getName()); + + if (ref == null) + return; + + BrowserLauncherService service = + (BrowserLauncherService) OtrActivator.bundleContext.getService(ref); + + service.openURL(OtrActivator.resourceService + .getI18NString("plugin.otr.authbuddydialog.HELP_URI")); + } + + @Override + public void refreshSession(OtrContact otrContact) + { + SessionID sessionID = getSessionID(otrContact); + try + { + otrEngine.getSession(sessionID).refreshSession(); + } + catch (OtrException e) + { + logger.error("Error refreshing session", e); + showError(sessionID, e.getMessage()); + } + } + + @Override + public void removeListener(ScOtrEngineListener l) + { + synchronized (listeners) + { + listeners.remove(l); + } + } + + /** + * Cleans the contactsMap when ProtocolProviderService + * gets unregistered. + */ + @Override + public void serviceChanged(ServiceEvent ev) + { + Object service + = OtrActivator.bundleContext.getService(ev.getServiceReference()); + + if (!(service instanceof ProtocolProviderService)) + return; + + if (ev.getType() == ServiceEvent.UNREGISTERING) + { + if (logger.isDebugEnabled()) + { + logger.debug( + "Unregistering a ProtocolProviderService, cleaning" + + " OTR's ScSessionID to Contact map."); + logger.debug( + "Unregistering a ProtocolProviderService, cleaning" + + " OTR's Contact to SpmProgressDialog map."); + } + + ProtocolProviderService provider + = (ProtocolProviderService) service; + + synchronized(contactsMap) + { + Iterator i = contactsMap.values().iterator(); + + while (i.hasNext()) { - OtrContact otrContact = i.next(); - if (provider.equals( - otrContact.contact.getProtocolProvider())) - { - scSessionStatusMap.remove(getSessionID(otrContact)); - i.remove(); - } - } - } - - Iterator i = progressDialogMap.keySet().iterator(); - - while (i.hasNext()) - { - if (provider.equals(i.next().contact.getProtocolProvider())) - i.remove(); - } - scheduler.serviceChanged(ev); - } - } - - @Override - public void setContactPolicy(Contact contact, OtrPolicy policy) - { - ProtocolProviderService pps = contact.getProtocolProvider(); - SessionID sessionID - = new SessionID( - pps.getAccountID().getAccountUniqueID(), - contact.getAddress(), - pps.getProtocolName()); - - String propertyID = sessionID + "contact_policy"; - if (policy == null) - this.configurator.removeProperty(propertyID); - else - this.configurator.setProperty(propertyID, policy.getPolicy()); - - for (ScOtrEngineListener l : getListeners()) - l.contactPolicyChanged(contact); - } - - @Override - public void setGlobalPolicy(OtrPolicy policy) - { - if (policy == null) - this.configurator.removeProperty("GLOBAL_POLICY"); - else - this.configurator.setProperty("GLOBAL_POLICY", policy.getPolicy()); - - for (ScOtrEngineListener l : getListeners()) - l.globalPolicyChanged(); - } - - public void showError(SessionID sessionID, String err) - { - OtrContact otrContact = getOtrContact(sessionID); - if (otrContact == null) - return; - - Contact contact = otrContact.contact; - OtrActivator.uiService.getChat(contact).addMessage( - contact.getDisplayName(), new Date(), - Chat.ERROR_MESSAGE, err, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); - } - - @Override - public void startSession(OtrContact otrContact) - { - SessionID sessionID = getSessionID(otrContact); - - ScSessionStatus scSessionStatus = getSessionStatus(otrContact); - scSessionStatus = ScSessionStatus.LOADING; - scSessionStatusMap.put(sessionID, scSessionStatus); - for (ScOtrEngineListener l : getListeners()) - { - l.sessionStatusChanged(otrContact); - } - - scheduler.scheduleScSessionStatusChange( - otrContact, ScSessionStatus.TIMED_OUT); - - try - { - otrEngine.getSession(sessionID).startSession(); - } - catch (OtrException e) - { - logger.error("Error starting session", e); - showError(sessionID, e.getMessage()); - } - } - - @Override - public String transformReceiving(OtrContact otrContact, String msgText) - { - SessionID sessionID = getSessionID(otrContact); - try - { - return otrEngine.getSession(sessionID).transformReceiving(msgText); - } - catch (OtrException e) - { - logger.error("Error receiving the message", e); - showError(sessionID, e.getMessage()); - return null; - } - } - - @Override - public String[] transformSending(OtrContact otrContact, String msgText) - { - SessionID sessionID = getSessionID(otrContact); - try - { - return otrEngine.getSession(sessionID).transformSending(msgText); - } - catch (OtrException e) - { - logger.error("Error transforming the message", e); - showError(sessionID, e.getMessage()); - return null; - } - } - - private Session getSession(OtrContact contact) - { - SessionID sessionID = getSessionID(contact); - return otrEngine.getSession(sessionID); - } - - @Override - public void initSmp(OtrContact otrContact, String question, String secret) - { - Session session = getSession(otrContact); - try - { - session.initSmp(question, secret); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(otrContact.contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.init(); - progressDialog.setVisible(true); - } - catch (OtrException e) - { - logger.error("Error initializing SMP session with contact " - + otrContact.contact.getDisplayName(), e); - showError(session.getSessionID(), e.getMessage()); - } - } - - @Override - public void respondSmp( OtrContact otrContact, - InstanceTag receiverTag, - String question, - String secret) - { - Session session = getSession(otrContact); - try - { - session.respondSmp(receiverTag, question, secret); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(otrContact.contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.incrementProgress(); - progressDialog.setVisible(true); - } - catch (OtrException e) - { - logger.error( - "Error occured when sending SMP response to contact " - + otrContact.contact.getDisplayName(), e); - showError(session.getSessionID(), e.getMessage()); - } - } - - @Override - public void abortSmp(OtrContact otrContact) - { - Session session = getSession(otrContact); - try - { - session.abortSmp(); - - SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); - if (progressDialog == null) - { - progressDialog = new SmpProgressDialog(otrContact.contact); - progressDialogMap.put(otrContact, progressDialog); - } - - progressDialog.dispose(); - } - catch (OtrException e) - { - logger.error("Error aborting SMP session with contact " - + otrContact.contact.getDisplayName(), e); - showError(session.getSessionID(), e.getMessage()); - } - } - - @Override - public PublicKey getRemotePublicKey(OtrContact otrContact) - { - if (otrContact == null) - return null; - - Session session = getSession(otrContact); - - return session.getRemotePublicKey(); - } - - @Override - public List getSessionInstances(OtrContact otrContact) - { - if (otrContact == null) - return Collections.emptyList(); - return getSession(otrContact).getInstances(); - } - - @Override - public boolean setOutgoingSession(OtrContact contact, InstanceTag tag) - { - if (contact == null) - return false; - - Session session = getSession(contact); - - scSessionStatusMap.remove(session.getSessionID()); - return session.setOutgoingInstance(tag); - } - - @Override - public Session getOutgoingSession(OtrContact contact) - { - if (contact == null) - return null; - - SessionID sessionID = getSessionID(contact); - - return otrEngine.getSession(sessionID).getOutgoingInstance(); - } -} + OtrContact otrContact = i.next(); + if (provider.equals( + otrContact.contact.getProtocolProvider())) + { + scSessionStatusMap.remove(getSessionID(otrContact)); + i.remove(); + } + } + } + + Iterator i = progressDialogMap.keySet().iterator(); + + while (i.hasNext()) + { + if (provider.equals(i.next().contact.getProtocolProvider())) + i.remove(); + } + scheduler.serviceChanged(ev); + } + } + + @Override + public void setContactPolicy(Contact contact, OtrPolicy policy) + { + ProtocolProviderService pps = contact.getProtocolProvider(); + SessionID sessionID + = new SessionID( + pps.getAccountID().getAccountUniqueID(), + contact.getAddress(), + pps.getProtocolName()); + + String propertyID = sessionID + "contact_policy"; + if (policy == null) + this.configurator.removeProperty(propertyID); + else + this.configurator.setProperty(propertyID, policy.getPolicy()); + + for (ScOtrEngineListener l : getListeners()) + l.contactPolicyChanged(contact); + } + + @Override + public void setGlobalPolicy(OtrPolicy policy) + { + if (policy == null) + this.configurator.removeProperty("GLOBAL_POLICY"); + else + this.configurator.setProperty("GLOBAL_POLICY", policy.getPolicy()); + + for (ScOtrEngineListener l : getListeners()) + l.globalPolicyChanged(); + } + + public void showError(SessionID sessionID, String err) + { + OtrContact otrContact = getOtrContact(sessionID); + if (otrContact == null) + return; + + Contact contact = otrContact.contact; + OtrActivator.uiService.getChat(contact).addMessage( + contact.getDisplayName(), new Date(), + Chat.ERROR_MESSAGE, err, + OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE); + } + + @Override + public void startSession(OtrContact otrContact) + { + SessionID sessionID = getSessionID(otrContact); + + ScSessionStatus scSessionStatus = getSessionStatus(otrContact); + scSessionStatus = ScSessionStatus.LOADING; + scSessionStatusMap.put(sessionID, scSessionStatus); + for (ScOtrEngineListener l : getListeners()) + { + l.sessionStatusChanged(otrContact); + } + + scheduler.scheduleScSessionStatusChange( + otrContact, ScSessionStatus.TIMED_OUT); + + try + { + otrEngine.getSession(sessionID).startSession(); + } + catch (OtrException e) + { + logger.error("Error starting session", e); + showError(sessionID, e.getMessage()); + } + } + + @Override + public String transformReceiving(OtrContact otrContact, String msgText) + { + SessionID sessionID = getSessionID(otrContact); + try + { + return otrEngine.getSession(sessionID).transformReceiving(msgText); + } + catch (OtrException e) + { + logger.error("Error receiving the message", e); + showError(sessionID, e.getMessage()); + return null; + } + } + + @Override + public String[] transformSending(OtrContact otrContact, String msgText) + { + SessionID sessionID = getSessionID(otrContact); + try + { + return otrEngine.getSession(sessionID).transformSending(msgText); + } + catch (OtrException e) + { + logger.error("Error transforming the message", e); + showError(sessionID, e.getMessage()); + return null; + } + } + + private Session getSession(OtrContact contact) + { + SessionID sessionID = getSessionID(contact); + return otrEngine.getSession(sessionID); + } + + @Override + public void initSmp(OtrContact otrContact, String question, String secret) + { + Session session = getSession(otrContact); + try + { + session.initSmp(question, secret); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(otrContact.contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.init(); + progressDialog.setVisible(true); + } + catch (OtrException e) + { + logger.error("Error initializing SMP session with contact " + + otrContact.contact.getDisplayName(), e); + showError(session.getSessionID(), e.getMessage()); + } + } + + @Override + public void respondSmp( OtrContact otrContact, + InstanceTag receiverTag, + String question, + String secret) + { + Session session = getSession(otrContact); + try + { + session.respondSmp(receiverTag, question, secret); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(otrContact.contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.incrementProgress(); + progressDialog.setVisible(true); + } + catch (OtrException e) + { + logger.error( + "Error occured when sending SMP response to contact " + + otrContact.contact.getDisplayName(), e); + showError(session.getSessionID(), e.getMessage()); + } + } + + @Override + public void abortSmp(OtrContact otrContact) + { + Session session = getSession(otrContact); + try + { + session.abortSmp(); + + SmpProgressDialog progressDialog = progressDialogMap.get(otrContact); + if (progressDialog == null) + { + progressDialog = new SmpProgressDialog(otrContact.contact); + progressDialogMap.put(otrContact, progressDialog); + } + + progressDialog.dispose(); + } + catch (OtrException e) + { + logger.error("Error aborting SMP session with contact " + + otrContact.contact.getDisplayName(), e); + showError(session.getSessionID(), e.getMessage()); + } + } + + @Override + public PublicKey getRemotePublicKey(OtrContact otrContact) + { + if (otrContact == null) + return null; + + Session session = getSession(otrContact); + + return session.getRemotePublicKey(); + } + + @Override + public List getSessionInstances(OtrContact otrContact) + { + if (otrContact == null) + return Collections.emptyList(); + return getSession(otrContact).getInstances(); + } + + @Override + public boolean setOutgoingSession(OtrContact contact, InstanceTag tag) + { + if (contact == null) + return false; + + Session session = getSession(contact); + + scSessionStatusMap.remove(session.getSessionID()); + return session.setOutgoingInstance(tag); + } + + @Override + public Session getOutgoingSession(OtrContact contact) + { + if (contact == null) + return null; + + SessionID sessionID = getSessionID(contact); + + return otrEngine.getSession(sessionID).getOutgoingInstance(); + } +} diff --git a/src/net/java/sip/communicator/service/muc/ChatRoomProviderWrapperListener.java b/src/net/java/sip/communicator/service/muc/ChatRoomProviderWrapperListener.java index 261f2d7..dab910b 100644 --- a/src/net/java/sip/communicator/service/muc/ChatRoomProviderWrapperListener.java +++ b/src/net/java/sip/communicator/service/muc/ChatRoomProviderWrapperListener.java @@ -1,40 +1,40 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.service.muc; - -/** - * Listener which registers for provider add/remove changes. - */ -public interface ChatRoomProviderWrapperListener -{ - /** - * When a provider wrapper is added this method is called to inform - * listeners. - * @param provider which was added. - */ - public void chatRoomProviderWrapperAdded( - ChatRoomProviderWrapper provider); - - /** - * When a provider wrapper is removed this method is called to inform - * listeners. - * @param provider which was removed. - */ - public void chatRoomProviderWrapperRemoved( - ChatRoomProviderWrapper provider); -} +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.service.muc; + +/** + * Listener which registers for provider add/remove changes. + */ +public interface ChatRoomProviderWrapperListener +{ + /** + * When a provider wrapper is added this method is called to inform + * listeners. + * @param provider which was added. + */ + public void chatRoomProviderWrapperAdded( + ChatRoomProviderWrapper provider); + + /** + * When a provider wrapper is removed this method is called to inform + * listeners. + * @param provider which was removed. + */ + public void chatRoomProviderWrapperRemoved( + ChatRoomProviderWrapper provider); +} diff --git a/src/net/java/sip/communicator/service/protocol/AccountManager.java b/src/net/java/sip/communicator/service/protocol/AccountManager.java index c608092..3ce85dc 100644 --- a/src/net/java/sip/communicator/service/protocol/AccountManager.java +++ b/src/net/java/sip/communicator/service/protocol/AccountManager.java @@ -1,1083 +1,1083 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.service.protocol; - -import java.util.*; - -import net.java.sip.communicator.service.credentialsstorage.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.util.Base64; //disambiguate from java.util.Base64 - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * Represents an implementation of AccountManager which loads the - * accounts in a separate thread. - * - * @author Lyubomir Marinov - * @author Yana Stamcheva - */ -public class AccountManager -{ - /** - * The delay in milliseconds the background Thread loading the - * stored accounts should wait before dying so that it doesn't get recreated - * for each ProtocolProviderFactory registration. - */ - private static final long LOAD_STORED_ACCOUNTS_TIMEOUT = 30000; - - /** - * The BundleContext this service is registered in. - */ - private final BundleContext bundleContext; - - /** - * The AccountManagerListeners currently interested in the - * events fired by this manager. - */ - private final List listeners = - new LinkedList(); - - /** - * The queue of ProtocolProviderFactory services awaiting their - * stored accounts to be loaded. - */ - private final Queue loadStoredAccountsQueue = - new LinkedList(); - - /** - * The Thread loading the stored accounts of the - * ProtocolProviderFactory services waiting in - * {@link #loadStoredAccountsQueue}. - */ - private Thread loadStoredAccountsThread; - - /** - * The Logger used by this AccountManagerImpl instance for - * logging output. - */ - private final Logger logger = Logger.getLogger(AccountManager.class); - - /** - * The list of AccountIDs, corresponding to all stored accounts. - */ - private final Vector storedAccounts = new Vector(); - - /** - * The prefix of the account unique identifier. - */ - private static final String ACCOUNT_UID_PREFIX = "acc"; - - /** - * Initializes a new AccountManagerImpl instance loaded in a - * specific BundleContext (in which the caller will usually - * later register it). - * - * @param bundleContext the BundleContext in which the new - * instance is loaded (and in which the caller will usually later - * register it as a service) - */ - public AccountManager(BundleContext bundleContext) - { - this.bundleContext = bundleContext; - - this.bundleContext.addServiceListener(new ServiceListener() - { - public void serviceChanged(ServiceEvent serviceEvent) - { - AccountManager.this.serviceChanged(serviceEvent); - } - }); - } - - /** - * Implements AccountManager#addListener(AccountManagerListener). - * @param listener the AccountManagerListener to add - */ - public void addListener(AccountManagerListener listener) - { - synchronized (listeners) - { - if (!listeners.contains(listener)) - listeners.add(listener); - } - } - - /** - * Loads the accounts stored for a specific - * ProtocolProviderFactory. - * - * @param factory the ProtocolProviderFactory to load the - * stored accounts of - */ - private void doLoadStoredAccounts(ProtocolProviderFactory factory) - { - ConfigurationService configService - = ProtocolProviderActivator.getConfigurationService(); - String factoryPackage = getFactoryImplPackageName(factory); - List accounts - = configService.getPropertyNamesByPrefix(factoryPackage, true); - - if (logger.isDebugEnabled()) - logger.debug("Discovered " + accounts.size() + " stored " - + factoryPackage + " accounts"); - - for (Iterator storedAccountIter = accounts.iterator(); - storedAccountIter.hasNext();) - { - String storedAccount = storedAccountIter.next(); - - // If the property is not related to an account we skip it. - int dotIndex = storedAccount.lastIndexOf("."); - if (!storedAccount.substring(dotIndex + 1) - .startsWith(ACCOUNT_UID_PREFIX)) - continue; - - if (logger.isDebugEnabled()) - logger.debug("Loading account " + storedAccount); - - List storedAccountProperties = - configService.getPropertyNamesByPrefix(storedAccount, false); - Map accountProperties = - new Hashtable(); - boolean disabled = false; - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - - int prefLen = storedAccount.length() + 1; - for (Iterator storedAccountPropertyIter - = storedAccountProperties.iterator(); - storedAccountPropertyIter.hasNext();) - { - String property = storedAccountPropertyIter.next(); - String value = configService.getString(property); - - //strip the package prefix - if(prefLen > property.length()) - continue; - - property = property.substring(prefLen); - - if (ProtocolProviderFactory.IS_ACCOUNT_DISABLED.equals(property)) - disabled = Boolean.parseBoolean(value); - // Decode passwords. - else if (ProtocolProviderFactory.PASSWORD.equals(property) - && !credentialsStorage.isStoredEncrypted(storedAccount)) - { - if ((value != null) && value.length() != 0) - { - - /* - * TODO Converting byte[] to String using the platform's - * default charset may result in an invalid password. - */ - value = new String(Base64.decode(value)); - } - } - - if (value != null) - accountProperties.put(property, value); - } - - try - { - AccountID accountID = factory.createAccount(accountProperties); - - // If for some reason the account id is not created we move to - // the next account. - if (accountID == null) - continue; - - synchronized (storedAccounts) - { - storedAccounts.add(accountID); - } - if (!disabled) - factory.loadAccount(accountID); - } - catch (Exception ex) - { - /* - * Swallow the exception in order to prevent a single account - * from halting the loading of subsequent accounts. - */ - logger.error("Failed to load account " + accountProperties, ex); - } - catch (ExceptionInInitializerError ex) - { - // In case we fail to instantiate the ProtocolProviderService. - logger.error( - "Failed to create account service instance for account " - + accountProperties, ex); - } - } - } - - /** - * Notifies the registered {@link #listeners} that the stored accounts of a - * specific ProtocolProviderFactory have just been loaded. - * - * @param factory the ProtocolProviderFactory which had its - * stored accounts just loaded - */ - private void fireStoredAccountsLoaded(ProtocolProviderFactory factory) - { - AccountManagerListener[] listeners; - synchronized (this.listeners) - { - listeners = - this.listeners - .toArray(new AccountManagerListener[this.listeners.size()]); - } - - int listenerCount = listeners.length; - if (listenerCount > 0) - { - AccountManagerEvent event = - new AccountManagerEvent(this, - AccountManagerEvent.STORED_ACCOUNTS_LOADED, factory); - - for (int listenerIndex = 0; - listenerIndex < listenerCount; listenerIndex++) - { - listeners[listenerIndex].handleAccountManagerEvent(event); - } - } - } - - /** - * Returns the package name of the factory. - * @param factory the factory which package will be returned. - * @return the package name of the factory. - */ - public String getFactoryImplPackageName(ProtocolProviderFactory factory) - { - String className = factory.getClass().getName(); - - return className.substring(0, className.lastIndexOf('.')); - } - - /** - * Check for stored accounts for the supplied protocolName. - * @param protocolName the protocol name to check for - * @param includeHidden whether to include hidden providers - * @return true if there is any account stored in configuration - * service with protocolName, false otherwise. - */ - public boolean hasStoredAccounts(String protocolName, boolean includeHidden) - { - return hasStoredAccount(protocolName, includeHidden, null); - } - - /** - * Checks whether a stored account with userID is stored - * in configuration. - * - * @param protocolName the protocol name - * @param includeHidden whether to check hidden providers - * @param userID the user id to check. - * @return true if there is any account stored in configuration - * service with protocolName and userID, - * false otherwise. - */ - public boolean hasStoredAccount(String protocolName, - boolean includeHidden, - String userID) - { - Collection> factoryRefs - = ServiceUtils.getServiceReferences( - bundleContext, - ProtocolProviderFactory.class); - boolean hasStoredAccounts = false; - - if (!factoryRefs.isEmpty()) - { - ConfigurationService configService - = ProtocolProviderActivator.getConfigurationService(); - - for (ServiceReference factoryRef - : factoryRefs) - { - ProtocolProviderFactory factory - = bundleContext.getService(factoryRef); - - if ((protocolName != null) - && !protocolName.equals(factory.getProtocolName())) - { - continue; - } - - String factoryPackage = getFactoryImplPackageName(factory); - List storedAccounts - = configService - .getPropertyNamesByPrefix(factoryPackage + ".acc", - false); - - /* Ignore the hidden accounts. */ - for (Iterator storedAccountIter = - storedAccounts.iterator(); storedAccountIter.hasNext();) - { - String storedAccount = storedAccountIter.next(); - List storedAccountProperties = - configService.getPropertyNamesByPrefix(storedAccount, - true); - boolean hidden = false; - String accountUserID = null; - - if (!includeHidden || userID != null) - { - for (Iterator storedAccountPropertyIter = - storedAccountProperties.iterator(); - storedAccountPropertyIter.hasNext();) - { - String property = storedAccountPropertyIter.next(); - String value = configService.getString(property); - - property = stripPackagePrefix(property); - - if (ProtocolProviderFactory.IS_PROTOCOL_HIDDEN - .equals(property)) - { - hidden = (value != null); - } - else if (ProtocolProviderFactory.USER_ID - .equals(property)) - { - accountUserID = value; - } - } - } - - if (includeHidden || !hidden) - { - if(accountUserID != null - && userID != null - && userID.equals(accountUserID)) - { - hasStoredAccounts = true; - break; - } - else if(userID == null) - { - hasStoredAccounts = true; - break; - } - } - } - - if (hasStoredAccounts || (protocolName != null)) - { - break; - } - } - } - return hasStoredAccounts; - } - - /** - * Searches for stored account with uid in stored - * configuration. The uid is the one generated when creating - * accounts with prefix ACCOUNT_UID_PREFIX. - * - * @return AccountID if there is any account stored in configuration - * service with uid, - * null otherwise. - */ - public AccountID findAccountID(String uid) - { - Collection> factoryRefs - = ServiceUtils.getServiceReferences( - bundleContext, - ProtocolProviderFactory.class); - - if (!factoryRefs.isEmpty()) - { - ConfigurationService configService - = ProtocolProviderActivator.getConfigurationService(); - - for (ServiceReference factoryRef - : factoryRefs) - { - ProtocolProviderFactory factory - = bundleContext.getService(factoryRef); - - String factoryPackage = getFactoryImplPackageName(factory); - List storedAccountsProps - = configService - .getPropertyNamesByPrefix(factoryPackage, true); - - for (Iterator storedAccountIter = - storedAccountsProps.iterator(); - storedAccountIter.hasNext();) - { - String storedAccount = storedAccountIter.next(); - - if(!storedAccount.endsWith(uid)) - continue; - - String accountUID = configService.getString( - storedAccount //node id - + "." + ProtocolProviderFactory.ACCOUNT_UID);// propname - - for(AccountID acc : storedAccounts) - { - if(acc.getAccountUniqueID().equals(accountUID)) - return acc; - } - } - } - } - return null; - } - - /** - * Loads the accounts stored for a specific - * ProtocolProviderFactory and notifies the registered - * {@link #listeners} that the stored accounts of the specified - * factory have just been loaded - * - * @param factory the ProtocolProviderFactory to load the - * stored accounts of - */ - private void loadStoredAccounts(ProtocolProviderFactory factory) - { - doLoadStoredAccounts(factory); - - fireStoredAccountsLoaded(factory); - } - - /** - * Notifies this manager that a specific - * ProtocolProviderFactory has been registered as a service. - * The current implementation queues the specified factory to - * have its stored accounts as soon as possible. - * - * @param factory the ProtocolProviderFactory which has been - * registered as a service. - */ - private void protocolProviderFactoryRegistered( - ProtocolProviderFactory factory) - { - queueLoadStoredAccounts(factory); - } - - /** - * Queues a specific ProtocolProviderFactory to have its stored - * accounts loaded as soon as possible. - * - * @param factory the ProtocolProviderFactory to be queued for - * loading its stored accounts as soon as possible - */ - private void queueLoadStoredAccounts(ProtocolProviderFactory factory) - { - synchronized (loadStoredAccountsQueue) - { - loadStoredAccountsQueue.add(factory); - loadStoredAccountsQueue.notifyAll(); - - if (loadStoredAccountsThread == null) - { - loadStoredAccountsThread = new Thread() - { - @Override - public void run() - { - runInLoadStoredAccountsThread(); - } - }; - loadStoredAccountsThread.setDaemon(true); - loadStoredAccountsThread.setName( - "AccountManager.loadStoredAccounts"); - loadStoredAccountsThread.start(); - } - } - } - - /** - * Implements AccountManager#removeListener(AccountManagerListener). - * @param listener the AccountManagerListener to remove - */ - public void removeListener(AccountManagerListener listener) - { - synchronized (listeners) - { - listeners.remove(listener); - } - } - - /** - * Running in {@link #loadStoredAccountsThread}, loads the stored accounts - * of the ProtocolProviderFactory services waiting in - * {@link #loadStoredAccountsQueue} - */ - private void runInLoadStoredAccountsThread() - { - boolean interrupted = false; - while (!interrupted) - { - try - { - ProtocolProviderFactory factory; - - synchronized (loadStoredAccountsQueue) - { - factory = loadStoredAccountsQueue.poll(); - if (factory == null) - { - /* - * Technically, we should be handing spurious wakeups. - * However, we cannot check the condition in a queue. - * Anyway, we just want to keep this Thread alive long - * enough to allow it to not be re-created multiple - * times and not handing a spurious wakeup will just - * cause such an inconvenience. - */ - try - { - loadStoredAccountsQueue - .wait(LOAD_STORED_ACCOUNTS_TIMEOUT); - } - catch (InterruptedException ex) - { - logger - .warn( - "The loading of the stored accounts has" - + " been interrupted", - ex); - interrupted = true; - break; - } - factory = loadStoredAccountsQueue.poll(); - } - if (factory != null) - loadStoredAccountsQueue.notifyAll(); - } - - if (factory != null) - { - try - { - loadStoredAccounts(factory); - } - catch (Exception ex) - { - - /* - * Swallow the exception in order to prevent a single - * factory from halting the loading of subsequent - * factories. - */ - logger.error("Failed to load accounts for " + factory, - ex); - } - } - } - finally - { - synchronized (loadStoredAccountsQueue) - { - if (!interrupted && (loadStoredAccountsQueue.size() <= 0)) - { - if (loadStoredAccountsThread == Thread.currentThread()) - { - loadStoredAccountsThread = null; - loadStoredAccountsQueue.notifyAll(); - } - break; - } - } - } - } - } - - /** - * Notifies this manager that an OSGi service has changed. The current - * implementation tracks the registrations of - * ProtocolProviderFactory services in order to queue them for - * loading their stored accounts. - * - * @param serviceEvent the ServiceEvent containing the event - * data - */ - private void serviceChanged(ServiceEvent serviceEvent) - { - switch (serviceEvent.getType()) - { - case ServiceEvent.REGISTERED: - Object service - = bundleContext.getService(serviceEvent.getServiceReference()); - - if (service instanceof ProtocolProviderFactory) - { - protocolProviderFactoryRegistered( - (ProtocolProviderFactory) service); - } - break; - default: - break; - } - } - - /** - * Stores an account represented in the form of an AccountID - * created by a specific ProtocolProviderFactory. - * - * @param factory the ProtocolProviderFactory which created the - * account to be stored - * @param accountID the account in the form of AccountID to be - * stored - * @throws OperationFailedException if anything goes wrong while storing the - * account - */ - public void storeAccount( - ProtocolProviderFactory factory, - AccountID accountID) - throws OperationFailedException - { - synchronized (storedAccounts) - { - if (!storedAccounts.contains(accountID)) - storedAccounts.add(accountID); - } - - ConfigurationService configurationService - = ProtocolProviderActivator.getConfigurationService(); - String factoryPackage = getFactoryImplPackageName(factory); - - String accountNodeName - = getAccountNodeName( factory, - accountID.getAccountUniqueID() ); - - Map configurationProperties - = new HashMap(); - - // Create a unique node name of the properties node that will contain - // this account's properties. - if (accountNodeName == null) - { - accountNodeName - = ACCOUNT_UID_PREFIX + Long.toString(System.currentTimeMillis()); - - // set a value for the persistent node so that we could later - // retrieve it as a property - configurationProperties.put( - factoryPackage /* prefix */ + "." + accountNodeName, - accountNodeName); - - // register the account in the configuration service. - // we register all the properties in the following hierarchy - //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME - configurationProperties.put(factoryPackage// prefix - + "." + accountNodeName // node name for the account id - + "." + ProtocolProviderFactory.ACCOUNT_UID, // propname - accountID.getAccountUniqueID()); // value - } - - // store the rest of the properties - Map accountProperties = accountID.getAccountProperties(); - - for (Map.Entry entry : accountProperties.entrySet()) - { - String property = entry.getKey(); - String value = entry.getValue(); - String secureStorePrefix = null; - - // If the property is a password, store it securely. - if (property.equals(ProtocolProviderFactory.PASSWORD)) - { - String accountPrefix = factoryPackage + "." + accountNodeName; - secureStorePrefix = accountPrefix; - } - else if(property.endsWith("." + ProtocolProviderFactory.PASSWORD)) - { - secureStorePrefix = factoryPackage + "." + accountNodeName + - "." + property.substring(0, property.lastIndexOf(".")); - } - - if(secureStorePrefix != null) - { - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - - // encrypt and store - if ((value != null) - && (value.length() != 0) - && !credentialsStorage.storePassword( - secureStorePrefix, - value)) - { - throw - new OperationFailedException( - "CredentialsStorageService failed to" - + " storePassword", - OperationFailedException.GENERAL_ERROR); - } - } - else - { - configurationProperties.put( - factoryPackage // prefix - + "." + accountNodeName // a unique node name for the account id - + "." + property, // propname - value); // value - } - } - - // clear the password if missing property, modification can request - // password delete - if(!accountProperties.containsKey(ProtocolProviderFactory.PASSWORD) - && // And only if it's not stored already in encrypted form. - // Account registration object clears also this property - // in order to forget the password - !configurationProperties.containsKey( - factoryPackage+"."+accountNodeName+".ENCRYPTED_PASSWORD")) - { - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - credentialsStorage.removePassword( - factoryPackage + "." + accountNodeName); - } - - if (configurationProperties.size() > 0) - configurationService.setProperties(configurationProperties); - - if (logger.isDebugEnabled()) - logger.debug("Stored account for id " + accountID.getAccountUniqueID() - + " for package " + factoryPackage); - } - - /** - * Gets account node name under which account configuration properties are - * stored. - * - * @param factory account's protocol provider factory - * @param accountUID account for which the prefix will be returned - * @return configuration prefix for given accountID if exists or - * null otherwise - */ - public String getAccountNodeName( ProtocolProviderFactory factory, - String accountUID ) - { - ConfigurationService configurationService - = ProtocolProviderActivator.getConfigurationService(); - String factoryPackage = getFactoryImplPackageName(factory); - - // First check if such accountID already exists in the configuration. - List storedAccounts = - configurationService.getPropertyNamesByPrefix(factoryPackage, true); - String accountNodeName = null; - - for (Iterator storedAccountIter = storedAccounts.iterator(); - storedAccountIter.hasNext();) - { - String storedAccount = storedAccountIter.next(); - - // If the property is not related to an account we skip it. - int dotIndex = storedAccount.lastIndexOf("."); - if (!storedAccount.substring(dotIndex + 1) - .startsWith(ACCOUNT_UID_PREFIX)) - continue; - - String storedAccountUID - = configurationService.getString( - storedAccount + "." + ProtocolProviderFactory.ACCOUNT_UID); - - if(storedAccountUID == null) - continue; - - if (storedAccountUID.equals(accountUID)) - accountNodeName = configurationService.getString(storedAccount); - } - return accountNodeName; - } - - /** - * Removes the account with accountID from the set of accounts - * that are persistently stored inside the configuration service. - * - * @param factory the ProtocolProviderFactory which created the - * account to be stored - * @param accountID the AccountID of the account to remove. - * @return true if an account has been removed and false otherwise. - */ - public boolean removeStoredAccount(ProtocolProviderFactory factory, - AccountID accountID) - { - synchronized (storedAccounts) - { - if (storedAccounts.contains(accountID)) - storedAccounts.remove(accountID); - } - - /* - * We're already doing it in #unloadAccount(AccountID) - we're figuring - * out the ProtocolProviderFactory by the AccountID. - */ - if (factory == null) - { - factory - = ProtocolProviderActivator.getProtocolProviderFactory( - accountID.getProtocolName()); - } - - String factoryPackage = getFactoryImplPackageName(factory); - - // remove the stored password explicitly using credentials service - CredentialsStorageService credentialsStorage - = ServiceUtils.getService( - bundleContext, - CredentialsStorageService.class); - String accountPrefix = - ProtocolProviderFactory.findAccountPrefix(bundleContext, accountID, - factoryPackage); - - credentialsStorage.removePassword(accountPrefix); - - ConfigurationService configurationService - = ServiceUtils.getService( - bundleContext, - ConfigurationService.class); - //first retrieve all accounts that we've registered - List storedAccounts - = configurationService.getPropertyNamesByPrefix( - factoryPackage, true); - - //find an account with the corresponding id. - for (String accountRootPropertyName : storedAccounts) - { - //unregister the account in the configuration service. - //all the properties must have been registered in the following - //hierarchy: - //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME - String accountUID = configurationService.getString( - accountRootPropertyName //node id - + "." + ProtocolProviderFactory.ACCOUNT_UID); // propname - - if (accountID.getAccountUniqueID().equals(accountUID)) - { - //retrieve the names of all properties registered for the - //current account. - List accountPropertyNames - = configurationService.getPropertyNamesByPrefix( - accountRootPropertyName, false); - - //set all account properties to null in order to remove them. - for (String propName : accountPropertyNames) - configurationService.setProperty(propName, null); - - //and now remove the parent too. - configurationService.setProperty(accountRootPropertyName, null); - return true; - } - } - return false; - } - - /** - * Removes all accounts which have been persistently stored. - * - * @see #removeStoredAccount(ProtocolProviderFactory, AccountID) - */ - public void removeStoredAccounts() - { - synchronized (loadStoredAccountsQueue) - { - /* - * Wait for the Thread which loads the stored account to complete so - * that we can be sure later on that it will not load a stored - * account while we are deleting it or another one for that matter. - */ - boolean interrupted = false; - - while (loadStoredAccountsThread != null) - try - { - loadStoredAccountsQueue.wait(LOAD_STORED_ACCOUNTS_TIMEOUT); - } - catch (InterruptedException ie) - { - interrupted = true; - } - if (interrupted) - Thread.currentThread().interrupt(); - - synchronized (this.storedAccounts) - { - AccountID[] storedAccounts - = this.storedAccounts.toArray( - new AccountID[this.storedAccounts.size()]); - - for (AccountID storedAccount : storedAccounts) - { - ProtocolProviderFactory ppf - = ProtocolProviderActivator.getProtocolProviderFactory( - storedAccount.getProtocolName()); - - if (ppf != null) - ppf.uninstallAccount(storedAccount); - } - } - } - } - - /** - * Returns an Iterator over a list of all stored - * AccountIDs. The list of stored accounts include all registered - * accounts and all disabled accounts. In other words in this list we could - * find accounts that aren't loaded. - *

    - * In order to check if an account is already loaded please use the - * #isAccountLoaded(AccountID accountID) method. To load an account use the - * #loadAccount(AccountID accountID) method. - * - * @return an Iterator over a list of all stored - * AccountIDs - */ - public Collection getStoredAccounts() - { - synchronized (storedAccounts) - { - return new Vector(storedAccounts); - } - } - - /** - * Loads the account corresponding to the given AccountID. An - * account is loaded when its ProtocolProviderService is registered - * in the bundle context. This method is meant to load the account through - * the corresponding ProtocolProviderFactory. - * - * @param accountID the identifier of the account to load - * @throws OperationFailedException if anything goes wrong while loading the - * account corresponding to the specified accountID - */ - public void loadAccount(AccountID accountID) - throws OperationFailedException - { - // If the account with the given id is already loaded we have nothing - // to do here. - if (isAccountLoaded(accountID)) - return; - - ProtocolProviderFactory providerFactory - = ProtocolProviderActivator.getProtocolProviderFactory( - accountID.getProtocolName()); - - if(providerFactory.loadAccount(accountID)) - { - accountID.putAccountProperty( - ProtocolProviderFactory.IS_ACCOUNT_DISABLED, - String.valueOf(false)); - // Finally store the modified properties. - storeAccount(providerFactory, accountID); - } - } - - /** - * Unloads the account corresponding to the given AccountID. An - * account is unloaded when its ProtocolProviderService is - * unregistered in the bundle context. This method is meant to unload the - * account through the corresponding ProtocolProviderFactory. - * - * @param accountID the identifier of the account to load - * @throws OperationFailedException if anything goes wrong while unloading - * the account corresponding to the specified accountID - */ - public void unloadAccount(AccountID accountID) - throws OperationFailedException - { - // If the account with the given id is already unloaded we have nothing - // to do here. - if (!isAccountLoaded(accountID)) - return; - - ProtocolProviderFactory providerFactory - = ProtocolProviderActivator.getProtocolProviderFactory( - accountID.getProtocolName()); - - // Obtain the protocol provider. - ServiceReference serRef - = providerFactory.getProviderForAccount(accountID); - - // If there's no such provider we have nothing to do here. - if (serRef == null) - return; - - ProtocolProviderService protocolProvider - = bundleContext.getService(serRef); - - // Set the account icon path for unloaded accounts. - String iconPathProperty = accountID.getAccountPropertyString( - ProtocolProviderFactory.ACCOUNT_ICON_PATH); - - if (iconPathProperty == null) - { - accountID.putAccountProperty( - ProtocolProviderFactory.ACCOUNT_ICON_PATH, - protocolProvider.getProtocolIcon() - .getIconPath(ProtocolIcon.ICON_SIZE_32x32)); - } - - accountID.putAccountProperty( - ProtocolProviderFactory.IS_ACCOUNT_DISABLED, - String.valueOf(true)); - - if (!providerFactory.unloadAccount(accountID)) - { - accountID.putAccountProperty( - ProtocolProviderFactory.IS_ACCOUNT_DISABLED, - String.valueOf(false)); - } - // Finally store the modified properties. - storeAccount(providerFactory, accountID); - } - - /** - * Checks if the account corresponding to the given accountID is - * loaded. An account is loaded if its ProtocolProviderService is - * registered in the bundle context. By default all accounts are loaded. - * However the user could manually unload an account, which would be - * unregistered from the bundle context, but would remain in the - * configuration file. - * - * @param accountID the identifier of the account to load - * @return true to indicate that the account with the given - * accountID is loaded, false - otherwise - */ - public boolean isAccountLoaded(AccountID accountID) - { - return storedAccounts.contains(accountID) && accountID.isEnabled(); - } - - private String stripPackagePrefix(String property) - { - int packageEndIndex = property.lastIndexOf('.'); - - if (packageEndIndex != -1) - property = property.substring(packageEndIndex + 1); - return property; - } -} +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.service.protocol; + +import java.util.*; + +import net.java.sip.communicator.service.credentialsstorage.*; +import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.Base64; //disambiguate from java.util.Base64 + +import org.jitsi.service.configuration.*; +import org.osgi.framework.*; + +/** + * Represents an implementation of AccountManager which loads the + * accounts in a separate thread. + * + * @author Lyubomir Marinov + * @author Yana Stamcheva + */ +public class AccountManager +{ + /** + * The delay in milliseconds the background Thread loading the + * stored accounts should wait before dying so that it doesn't get recreated + * for each ProtocolProviderFactory registration. + */ + private static final long LOAD_STORED_ACCOUNTS_TIMEOUT = 30000; + + /** + * The BundleContext this service is registered in. + */ + private final BundleContext bundleContext; + + /** + * The AccountManagerListeners currently interested in the + * events fired by this manager. + */ + private final List listeners = + new LinkedList(); + + /** + * The queue of ProtocolProviderFactory services awaiting their + * stored accounts to be loaded. + */ + private final Queue loadStoredAccountsQueue = + new LinkedList(); + + /** + * The Thread loading the stored accounts of the + * ProtocolProviderFactory services waiting in + * {@link #loadStoredAccountsQueue}. + */ + private Thread loadStoredAccountsThread; + + /** + * The Logger used by this AccountManagerImpl instance for + * logging output. + */ + private final Logger logger = Logger.getLogger(AccountManager.class); + + /** + * The list of AccountIDs, corresponding to all stored accounts. + */ + private final Vector storedAccounts = new Vector(); + + /** + * The prefix of the account unique identifier. + */ + private static final String ACCOUNT_UID_PREFIX = "acc"; + + /** + * Initializes a new AccountManagerImpl instance loaded in a + * specific BundleContext (in which the caller will usually + * later register it). + * + * @param bundleContext the BundleContext in which the new + * instance is loaded (and in which the caller will usually later + * register it as a service) + */ + public AccountManager(BundleContext bundleContext) + { + this.bundleContext = bundleContext; + + this.bundleContext.addServiceListener(new ServiceListener() + { + public void serviceChanged(ServiceEvent serviceEvent) + { + AccountManager.this.serviceChanged(serviceEvent); + } + }); + } + + /** + * Implements AccountManager#addListener(AccountManagerListener). + * @param listener the AccountManagerListener to add + */ + public void addListener(AccountManagerListener listener) + { + synchronized (listeners) + { + if (!listeners.contains(listener)) + listeners.add(listener); + } + } + + /** + * Loads the accounts stored for a specific + * ProtocolProviderFactory. + * + * @param factory the ProtocolProviderFactory to load the + * stored accounts of + */ + private void doLoadStoredAccounts(ProtocolProviderFactory factory) + { + ConfigurationService configService + = ProtocolProviderActivator.getConfigurationService(); + String factoryPackage = getFactoryImplPackageName(factory); + List accounts + = configService.getPropertyNamesByPrefix(factoryPackage, true); + + if (logger.isDebugEnabled()) + logger.debug("Discovered " + accounts.size() + " stored " + + factoryPackage + " accounts"); + + for (Iterator storedAccountIter = accounts.iterator(); + storedAccountIter.hasNext();) + { + String storedAccount = storedAccountIter.next(); + + // If the property is not related to an account we skip it. + int dotIndex = storedAccount.lastIndexOf("."); + if (!storedAccount.substring(dotIndex + 1) + .startsWith(ACCOUNT_UID_PREFIX)) + continue; + + if (logger.isDebugEnabled()) + logger.debug("Loading account " + storedAccount); + + List storedAccountProperties = + configService.getPropertyNamesByPrefix(storedAccount, false); + Map accountProperties = + new Hashtable(); + boolean disabled = false; + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + int prefLen = storedAccount.length() + 1; + for (Iterator storedAccountPropertyIter + = storedAccountProperties.iterator(); + storedAccountPropertyIter.hasNext();) + { + String property = storedAccountPropertyIter.next(); + String value = configService.getString(property); + + //strip the package prefix + if(prefLen > property.length()) + continue; + + property = property.substring(prefLen); + + if (ProtocolProviderFactory.IS_ACCOUNT_DISABLED.equals(property)) + disabled = Boolean.parseBoolean(value); + // Decode passwords. + else if (ProtocolProviderFactory.PASSWORD.equals(property) + && !credentialsStorage.isStoredEncrypted(storedAccount)) + { + if ((value != null) && value.length() != 0) + { + + /* + * TODO Converting byte[] to String using the platform's + * default charset may result in an invalid password. + */ + value = new String(Base64.decode(value)); + } + } + + if (value != null) + accountProperties.put(property, value); + } + + try + { + AccountID accountID = factory.createAccount(accountProperties); + + // If for some reason the account id is not created we move to + // the next account. + if (accountID == null) + continue; + + synchronized (storedAccounts) + { + storedAccounts.add(accountID); + } + if (!disabled) + factory.loadAccount(accountID); + } + catch (Exception ex) + { + /* + * Swallow the exception in order to prevent a single account + * from halting the loading of subsequent accounts. + */ + logger.error("Failed to load account " + accountProperties, ex); + } + catch (ExceptionInInitializerError ex) + { + // In case we fail to instantiate the ProtocolProviderService. + logger.error( + "Failed to create account service instance for account " + + accountProperties, ex); + } + } + } + + /** + * Notifies the registered {@link #listeners} that the stored accounts of a + * specific ProtocolProviderFactory have just been loaded. + * + * @param factory the ProtocolProviderFactory which had its + * stored accounts just loaded + */ + private void fireStoredAccountsLoaded(ProtocolProviderFactory factory) + { + AccountManagerListener[] listeners; + synchronized (this.listeners) + { + listeners = + this.listeners + .toArray(new AccountManagerListener[this.listeners.size()]); + } + + int listenerCount = listeners.length; + if (listenerCount > 0) + { + AccountManagerEvent event = + new AccountManagerEvent(this, + AccountManagerEvent.STORED_ACCOUNTS_LOADED, factory); + + for (int listenerIndex = 0; + listenerIndex < listenerCount; listenerIndex++) + { + listeners[listenerIndex].handleAccountManagerEvent(event); + } + } + } + + /** + * Returns the package name of the factory. + * @param factory the factory which package will be returned. + * @return the package name of the factory. + */ + public String getFactoryImplPackageName(ProtocolProviderFactory factory) + { + String className = factory.getClass().getName(); + + return className.substring(0, className.lastIndexOf('.')); + } + + /** + * Check for stored accounts for the supplied protocolName. + * @param protocolName the protocol name to check for + * @param includeHidden whether to include hidden providers + * @return true if there is any account stored in configuration + * service with protocolName, false otherwise. + */ + public boolean hasStoredAccounts(String protocolName, boolean includeHidden) + { + return hasStoredAccount(protocolName, includeHidden, null); + } + + /** + * Checks whether a stored account with userID is stored + * in configuration. + * + * @param protocolName the protocol name + * @param includeHidden whether to check hidden providers + * @param userID the user id to check. + * @return true if there is any account stored in configuration + * service with protocolName and userID, + * false otherwise. + */ + public boolean hasStoredAccount(String protocolName, + boolean includeHidden, + String userID) + { + Collection> factoryRefs + = ServiceUtils.getServiceReferences( + bundleContext, + ProtocolProviderFactory.class); + boolean hasStoredAccounts = false; + + if (!factoryRefs.isEmpty()) + { + ConfigurationService configService + = ProtocolProviderActivator.getConfigurationService(); + + for (ServiceReference factoryRef + : factoryRefs) + { + ProtocolProviderFactory factory + = bundleContext.getService(factoryRef); + + if ((protocolName != null) + && !protocolName.equals(factory.getProtocolName())) + { + continue; + } + + String factoryPackage = getFactoryImplPackageName(factory); + List storedAccounts + = configService + .getPropertyNamesByPrefix(factoryPackage + ".acc", + false); + + /* Ignore the hidden accounts. */ + for (Iterator storedAccountIter = + storedAccounts.iterator(); storedAccountIter.hasNext();) + { + String storedAccount = storedAccountIter.next(); + List storedAccountProperties = + configService.getPropertyNamesByPrefix(storedAccount, + true); + boolean hidden = false; + String accountUserID = null; + + if (!includeHidden || userID != null) + { + for (Iterator storedAccountPropertyIter = + storedAccountProperties.iterator(); + storedAccountPropertyIter.hasNext();) + { + String property = storedAccountPropertyIter.next(); + String value = configService.getString(property); + + property = stripPackagePrefix(property); + + if (ProtocolProviderFactory.IS_PROTOCOL_HIDDEN + .equals(property)) + { + hidden = (value != null); + } + else if (ProtocolProviderFactory.USER_ID + .equals(property)) + { + accountUserID = value; + } + } + } + + if (includeHidden || !hidden) + { + if(accountUserID != null + && userID != null + && userID.equals(accountUserID)) + { + hasStoredAccounts = true; + break; + } + else if(userID == null) + { + hasStoredAccounts = true; + break; + } + } + } + + if (hasStoredAccounts || (protocolName != null)) + { + break; + } + } + } + return hasStoredAccounts; + } + + /** + * Searches for stored account with uid in stored + * configuration. The uid is the one generated when creating + * accounts with prefix ACCOUNT_UID_PREFIX. + * + * @return AccountID if there is any account stored in configuration + * service with uid, + * null otherwise. + */ + public AccountID findAccountID(String uid) + { + Collection> factoryRefs + = ServiceUtils.getServiceReferences( + bundleContext, + ProtocolProviderFactory.class); + + if (!factoryRefs.isEmpty()) + { + ConfigurationService configService + = ProtocolProviderActivator.getConfigurationService(); + + for (ServiceReference factoryRef + : factoryRefs) + { + ProtocolProviderFactory factory + = bundleContext.getService(factoryRef); + + String factoryPackage = getFactoryImplPackageName(factory); + List storedAccountsProps + = configService + .getPropertyNamesByPrefix(factoryPackage, true); + + for (Iterator storedAccountIter = + storedAccountsProps.iterator(); + storedAccountIter.hasNext();) + { + String storedAccount = storedAccountIter.next(); + + if(!storedAccount.endsWith(uid)) + continue; + + String accountUID = configService.getString( + storedAccount //node id + + "." + ProtocolProviderFactory.ACCOUNT_UID);// propname + + for(AccountID acc : storedAccounts) + { + if(acc.getAccountUniqueID().equals(accountUID)) + return acc; + } + } + } + } + return null; + } + + /** + * Loads the accounts stored for a specific + * ProtocolProviderFactory and notifies the registered + * {@link #listeners} that the stored accounts of the specified + * factory have just been loaded + * + * @param factory the ProtocolProviderFactory to load the + * stored accounts of + */ + private void loadStoredAccounts(ProtocolProviderFactory factory) + { + doLoadStoredAccounts(factory); + + fireStoredAccountsLoaded(factory); + } + + /** + * Notifies this manager that a specific + * ProtocolProviderFactory has been registered as a service. + * The current implementation queues the specified factory to + * have its stored accounts as soon as possible. + * + * @param factory the ProtocolProviderFactory which has been + * registered as a service. + */ + private void protocolProviderFactoryRegistered( + ProtocolProviderFactory factory) + { + queueLoadStoredAccounts(factory); + } + + /** + * Queues a specific ProtocolProviderFactory to have its stored + * accounts loaded as soon as possible. + * + * @param factory the ProtocolProviderFactory to be queued for + * loading its stored accounts as soon as possible + */ + private void queueLoadStoredAccounts(ProtocolProviderFactory factory) + { + synchronized (loadStoredAccountsQueue) + { + loadStoredAccountsQueue.add(factory); + loadStoredAccountsQueue.notifyAll(); + + if (loadStoredAccountsThread == null) + { + loadStoredAccountsThread = new Thread() + { + @Override + public void run() + { + runInLoadStoredAccountsThread(); + } + }; + loadStoredAccountsThread.setDaemon(true); + loadStoredAccountsThread.setName( + "AccountManager.loadStoredAccounts"); + loadStoredAccountsThread.start(); + } + } + } + + /** + * Implements AccountManager#removeListener(AccountManagerListener). + * @param listener the AccountManagerListener to remove + */ + public void removeListener(AccountManagerListener listener) + { + synchronized (listeners) + { + listeners.remove(listener); + } + } + + /** + * Running in {@link #loadStoredAccountsThread}, loads the stored accounts + * of the ProtocolProviderFactory services waiting in + * {@link #loadStoredAccountsQueue} + */ + private void runInLoadStoredAccountsThread() + { + boolean interrupted = false; + while (!interrupted) + { + try + { + ProtocolProviderFactory factory; + + synchronized (loadStoredAccountsQueue) + { + factory = loadStoredAccountsQueue.poll(); + if (factory == null) + { + /* + * Technically, we should be handing spurious wakeups. + * However, we cannot check the condition in a queue. + * Anyway, we just want to keep this Thread alive long + * enough to allow it to not be re-created multiple + * times and not handing a spurious wakeup will just + * cause such an inconvenience. + */ + try + { + loadStoredAccountsQueue + .wait(LOAD_STORED_ACCOUNTS_TIMEOUT); + } + catch (InterruptedException ex) + { + logger + .warn( + "The loading of the stored accounts has" + + " been interrupted", + ex); + interrupted = true; + break; + } + factory = loadStoredAccountsQueue.poll(); + } + if (factory != null) + loadStoredAccountsQueue.notifyAll(); + } + + if (factory != null) + { + try + { + loadStoredAccounts(factory); + } + catch (Exception ex) + { + + /* + * Swallow the exception in order to prevent a single + * factory from halting the loading of subsequent + * factories. + */ + logger.error("Failed to load accounts for " + factory, + ex); + } + } + } + finally + { + synchronized (loadStoredAccountsQueue) + { + if (!interrupted && (loadStoredAccountsQueue.size() <= 0)) + { + if (loadStoredAccountsThread == Thread.currentThread()) + { + loadStoredAccountsThread = null; + loadStoredAccountsQueue.notifyAll(); + } + break; + } + } + } + } + } + + /** + * Notifies this manager that an OSGi service has changed. The current + * implementation tracks the registrations of + * ProtocolProviderFactory services in order to queue them for + * loading their stored accounts. + * + * @param serviceEvent the ServiceEvent containing the event + * data + */ + private void serviceChanged(ServiceEvent serviceEvent) + { + switch (serviceEvent.getType()) + { + case ServiceEvent.REGISTERED: + Object service + = bundleContext.getService(serviceEvent.getServiceReference()); + + if (service instanceof ProtocolProviderFactory) + { + protocolProviderFactoryRegistered( + (ProtocolProviderFactory) service); + } + break; + default: + break; + } + } + + /** + * Stores an account represented in the form of an AccountID + * created by a specific ProtocolProviderFactory. + * + * @param factory the ProtocolProviderFactory which created the + * account to be stored + * @param accountID the account in the form of AccountID to be + * stored + * @throws OperationFailedException if anything goes wrong while storing the + * account + */ + public void storeAccount( + ProtocolProviderFactory factory, + AccountID accountID) + throws OperationFailedException + { + synchronized (storedAccounts) + { + if (!storedAccounts.contains(accountID)) + storedAccounts.add(accountID); + } + + ConfigurationService configurationService + = ProtocolProviderActivator.getConfigurationService(); + String factoryPackage = getFactoryImplPackageName(factory); + + String accountNodeName + = getAccountNodeName( factory, + accountID.getAccountUniqueID() ); + + Map configurationProperties + = new HashMap(); + + // Create a unique node name of the properties node that will contain + // this account's properties. + if (accountNodeName == null) + { + accountNodeName + = ACCOUNT_UID_PREFIX + Long.toString(System.currentTimeMillis()); + + // set a value for the persistent node so that we could later + // retrieve it as a property + configurationProperties.put( + factoryPackage /* prefix */ + "." + accountNodeName, + accountNodeName); + + // register the account in the configuration service. + // we register all the properties in the following hierarchy + //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME + configurationProperties.put(factoryPackage// prefix + + "." + accountNodeName // node name for the account id + + "." + ProtocolProviderFactory.ACCOUNT_UID, // propname + accountID.getAccountUniqueID()); // value + } + + // store the rest of the properties + Map accountProperties = accountID.getAccountProperties(); + + for (Map.Entry entry : accountProperties.entrySet()) + { + String property = entry.getKey(); + String value = entry.getValue(); + String secureStorePrefix = null; + + // If the property is a password, store it securely. + if (property.equals(ProtocolProviderFactory.PASSWORD)) + { + String accountPrefix = factoryPackage + "." + accountNodeName; + secureStorePrefix = accountPrefix; + } + else if(property.endsWith("." + ProtocolProviderFactory.PASSWORD)) + { + secureStorePrefix = factoryPackage + "." + accountNodeName + + "." + property.substring(0, property.lastIndexOf(".")); + } + + if(secureStorePrefix != null) + { + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + + // encrypt and store + if ((value != null) + && (value.length() != 0) + && !credentialsStorage.storePassword( + secureStorePrefix, + value)) + { + throw + new OperationFailedException( + "CredentialsStorageService failed to" + + " storePassword", + OperationFailedException.GENERAL_ERROR); + } + } + else + { + configurationProperties.put( + factoryPackage // prefix + + "." + accountNodeName // a unique node name for the account id + + "." + property, // propname + value); // value + } + } + + // clear the password if missing property, modification can request + // password delete + if(!accountProperties.containsKey(ProtocolProviderFactory.PASSWORD) + && // And only if it's not stored already in encrypted form. + // Account registration object clears also this property + // in order to forget the password + !configurationProperties.containsKey( + factoryPackage+"."+accountNodeName+".ENCRYPTED_PASSWORD")) + { + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + credentialsStorage.removePassword( + factoryPackage + "." + accountNodeName); + } + + if (configurationProperties.size() > 0) + configurationService.setProperties(configurationProperties); + + if (logger.isDebugEnabled()) + logger.debug("Stored account for id " + accountID.getAccountUniqueID() + + " for package " + factoryPackage); + } + + /** + * Gets account node name under which account configuration properties are + * stored. + * + * @param factory account's protocol provider factory + * @param accountUID account for which the prefix will be returned + * @return configuration prefix for given accountID if exists or + * null otherwise + */ + public String getAccountNodeName( ProtocolProviderFactory factory, + String accountUID ) + { + ConfigurationService configurationService + = ProtocolProviderActivator.getConfigurationService(); + String factoryPackage = getFactoryImplPackageName(factory); + + // First check if such accountID already exists in the configuration. + List storedAccounts = + configurationService.getPropertyNamesByPrefix(factoryPackage, true); + String accountNodeName = null; + + for (Iterator storedAccountIter = storedAccounts.iterator(); + storedAccountIter.hasNext();) + { + String storedAccount = storedAccountIter.next(); + + // If the property is not related to an account we skip it. + int dotIndex = storedAccount.lastIndexOf("."); + if (!storedAccount.substring(dotIndex + 1) + .startsWith(ACCOUNT_UID_PREFIX)) + continue; + + String storedAccountUID + = configurationService.getString( + storedAccount + "." + ProtocolProviderFactory.ACCOUNT_UID); + + if(storedAccountUID == null) + continue; + + if (storedAccountUID.equals(accountUID)) + accountNodeName = configurationService.getString(storedAccount); + } + return accountNodeName; + } + + /** + * Removes the account with accountID from the set of accounts + * that are persistently stored inside the configuration service. + * + * @param factory the ProtocolProviderFactory which created the + * account to be stored + * @param accountID the AccountID of the account to remove. + * @return true if an account has been removed and false otherwise. + */ + public boolean removeStoredAccount(ProtocolProviderFactory factory, + AccountID accountID) + { + synchronized (storedAccounts) + { + if (storedAccounts.contains(accountID)) + storedAccounts.remove(accountID); + } + + /* + * We're already doing it in #unloadAccount(AccountID) - we're figuring + * out the ProtocolProviderFactory by the AccountID. + */ + if (factory == null) + { + factory + = ProtocolProviderActivator.getProtocolProviderFactory( + accountID.getProtocolName()); + } + + String factoryPackage = getFactoryImplPackageName(factory); + + // remove the stored password explicitly using credentials service + CredentialsStorageService credentialsStorage + = ServiceUtils.getService( + bundleContext, + CredentialsStorageService.class); + String accountPrefix = + ProtocolProviderFactory.findAccountPrefix(bundleContext, accountID, + factoryPackage); + + credentialsStorage.removePassword(accountPrefix); + + ConfigurationService configurationService + = ServiceUtils.getService( + bundleContext, + ConfigurationService.class); + //first retrieve all accounts that we've registered + List storedAccounts + = configurationService.getPropertyNamesByPrefix( + factoryPackage, true); + + //find an account with the corresponding id. + for (String accountRootPropertyName : storedAccounts) + { + //unregister the account in the configuration service. + //all the properties must have been registered in the following + //hierarchy: + //net.java.sip.communicator.impl.protocol.PROTO_NAME.ACC_ID.PROP_NAME + String accountUID = configurationService.getString( + accountRootPropertyName //node id + + "." + ProtocolProviderFactory.ACCOUNT_UID); // propname + + if (accountID.getAccountUniqueID().equals(accountUID)) + { + //retrieve the names of all properties registered for the + //current account. + List accountPropertyNames + = configurationService.getPropertyNamesByPrefix( + accountRootPropertyName, false); + + //set all account properties to null in order to remove them. + for (String propName : accountPropertyNames) + configurationService.setProperty(propName, null); + + //and now remove the parent too. + configurationService.setProperty(accountRootPropertyName, null); + return true; + } + } + return false; + } + + /** + * Removes all accounts which have been persistently stored. + * + * @see #removeStoredAccount(ProtocolProviderFactory, AccountID) + */ + public void removeStoredAccounts() + { + synchronized (loadStoredAccountsQueue) + { + /* + * Wait for the Thread which loads the stored account to complete so + * that we can be sure later on that it will not load a stored + * account while we are deleting it or another one for that matter. + */ + boolean interrupted = false; + + while (loadStoredAccountsThread != null) + try + { + loadStoredAccountsQueue.wait(LOAD_STORED_ACCOUNTS_TIMEOUT); + } + catch (InterruptedException ie) + { + interrupted = true; + } + if (interrupted) + Thread.currentThread().interrupt(); + + synchronized (this.storedAccounts) + { + AccountID[] storedAccounts + = this.storedAccounts.toArray( + new AccountID[this.storedAccounts.size()]); + + for (AccountID storedAccount : storedAccounts) + { + ProtocolProviderFactory ppf + = ProtocolProviderActivator.getProtocolProviderFactory( + storedAccount.getProtocolName()); + + if (ppf != null) + ppf.uninstallAccount(storedAccount); + } + } + } + } + + /** + * Returns an Iterator over a list of all stored + * AccountIDs. The list of stored accounts include all registered + * accounts and all disabled accounts. In other words in this list we could + * find accounts that aren't loaded. + *

    + * In order to check if an account is already loaded please use the + * #isAccountLoaded(AccountID accountID) method. To load an account use the + * #loadAccount(AccountID accountID) method. + * + * @return an Iterator over a list of all stored + * AccountIDs + */ + public Collection getStoredAccounts() + { + synchronized (storedAccounts) + { + return new Vector(storedAccounts); + } + } + + /** + * Loads the account corresponding to the given AccountID. An + * account is loaded when its ProtocolProviderService is registered + * in the bundle context. This method is meant to load the account through + * the corresponding ProtocolProviderFactory. + * + * @param accountID the identifier of the account to load + * @throws OperationFailedException if anything goes wrong while loading the + * account corresponding to the specified accountID + */ + public void loadAccount(AccountID accountID) + throws OperationFailedException + { + // If the account with the given id is already loaded we have nothing + // to do here. + if (isAccountLoaded(accountID)) + return; + + ProtocolProviderFactory providerFactory + = ProtocolProviderActivator.getProtocolProviderFactory( + accountID.getProtocolName()); + + if(providerFactory.loadAccount(accountID)) + { + accountID.putAccountProperty( + ProtocolProviderFactory.IS_ACCOUNT_DISABLED, + String.valueOf(false)); + // Finally store the modified properties. + storeAccount(providerFactory, accountID); + } + } + + /** + * Unloads the account corresponding to the given AccountID. An + * account is unloaded when its ProtocolProviderService is + * unregistered in the bundle context. This method is meant to unload the + * account through the corresponding ProtocolProviderFactory. + * + * @param accountID the identifier of the account to load + * @throws OperationFailedException if anything goes wrong while unloading + * the account corresponding to the specified accountID + */ + public void unloadAccount(AccountID accountID) + throws OperationFailedException + { + // If the account with the given id is already unloaded we have nothing + // to do here. + if (!isAccountLoaded(accountID)) + return; + + ProtocolProviderFactory providerFactory + = ProtocolProviderActivator.getProtocolProviderFactory( + accountID.getProtocolName()); + + // Obtain the protocol provider. + ServiceReference serRef + = providerFactory.getProviderForAccount(accountID); + + // If there's no such provider we have nothing to do here. + if (serRef == null) + return; + + ProtocolProviderService protocolProvider + = bundleContext.getService(serRef); + + // Set the account icon path for unloaded accounts. + String iconPathProperty = accountID.getAccountPropertyString( + ProtocolProviderFactory.ACCOUNT_ICON_PATH); + + if (iconPathProperty == null) + { + accountID.putAccountProperty( + ProtocolProviderFactory.ACCOUNT_ICON_PATH, + protocolProvider.getProtocolIcon() + .getIconPath(ProtocolIcon.ICON_SIZE_32x32)); + } + + accountID.putAccountProperty( + ProtocolProviderFactory.IS_ACCOUNT_DISABLED, + String.valueOf(true)); + + if (!providerFactory.unloadAccount(accountID)) + { + accountID.putAccountProperty( + ProtocolProviderFactory.IS_ACCOUNT_DISABLED, + String.valueOf(false)); + } + // Finally store the modified properties. + storeAccount(providerFactory, accountID); + } + + /** + * Checks if the account corresponding to the given accountID is + * loaded. An account is loaded if its ProtocolProviderService is + * registered in the bundle context. By default all accounts are loaded. + * However the user could manually unload an account, which would be + * unregistered from the bundle context, but would remain in the + * configuration file. + * + * @param accountID the identifier of the account to load + * @return true to indicate that the account with the given + * accountID is loaded, false - otherwise + */ + public boolean isAccountLoaded(AccountID accountID) + { + return storedAccounts.contains(accountID) && accountID.isEnabled(); + } + + private String stripPackagePrefix(String property) + { + int packageEndIndex = property.lastIndexOf('.'); + + if (packageEndIndex != -1) + property = property.substring(packageEndIndex + 1); + return property; + } +} diff --git a/test/net/java/sip/communicator/slick/popupmessagehandler/PopupMessageHandlerSLick.java b/test/net/java/sip/communicator/slick/popupmessagehandler/PopupMessageHandlerSLick.java index 10a89bc..0cc63a8 100644 --- a/test/net/java/sip/communicator/slick/popupmessagehandler/PopupMessageHandlerSLick.java +++ b/test/net/java/sip/communicator/slick/popupmessagehandler/PopupMessageHandlerSLick.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,54 +15,54 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.slick.popupmessagehandler; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.systray.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * - * @author Symphorien Wanko - */ -public class PopupMessageHandlerSLick extends TestSuite implements BundleActivator -{ - /** Logger for this class */ - private static Logger logger = - Logger.getLogger(PopupMessageHandlerSLick.class); - - /** our bundle context */ - protected static BundleContext bundleContext = null; - - /** implements BundleActivator.start() */ - public void start(BundleContext bc) throws Exception - { - logger.info("starting popup message test "); - - bundleContext = bc; - - setName("PopupMessageHandlerSLick"); - - Hashtable properties = new Hashtable(); - - properties.put("service.pid", getName()); - - // we maybe are running on machine without WM and systray - // (test server machine), skip tests - if(ServiceUtils.getService(bc, SystrayService.class) != null) - { - addTest(TestPopupMessageHandler.suite()); - } - - bundleContext.registerService(getClass().getName(), this, properties); - } - - /** implements BundleActivator.stop() */ - public void stop(BundleContext bc) throws Exception - {} - -} +package net.java.sip.communicator.slick.popupmessagehandler; + +import java.util.*; + +import junit.framework.*; +import net.java.sip.communicator.service.systray.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * + * @author Symphorien Wanko + */ +public class PopupMessageHandlerSLick extends TestSuite implements BundleActivator +{ + /** Logger for this class */ + private static Logger logger = + Logger.getLogger(PopupMessageHandlerSLick.class); + + /** our bundle context */ + protected static BundleContext bundleContext = null; + + /** implements BundleActivator.start() */ + public void start(BundleContext bc) throws Exception + { + logger.info("starting popup message test "); + + bundleContext = bc; + + setName("PopupMessageHandlerSLick"); + + Hashtable properties = new Hashtable(); + + properties.put("service.pid", getName()); + + // we maybe are running on machine without WM and systray + // (test server machine), skip tests + if(ServiceUtils.getService(bc, SystrayService.class) != null) + { + addTest(TestPopupMessageHandler.suite()); + } + + bundleContext.registerService(getClass().getName(), this, properties); + } + + /** implements BundleActivator.stop() */ + public void stop(BundleContext bc) throws Exception + {} + +} diff --git a/test/net/java/sip/communicator/slick/protocol/sip/TestAutoProxyDetection.java b/test/net/java/sip/communicator/slick/protocol/sip/TestAutoProxyDetection.java index 948dd9d..e5e9511 100644 --- a/test/net/java/sip/communicator/slick/protocol/sip/TestAutoProxyDetection.java +++ b/test/net/java/sip/communicator/slick/protocol/sip/TestAutoProxyDetection.java @@ -1,4 +1,4 @@ -/* +/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd @@ -15,487 +15,487 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.java.sip.communicator.slick.protocol.sip; - -import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.USER_ID; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; - -import java.net.*; -import java.text.*; - -import junit.framework.*; -import net.java.sip.communicator.impl.protocol.sip.*; -import net.java.sip.communicator.impl.protocol.sip.net.*; -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.util.*; - -/** - * Tests all variations of automatic proxy detection through (simulated) DNS. - * - * @author Ingo Bauersachs - */ -public class TestAutoProxyDetection - extends TestCase -{ - private static class TestedAutoProxyDetection extends AutoProxyConnection - { - public TestedAutoProxyDetection(SipAccountIDImpl account, - String defaultTransport) - { - super(account, defaultTransport); - } - - @Override - public void setNetworkUtils(LocalNetworkUtils nu) - { - super.setNetworkUtils(nu); - } - - public static class NetworkUtils extends LocalNetworkUtils - { - } - } - - private SipAccountIDImpl account; - private TestedAutoProxyDetection.NetworkUtils nu; - private SRVRecord srv1; - private SRVRecord srv2; - private SRVRecord srv3; - private InetSocketAddress a1; - private InetSocketAddress a2; - private InetSocketAddress a3; - private InetSocketAddress a4; - private final static String DOMAIN = "example.com"; - private InetAddress ia1; - private InetAddress ia2; - private InetAddress ia3; - private InetAddress ia4; - private TestedAutoProxyDetection apd; - - @Override - public void setUp() - { - account = createMock(SipAccountIDImpl.class); - expect(account.getAccountPropertyString(USER_ID)) - .andReturn("unit@" + DOMAIN); - replay(account); - - nu = createMock(TestedAutoProxyDetection.NetworkUtils.class); - apd = new TestedAutoProxyDetection(account, "UDP"); - apd.setNetworkUtils(nu); - - srv1 = createMock(SRVRecord.class); - expect(srv1.getTarget()).andReturn("proxy1."+DOMAIN); - expect(srv1.getPort()).andReturn(5060); - srv2 = createMock(SRVRecord.class); - expect(srv2.getTarget()).andReturn("proxy2."+DOMAIN); - expect(srv2.getPort()).andReturn(5061); - srv3 = createMock(SRVRecord.class); - expect(srv3.getTarget()).andReturn("proxy3."+DOMAIN); - expect(srv3.getPort()).andReturn(5062); - try - { - ia1 = InetAddress.getByAddress("proxy1." + DOMAIN, - new byte[]{0x7f,0,0,1}); - ia2 = InetAddress.getByAddress("proxy2." + DOMAIN, - new byte[]{0x7f,0,0,2}); - ia3 = InetAddress.getByAddress("proxy3." + DOMAIN, - new byte[]{0x7f,0,0,3}); - ia4 = InetAddress.getByAddress("proxy4." + DOMAIN, - new byte[]{0x7f,0,0,4}); - } - catch (UnknownHostException e) - { - fail("unable to initialize: " + e.getMessage()); - } - a1 = new InetSocketAddress(ia1, 5060); - a2 = new InetSocketAddress(ia2, 5061); - a3 = new InetSocketAddress(ia3, 5062); - a4 = new InetSocketAddress(ia4, 5063); - } - - private void prepareOneNaptrOneSrv() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ - {"0", "udp", "_sip._udp." + DOMAIN} - }); - expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) - .andReturn(new SRVRecord[]{ srv1 }); - } - - private void prepareOneNaptrTwoSrv() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ - {"0", "udp", "_sip._udp." + DOMAIN} - }); - expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) - .andReturn(new SRVRecord[]{ srv1, srv2 }); - } - - public void testOneNaptrNoSrv() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ - {"0", "udp", "_sip._udp." + DOMAIN} - }); - expect(nu.getSRVRecords("_sip._udp." + DOMAIN)).andReturn(null); - replay(nu); - - assertFalse(apd.getNextAddress()); - verify(account, nu); - } - - public void testOneNaptrOneSrvOneA() throws ParseException, DnssecException - { - prepareOneNaptrOneSrv(); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - replay(nu, srv1); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } - - public void testOneNaptrOneSrvTwoA() throws ParseException, DnssecException - { - prepareOneNaptrOneSrv(); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1, a2}); - replay(nu, srv1); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } - - //----------------------- - - public void testOneNaptrTwoSrvOneA() throws ParseException, DnssecException - { - prepareOneNaptrTwoSrv(); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) - .andReturn(new InetSocketAddress[]{a2}); - replay(nu, srv1, srv2); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1, srv2); - } - - public void testOneNaptrTwoSrvTwoA() throws ParseException, DnssecException - { - prepareOneNaptrTwoSrv(); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1, a2}); - expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) - .andReturn(new InetSocketAddress[]{a3, a4}); - replay(nu, srv1, srv2); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a3, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a4, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1, srv2); - } - - //------------------- - - public void testThreeNaptrOneSrvEachOneAEach() - throws ParseException, - DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ - {"0", "udp", "_sip._udp." + DOMAIN}, - {"0", "tcp", "_sip._tcp." + DOMAIN}, - {"0", "tls", "_sips._tcp." + DOMAIN} - }); - expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) - .andReturn(new SRVRecord[]{ srv1 }); - expect(nu.getSRVRecords("_sip._tcp."+DOMAIN)) - .andReturn(new SRVRecord[]{ srv2 }); - expect(nu.getSRVRecords("_sips._tcp."+DOMAIN)) - .andReturn(new SRVRecord[]{ srv3 }); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy3." + DOMAIN, 5062)) - .andReturn(new InetSocketAddress[]{a1}); - - replay(nu, srv1, srv2, srv3); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("TCP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("TLS", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1, srv2, srv3); - } - - //----------------------- - - public void testNoSrvOneA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); - expect(nu.getAandAAAARecords(DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - - replay(nu); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu); - } - - public void testOneSrvNoA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) - .andReturn(new SRVRecord[]{srv1}); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(null); - - replay(nu, srv1); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } - - public void testOneSrvOneA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) - .andReturn(new SRVRecord[]{srv1}); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - - replay(nu, srv1); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } - - public void testOneSrvTwoA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) - .andReturn(new SRVRecord[]{srv1}); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1, a2}); - - replay(nu, srv1); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } - - public void testTwoSrvOneA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)) - .andReturn(new SRVRecord[]{srv2}); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) - .andReturn(new SRVRecord[]{srv1}); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) - .andReturn(new InetSocketAddress[]{a2}); - - replay(nu, srv1, srv2); - - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("TLS", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1, srv2); - } - - public void testTwoSameSrvOneA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)) - .andReturn(new SRVRecord[]{srv1, srv2}); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) - .andReturn(new InetSocketAddress[]{a2}); - - replay(nu, srv1, srv2); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("TLS", apd.getTransport()); - assertEquals(5060, apd.getAddress().getPort()); - - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("TLS", apd.getTransport()); - assertEquals(5061, apd.getAddress().getPort()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1, srv2); - } - - //---------------------- - - public void testNoA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); - expect(nu.getAandAAAARecords(DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{}); - - replay(nu); - - assertFalse(apd.getNextAddress()); - verify(account, nu); - } - - public void testOneA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); - expect(nu.getAandAAAARecords(DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - - replay(nu); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu); - } - - public void testTwoA() throws ParseException, DnssecException - { - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); - expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); - expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); - expect(nu.getAandAAAARecords(DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1, a2}); - - replay(nu); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertTrue(apd.getNextAddress()); - assertEquals(a2, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu); - } - - public void testNotReturningSameAddressTwice() - throws ParseException, - DnssecException - { - expect(srv1.getTarget()).andReturn("proxy1."+DOMAIN); - expect(srv1.getPort()).andReturn(5060); - expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ - {"0", "udp", "_sip._udp." + DOMAIN}, - {"1", "udp", "_sip._udp." + DOMAIN} - }); - expect(nu.getSRVRecords("_sip._udp."+DOMAIN)).andReturn(new SRVRecord[]{ - srv1 - }); - expect(nu.getSRVRecords("_sip._udp."+DOMAIN)).andReturn(new SRVRecord[]{ - srv1 - }); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) - .andReturn(new InetSocketAddress[]{a1}); - - replay(nu, srv1); - - assertTrue(apd.getNextAddress()); - assertEquals(a1, apd.getAddress()); - assertEquals("UDP", apd.getTransport()); - - assertFalse(apd.getNextAddress()); - verify(account, nu, srv1); - } -} +package net.java.sip.communicator.slick.protocol.sip; + +import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.USER_ID; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.net.*; +import java.text.*; + +import junit.framework.*; +import net.java.sip.communicator.impl.protocol.sip.*; +import net.java.sip.communicator.impl.protocol.sip.net.*; +import net.java.sip.communicator.service.dns.*; +import net.java.sip.communicator.util.*; + +/** + * Tests all variations of automatic proxy detection through (simulated) DNS. + * + * @author Ingo Bauersachs + */ +public class TestAutoProxyDetection + extends TestCase +{ + private static class TestedAutoProxyDetection extends AutoProxyConnection + { + public TestedAutoProxyDetection(SipAccountIDImpl account, + String defaultTransport) + { + super(account, defaultTransport); + } + + @Override + public void setNetworkUtils(LocalNetworkUtils nu) + { + super.setNetworkUtils(nu); + } + + public static class NetworkUtils extends LocalNetworkUtils + { + } + } + + private SipAccountIDImpl account; + private TestedAutoProxyDetection.NetworkUtils nu; + private SRVRecord srv1; + private SRVRecord srv2; + private SRVRecord srv3; + private InetSocketAddress a1; + private InetSocketAddress a2; + private InetSocketAddress a3; + private InetSocketAddress a4; + private final static String DOMAIN = "example.com"; + private InetAddress ia1; + private InetAddress ia2; + private InetAddress ia3; + private InetAddress ia4; + private TestedAutoProxyDetection apd; + + @Override + public void setUp() + { + account = createMock(SipAccountIDImpl.class); + expect(account.getAccountPropertyString(USER_ID)) + .andReturn("unit@" + DOMAIN); + replay(account); + + nu = createMock(TestedAutoProxyDetection.NetworkUtils.class); + apd = new TestedAutoProxyDetection(account, "UDP"); + apd.setNetworkUtils(nu); + + srv1 = createMock(SRVRecord.class); + expect(srv1.getTarget()).andReturn("proxy1."+DOMAIN); + expect(srv1.getPort()).andReturn(5060); + srv2 = createMock(SRVRecord.class); + expect(srv2.getTarget()).andReturn("proxy2."+DOMAIN); + expect(srv2.getPort()).andReturn(5061); + srv3 = createMock(SRVRecord.class); + expect(srv3.getTarget()).andReturn("proxy3."+DOMAIN); + expect(srv3.getPort()).andReturn(5062); + try + { + ia1 = InetAddress.getByAddress("proxy1." + DOMAIN, + new byte[]{0x7f,0,0,1}); + ia2 = InetAddress.getByAddress("proxy2." + DOMAIN, + new byte[]{0x7f,0,0,2}); + ia3 = InetAddress.getByAddress("proxy3." + DOMAIN, + new byte[]{0x7f,0,0,3}); + ia4 = InetAddress.getByAddress("proxy4." + DOMAIN, + new byte[]{0x7f,0,0,4}); + } + catch (UnknownHostException e) + { + fail("unable to initialize: " + e.getMessage()); + } + a1 = new InetSocketAddress(ia1, 5060); + a2 = new InetSocketAddress(ia2, 5061); + a3 = new InetSocketAddress(ia3, 5062); + a4 = new InetSocketAddress(ia4, 5063); + } + + private void prepareOneNaptrOneSrv() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ + {"0", "udp", "_sip._udp." + DOMAIN} + }); + expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) + .andReturn(new SRVRecord[]{ srv1 }); + } + + private void prepareOneNaptrTwoSrv() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ + {"0", "udp", "_sip._udp." + DOMAIN} + }); + expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) + .andReturn(new SRVRecord[]{ srv1, srv2 }); + } + + public void testOneNaptrNoSrv() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ + {"0", "udp", "_sip._udp." + DOMAIN} + }); + expect(nu.getSRVRecords("_sip._udp." + DOMAIN)).andReturn(null); + replay(nu); + + assertFalse(apd.getNextAddress()); + verify(account, nu); + } + + public void testOneNaptrOneSrvOneA() throws ParseException, DnssecException + { + prepareOneNaptrOneSrv(); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + replay(nu, srv1); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } + + public void testOneNaptrOneSrvTwoA() throws ParseException, DnssecException + { + prepareOneNaptrOneSrv(); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1, a2}); + replay(nu, srv1); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } + + //----------------------- + + public void testOneNaptrTwoSrvOneA() throws ParseException, DnssecException + { + prepareOneNaptrTwoSrv(); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) + .andReturn(new InetSocketAddress[]{a2}); + replay(nu, srv1, srv2); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1, srv2); + } + + public void testOneNaptrTwoSrvTwoA() throws ParseException, DnssecException + { + prepareOneNaptrTwoSrv(); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1, a2}); + expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) + .andReturn(new InetSocketAddress[]{a3, a4}); + replay(nu, srv1, srv2); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a3, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a4, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1, srv2); + } + + //------------------- + + public void testThreeNaptrOneSrvEachOneAEach() + throws ParseException, + DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ + {"0", "udp", "_sip._udp." + DOMAIN}, + {"0", "tcp", "_sip._tcp." + DOMAIN}, + {"0", "tls", "_sips._tcp." + DOMAIN} + }); + expect(nu.getSRVRecords("_sip._udp."+DOMAIN)) + .andReturn(new SRVRecord[]{ srv1 }); + expect(nu.getSRVRecords("_sip._tcp."+DOMAIN)) + .andReturn(new SRVRecord[]{ srv2 }); + expect(nu.getSRVRecords("_sips._tcp."+DOMAIN)) + .andReturn(new SRVRecord[]{ srv3 }); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy3." + DOMAIN, 5062)) + .andReturn(new InetSocketAddress[]{a1}); + + replay(nu, srv1, srv2, srv3); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("TCP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("TLS", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1, srv2, srv3); + } + + //----------------------- + + public void testNoSrvOneA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); + expect(nu.getAandAAAARecords(DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + + replay(nu); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu); + } + + public void testOneSrvNoA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) + .andReturn(new SRVRecord[]{srv1}); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(null); + + replay(nu, srv1); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } + + public void testOneSrvOneA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) + .andReturn(new SRVRecord[]{srv1}); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + + replay(nu, srv1); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } + + public void testOneSrvTwoA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) + .andReturn(new SRVRecord[]{srv1}); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1, a2}); + + replay(nu, srv1); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } + + public void testTwoSrvOneA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)) + .andReturn(new SRVRecord[]{srv2}); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)) + .andReturn(new SRVRecord[]{srv1}); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) + .andReturn(new InetSocketAddress[]{a2}); + + replay(nu, srv1, srv2); + + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("TLS", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1, srv2); + } + + public void testTwoSameSrvOneA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)) + .andReturn(new SRVRecord[]{srv1, srv2}); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy2." + DOMAIN, 5061)) + .andReturn(new InetSocketAddress[]{a2}); + + replay(nu, srv1, srv2); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("TLS", apd.getTransport()); + assertEquals(5060, apd.getAddress().getPort()); + + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("TLS", apd.getTransport()); + assertEquals(5061, apd.getAddress().getPort()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1, srv2); + } + + //---------------------- + + public void testNoA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); + expect(nu.getAandAAAARecords(DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{}); + + replay(nu); + + assertFalse(apd.getNextAddress()); + verify(account, nu); + } + + public void testOneA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); + expect(nu.getAandAAAARecords(DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + + replay(nu); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu); + } + + public void testTwoA() throws ParseException, DnssecException + { + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{}); + expect(nu.getSRVRecords("sips", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "TCP", DOMAIN)).andReturn(null); + expect(nu.getSRVRecords("sip", "UDP", DOMAIN)).andReturn(null); + expect(nu.getAandAAAARecords(DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1, a2}); + + replay(nu); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertTrue(apd.getNextAddress()); + assertEquals(a2, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu); + } + + public void testNotReturningSameAddressTwice() + throws ParseException, + DnssecException + { + expect(srv1.getTarget()).andReturn("proxy1."+DOMAIN); + expect(srv1.getPort()).andReturn(5060); + expect(nu.getNAPTRRecords(DOMAIN)).andReturn(new String[][]{ + {"0", "udp", "_sip._udp." + DOMAIN}, + {"1", "udp", "_sip._udp." + DOMAIN} + }); + expect(nu.getSRVRecords("_sip._udp."+DOMAIN)).andReturn(new SRVRecord[]{ + srv1 + }); + expect(nu.getSRVRecords("_sip._udp."+DOMAIN)).andReturn(new SRVRecord[]{ + srv1 + }); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + expect(nu.getAandAAAARecords("proxy1." + DOMAIN, 5060)) + .andReturn(new InetSocketAddress[]{a1}); + + replay(nu, srv1); + + assertTrue(apd.getNextAddress()); + assertEquals(a1, apd.getAddress()); + assertEquals("UDP", apd.getTransport()); + + assertFalse(apd.getNextAddress()); + verify(account, nu, srv1); + } +} -- cgit v1.1 From 6f50b84df3d6a9536413ca3d51ccf812bbb0cb6c Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 28 Feb 2016 22:12:29 +0100 Subject: Remove the Facebook protocol wizard Facebook disabled their XMPP API. See also: https://developers.facebook.com/docs/chat --- build.xml | 14 +- lib/felix.client.run.properties | 1 - lib/jitsi-defaults.properties | 3 +- m2/jitsi-protocol/pom.xml | 2 - resources/images/images.properties | 4 - .../images/protocol/facebook/facebook-online.png | Bin 537 -> 0 bytes resources/images/protocol/facebook/facebook48.png | Bin 1521 -> 0 bytes resources/images/protocol/facebook/logo32x32.png | Bin 1500 -> 0 bytes resources/images/protocol/facebook/logo48x48.png | Bin 2155 -> 0 bytes resources/images/protocol/facebook/logo64x64.png | Bin 2507 -> 0 bytes .../images/protocol/facebook/status16x16-away.png | Bin 786 -> 0 bytes .../protocol/facebook/status16x16-connecting.gif | Bin 522 -> 0 bytes .../protocol/facebook/status16x16-connecting.png | Bin 694 -> 0 bytes .../images/protocol/facebook/status16x16-dnd.png | Bin 773 -> 0 bytes .../images/protocol/facebook/status16x16-ffc.png | Bin 871 -> 0 bytes .../protocol/facebook/status16x16-invisible.png | Bin 787 -> 0 bytes .../protocol/facebook/status16x16-meeting.png | Bin 1829 -> 0 bytes .../protocol/facebook/status16x16-offline.png | Bin 490 -> 0 bytes .../protocol/facebook/status16x16-online.png | Bin 537 -> 0 bytes .../images/protocol/facebook/status16x16-phone.png | Bin 816 -> 0 bytes .../images/protocol/facebook/status16x16-xa.png | Bin 756 -> 0 bytes resources/languages/resources.properties | 7 - .../FacebookAccRegWizzActivator.java | 213 --------------- .../FacebookAccountRegistrationWizard.java | 300 --------------------- .../facebookaccregwizz.manifest.mf | 34 --- .../service/protocol/ProtocolNames.java | 5 - 26 files changed, 2 insertions(+), 581 deletions(-) delete mode 100644 resources/images/protocol/facebook/facebook-online.png delete mode 100644 resources/images/protocol/facebook/facebook48.png delete mode 100644 resources/images/protocol/facebook/logo32x32.png delete mode 100644 resources/images/protocol/facebook/logo48x48.png delete mode 100644 resources/images/protocol/facebook/logo64x64.png delete mode 100644 resources/images/protocol/facebook/status16x16-away.png delete mode 100644 resources/images/protocol/facebook/status16x16-connecting.gif delete mode 100644 resources/images/protocol/facebook/status16x16-connecting.png delete mode 100644 resources/images/protocol/facebook/status16x16-dnd.png delete mode 100644 resources/images/protocol/facebook/status16x16-ffc.png delete mode 100644 resources/images/protocol/facebook/status16x16-invisible.png delete mode 100644 resources/images/protocol/facebook/status16x16-meeting.png delete mode 100644 resources/images/protocol/facebook/status16x16-offline.png delete mode 100644 resources/images/protocol/facebook/status16x16-online.png delete mode 100644 resources/images/protocol/facebook/status16x16-phone.png delete mode 100644 resources/images/protocol/facebook/status16x16-xa.png delete mode 100644 src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/facebookaccregwizz/facebookaccregwizz.manifest.mf diff --git a/build.xml b/build.xml index 5bbd81f..5cca731 100644 --- a/build.xml +++ b/build.xml @@ -1078,7 +1078,7 @@ bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service, bundle-argdelegation,bundle-zrtp4j,bundle-sdes4j,bundle-json, bundle-filehistory,bundle-metahistory,bundle-metahistory-slick, - bundle-plugin-facebookaccregwizz,bundle-plugin-ippiaccregwizz, + bundle-plugin-ippiaccregwizz, bundle-bouncycastle,bundle-plugin-otr,bundle-plugin-iptelaccregwizz, bundle-contactsource,bundle-plugin-reconnect,bundle-plugin-securityconfig, bundle-plugin-advancedconfig, @@ -1549,7 +1549,6 @@ javax.swing.event, javax.swing.border"/> prefix="resources/images"> - @@ -1896,17 +1895,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 061b70a..649afc8 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -189,7 +189,6 @@ felix.auto.start.67= \ reference:file:sc-bundles/keybindingChooser.jar \ reference:file:sc-bundles/generalconfig.jar \ reference:file:sc-bundles/otr.jar \ - reference:file:sc-bundles/facebookaccregwizz.jar \ reference:file:sc-bundles/spellChecker.jar \ reference:file:sc-bundles/advancedconfig.jar \ reference:file:sc-bundles/plugin-loggingutils.jar \ diff --git a/lib/jitsi-defaults.properties b/lib/jitsi-defaults.properties index 417bd00..a132d7e 100644 --- a/lib/jitsi-defaults.properties +++ b/lib/jitsi-defaults.properties @@ -37,7 +37,7 @@ net.java.sip.communicator.service.protocol.jabber.GOOGLE_CONTACTS_ENABLED=true net.java.sip.communicator.plugin.spellcheck.SYSTEM_HUNSPELL_DIR=/usr/share/hunspell # protocol order for the simple initial account registration wizard -plugin.simpleaccreg.PROTOCOL_ORDER=SIP|Jabber|Facebook|Google Talk +plugin.simpleaccreg.PROTOCOL_ORDER=SIP|Jabber|Google Talk #provisioning defaults net.java.sip.communicator.plugin.provisioning.MANDATORY=false @@ -75,7 +75,6 @@ net.java.sip.communicator.plugin.pluginmanager.SYSTEM_BUNDLES=\ net.java.sip.communicator.plugin.defaultresourcepack,\ net.java.sip.communicator.plugin.demuxcontactsource,\ net.java.sip.communicator.replacement.directimage,\ - net.java.sip.communicator.plugin.facebookaccregwizz,\ net.java.sip.communicator.fileaccess,\ net.java.sip.communicator.filehistory,\ net.java.sip.communicator.replacement.flickr,\ diff --git a/m2/jitsi-protocol/pom.xml b/m2/jitsi-protocol/pom.xml index e045b56..d61a018 100644 --- a/m2/jitsi-protocol/pom.xml +++ b/m2/jitsi-protocol/pom.xml @@ -61,7 +61,6 @@ net/java/sip/communicator/service/protocol/** - resources/images/protocol/facebook/** resources/images/protocol/googletalk/** resources/images/protocol/icq/** resources/images/protocol/jabber/** @@ -77,7 +76,6 @@ resources/images/protocol/media/** - resources/images/protocol/facebook/** resources/images/protocol/googletalk/** resources/images/protocol/icq/** resources/images/protocol/jabber/** diff --git a/resources/images/images.properties b/resources/images/images.properties index d0ff14c..482dc85 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -511,10 +511,6 @@ service.protocol.sip2sip.SIP2SIP_64x64=resources/images/protocol/sip2sip/sip64x6 service.protocol.ippi.IPPI_16x16=resources/images/protocol/ippi/sip16x16.png service.protocol.ippi.IPPI_64x64=resources/images/protocol/ippi/sip64x64.png -# facebook accregwizz -service.protocol.facebook.FACEBOOK_16x16=resources/images/protocol/facebook/facebook-online.png -service.protocol.facebook.FACEBOOK_48x48=resources/images/protocol/facebook/facebook48.png - # branding plugin images plugin.branding.ABOUT_WINDOW_BACKGROUND=resources/images/plugin/branding/aboutWindowBackground.png plugin.branding.SPLASH_SCREEN_BACKGROUND=resources/images/plugin/branding/splashScreenBackground.png diff --git a/resources/images/protocol/facebook/facebook-online.png b/resources/images/protocol/facebook/facebook-online.png deleted file mode 100644 index eef81e3..0000000 Binary files a/resources/images/protocol/facebook/facebook-online.png and /dev/null differ diff --git a/resources/images/protocol/facebook/facebook48.png b/resources/images/protocol/facebook/facebook48.png deleted file mode 100644 index 2501aca..0000000 Binary files a/resources/images/protocol/facebook/facebook48.png and /dev/null differ diff --git a/resources/images/protocol/facebook/logo32x32.png b/resources/images/protocol/facebook/logo32x32.png deleted file mode 100644 index 96da001..0000000 Binary files a/resources/images/protocol/facebook/logo32x32.png and /dev/null differ diff --git a/resources/images/protocol/facebook/logo48x48.png b/resources/images/protocol/facebook/logo48x48.png deleted file mode 100644 index 7c887f8..0000000 Binary files a/resources/images/protocol/facebook/logo48x48.png and /dev/null differ diff --git a/resources/images/protocol/facebook/logo64x64.png b/resources/images/protocol/facebook/logo64x64.png deleted file mode 100644 index 1c4da39..0000000 Binary files a/resources/images/protocol/facebook/logo64x64.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-away.png b/resources/images/protocol/facebook/status16x16-away.png deleted file mode 100644 index 51fc2ed..0000000 Binary files a/resources/images/protocol/facebook/status16x16-away.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-connecting.gif b/resources/images/protocol/facebook/status16x16-connecting.gif deleted file mode 100644 index 84b16f1..0000000 Binary files a/resources/images/protocol/facebook/status16x16-connecting.gif and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-connecting.png b/resources/images/protocol/facebook/status16x16-connecting.png deleted file mode 100644 index 1fae81e..0000000 Binary files a/resources/images/protocol/facebook/status16x16-connecting.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-dnd.png b/resources/images/protocol/facebook/status16x16-dnd.png deleted file mode 100644 index 34f3615..0000000 Binary files a/resources/images/protocol/facebook/status16x16-dnd.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-ffc.png b/resources/images/protocol/facebook/status16x16-ffc.png deleted file mode 100644 index f9848fe..0000000 Binary files a/resources/images/protocol/facebook/status16x16-ffc.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-invisible.png b/resources/images/protocol/facebook/status16x16-invisible.png deleted file mode 100644 index 05bcba2..0000000 Binary files a/resources/images/protocol/facebook/status16x16-invisible.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-meeting.png b/resources/images/protocol/facebook/status16x16-meeting.png deleted file mode 100644 index 6d939ee..0000000 Binary files a/resources/images/protocol/facebook/status16x16-meeting.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-offline.png b/resources/images/protocol/facebook/status16x16-offline.png deleted file mode 100644 index ddfaf6f..0000000 Binary files a/resources/images/protocol/facebook/status16x16-offline.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-online.png b/resources/images/protocol/facebook/status16x16-online.png deleted file mode 100644 index eef81e3..0000000 Binary files a/resources/images/protocol/facebook/status16x16-online.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-phone.png b/resources/images/protocol/facebook/status16x16-phone.png deleted file mode 100644 index 2d19f7b..0000000 Binary files a/resources/images/protocol/facebook/status16x16-phone.png and /dev/null differ diff --git a/resources/images/protocol/facebook/status16x16-xa.png b/resources/images/protocol/facebook/status16x16-xa.png deleted file mode 100644 index d6eb195..0000000 Binary files a/resources/images/protocol/facebook/status16x16-xa.png and /dev/null differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 63dbd17..ba631d9 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1035,13 +1035,6 @@ plugin.dictaccregwizz.NO_STRATEGIES_FOUND=No strategy found on the server plugin.dictaccregwizz.POPULATE_LIST=Populating list plugin.dictaccregwizz.CLOSING_CONNECTION=Closing connection -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=

    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=The Facebook Chat protocol -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Username: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Username and Password - # generalconfig plugin.generalconfig.AUTO_START=Auto-start {0} when computer restarts or reboots plugin.generalconfig.CHATALERTS_ON_MESSAGE=Use task bar / dock alerts on incoming calls and chats diff --git a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java deleted file mode 100644 index 3a7b2b9..0000000 --- a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccRegWizzActivator.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.facebookaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the FacebookAccountRegistrationWizard in the UI Service. - * - * @author Dai Zhiwei - */ -public class FacebookAccRegWizzActivator - extends AbstractServiceDependentActivator -{ - /** - * The logger. - */ - private static Logger logger - = Logger.getLogger(FacebookAccRegWizzActivator.class.getName()); - - /** - * A currently valid bundle context. - */ - public static BundleContext bundleContext; - - /** - * The container. - */ - private static WizardContainer wizardContainer; - - /** - * Registration wizard. - */ - private static FacebookAccountRegistrationWizard facebookWizard; - - /** - * The UI service. - */ - private static UIService uiService; - - /** - * The browser launcher service. - */ - private static BrowserLauncherService browserLauncherService; - - private static ResourceManagementService resourcesService; - - /** - * Starts this bundle. - */ - @Override - public void start(Object dependentService) - { - if (logger.isInfoEnabled()) - logger.info("Loading facebook account wizard."); - - uiService = (UIService)dependentService; - - wizardContainer = uiService.getAccountRegWizardContainer(); - - facebookWizard - = new FacebookAccountRegistrationWizard(wizardContainer); - - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.FACEBOOK); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - facebookWizard, - containerFilter); - - if (logger.isInfoEnabled()) - logger.info("Facebook account registration wizard [STARTED]."); - } - - /** - * The dependent class. We are waiting for the ui service. - * @return the ui service class. - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * The bundle context to use. - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param bundleContext The execution context of the bundle being stopped. - */ - public void stop(BundleContext bundleContext) - { - } - - /** - * Returns the ProtocolProviderFactory for the Facebook protocol. - * @return the ProtocolProviderFactory for the Facebook protocol - */ - public static ProtocolProviderFactory getFacebookProtocolProviderFactory() - { - - ServiceReference[] serRefs = null; - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" + ProtocolNames.JABBER + ")"; - - try - { - serRefs = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error("FacebookAccRegWizzActivator : " + ex); - } - - return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); - } - - /** - * Returns the bundleContext that we received when we were started. - * - * @return a currently valid instance of a bundleContext. - */ - public BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Gets the browser launcher service. - * @return the browser launcher service. - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - ServiceReference serviceReference = - bundleContext.getServiceReference(BrowserLauncherService.class - .getName()); - - browserLauncherService = - (BrowserLauncherService) bundleContext - .getService(serviceReference); - } - - return browserLauncherService; - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(FacebookAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java deleted file mode 100644 index 896c054..0000000 --- a/src/net/java/sip/communicator/plugin/facebookaccregwizz/FacebookAccountRegistrationWizard.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.facebookaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.jabberaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.jabber.*; - -/** - * The FacebookAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Facebook Chat protocol. It allows - * the user to create and configure a new Facebook account. - * - * @author Dai Zhiwei - * @author Yana Stamcheva - */ -public class FacebookAccountRegistrationWizard - extends JabberAccountRegistrationWizard -{ - /** - * The protocol name. - */ - private static final String PROTOCOL = "Facebook"; - - /** - * A constant pointing to the Facebook protocol logo icon. - */ - private static final String PROTOCOL_ICON - = "service.protocol.facebook.FACEBOOK_16x16"; - - /** - * A constant pointing to the Facebook protocol wizard page image. - */ - private static final String PAGE_IMAGE - = "service.protocol.facebook.FACEBOOK_48x48"; - - private static final String SERVER_ADDRESS = "chat.facebook.com"; - - /** - * Creates an instance of FacebookAccountRegistrationWizard. - * @param wizardContainer the wizard container, where this wizard - * is added - */ - public FacebookAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - JabberAccountRegistration reg = new JabberAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all facebook specific properties. - * - * @param reg the registration object - */ - private void setPredefinedProperties(JabberAccountRegistration reg) - { - reg.setServerAddress(SERVER_ADDRESS); - reg.setSendKeepAlive(true); - - reg.setServerOverridden(true); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return FacebookAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return FacebookAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: username"; - } - - /** - * Returns the display label used for the sip id field. - * @return the sip id display label string. - */ - @Override - protected String getUsernameLabel() - { - return FacebookAccRegWizzActivator.getResources() - .getI18NString("plugin.facebookaccregwizz.USERNAME"); - } - - /** - * Return the string for add existing account button. - * @return the string for add existing account button. - */ - @Override - protected String getCreateAccountButtonLabel() - { - return null; - } - - /** - * Return the string for create new account button. - * @return the string for create new account button. - */ - @Override - protected String getCreateAccountLabel() - { - return FacebookAccRegWizzActivator.getResources().getI18NString( - "plugin.facebookaccregwizz.DESCRIPTION"); - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/facebook"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/facebook/logo32x32.png"; - } - - /** - * Opens a browser on the sign up page. - */ - @Override - public void webSignup() {} - - /** - * Returns true if the web sign up is supported by the current - * implementation, false - otherwise. - * @return true if the web sign up is supported by the current - * implementation, false - otherwise - */ - @Override - public boolean isWebSignupSupported() - { - return false; - } - - /** - * Creates an account for the given user and password. - * - * @param providerFactory the ProtocolProviderFactory which will create - * the account - * @param userName the user identifier - * @param passwd the password - * @return the ProtocolProviderService for the new account. - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - protected ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, - String userName, - String passwd) - throws OperationFailedException - { - // add server part to username - if(userName.indexOf("@") == -1) - userName += "@" + SERVER_ADDRESS; - - return super.installAccount(providerFactory, userName, passwd); - } - - /** - * Returns an instance of CreateAccountService through which the - * user could create an account. This method is meant to be implemented by - * specific protocol provider wizards. - * @return an instance of CreateAccountService - */ - @Override - protected JabberAccountCreationFormService getCreateAccountService() - { - return null; - } - - /** - * Whether the advanced configuration is enabled. Gives an option - * to disable/hide advanced config button. - * @return whether the advanced configuration is enabled. - */ - public boolean isAdvancedConfigurationEnabled() - { - return false; - } -} diff --git a/src/net/java/sip/communicator/plugin/facebookaccregwizz/facebookaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/facebookaccregwizz/facebookaccregwizz.manifest.mf deleted file mode 100644 index 9c79947..0000000 --- a/src/net/java/sip/communicator/plugin/facebookaccregwizz/facebookaccregwizz.manifest.mf +++ /dev/null @@ -1,34 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.facebookaccregwizz.FacebookAccRegWizzActivator -Bundle-Name: Facebook account registration wizard -Bundle-Description: Facebook account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.facebookaccregwizz -Import-Package: org.osgi.framework, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - net.java.sip.communicator.service.protocol.jabber, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - net.java.sip.communicator.plugin.jabberaccregwizz, - javax.accessibility, - javax.imageio, - javax.swing, - javax.swing.border, - javax.swing.filechooser, - javax.swing.plaf, - javax.swing.plaf.basic, - javax.swing.plaf.metal, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.swing.tree, - javax.swing.undo diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java index 8332557..51ac63d 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java @@ -97,9 +97,4 @@ public interface ProtocolNames * The Dict protocol. */ public static final String DICT = "Dict"; - - /** - * The Facebook protocol. - */ - public static final String FACEBOOK = "Facebook"; } -- cgit v1.1 From f96b2ef870cdcb17938e1f6484743b6a230ec5ef Mon Sep 17 00:00:00 2001 From: George Politis Date: Mon, 29 Feb 2016 22:09:48 +0000 Subject: Increases the queue size for the PacketLoggingServiceImpl. --- .../impl/packetlogging/PacketLoggingServiceImpl.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 6486398..90e95c9 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -42,6 +42,14 @@ public class PacketLoggingServiceImpl = Logger.getLogger(PacketLoggingServiceImpl.class); /** + * The max size of the EvictingQueue that the saver thread + * is using. + * + * TODO this needs to be configurable eventually. + */ + private static final int EVICTING_QUEUE_MAX_SIZE = 1000; + + /** * The OutputStream we are currently writing to. */ private FileOutputStream outputStream = null; @@ -768,7 +776,8 @@ public class PacketLoggingServiceImpl /** * List of packets queued to be written in the file. */ - private final Queue pktsToSave = EvictingQueue.create(10); + private final EvictingQueue pktsToSave + = EvictingQueue.create(EVICTING_QUEUE_MAX_SIZE); /** * Initializes a new SaverThread. @@ -843,6 +852,11 @@ public class PacketLoggingServiceImpl */ public synchronized void queuePacket(Packet packet) { + if (pktsToSave.remainingCapacity() == 0) + { + logger.warn("Queue is full, packets are being evicted."); + } + pktsToSave.add(packet); notifyAll(); } -- cgit v1.1 From 2d83b56d5e7e5ed945344f6e0f7b96e537bd0c48 Mon Sep 17 00:00:00 2001 From: George Politis Date: Mon, 29 Feb 2016 23:59:33 +0000 Subject: EvictingQueue.remainingSize() is not available in Guava 15. --- .../sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 90e95c9..220f36b 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -852,7 +852,7 @@ public class PacketLoggingServiceImpl */ public synchronized void queuePacket(Packet packet) { - if (pktsToSave.remainingCapacity() == 0) + if (EVICTING_QUEUE_MAX_SIZE - pktsToSave.size() == 0) { logger.warn("Queue is full, packets are being evicted."); } -- cgit v1.1 From e2e661ecc1b861e3cec0c2b05276cdd9dbbd8e61 Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Wed, 2 Mar 2016 16:10:35 -0600 Subject: Fix the XML generated for the adaptive-simulcast property. --- .../impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java index 24ee50d..48e344b 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java @@ -1077,8 +1077,8 @@ public class ColibriConferenceIQ if (adaptiveSimulcast != null) { - xml.append(' ').append(adaptiveSimulcast).append("='") - .append(adaptiveSimulcast).append('\''); + xml.append(' ').append(ADAPTIVE_SIMULCAST_ATTR_NAME) + .append("='").append(adaptiveSimulcast).append('\''); } // simulcastMode -- cgit v1.1 From 4f57d6fcd08c1915378dfa60b8b7dbec9880d852 Mon Sep 17 00:00:00 2001 From: Boris Grozev Date: Wed, 2 Mar 2016 17:05:55 -0600 Subject: Parses the adaptive-simulcast attribute. --- .../jabber/extensions/colibri/ColibriIQProvider.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java index 4298b3f..a05f213 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java @@ -476,6 +476,18 @@ public class ColibriIQProvider channel.setAdaptiveLastN( Boolean.parseBoolean(adaptiveLastN)); + String adaptiveSimulcast + = parser.getAttributeValue( + "", + ColibriConferenceIQ.Channel + .ADAPTIVE_SIMULCAST_ATTR_NAME); + + if (!StringUtils.isNullOrEmpty(adaptiveSimulcast)) + { + channel.setAdaptiveSimulcast( + Boolean.parseBoolean(adaptiveSimulcast)); + } + // simulcastMode String simulcastMode = parser.getAttributeValue( -- cgit v1.1 From 092ea03b60e6f74eabad86e34f38a4f7b8043e98 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 3 Mar 2016 16:02:29 -0600 Subject: Adds ComponentVersionsExtension class. --- .../jitsimeet/ComponentVersionsExtension.java | 135 +++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java new file mode 100644 index 0000000..bcc3397 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java @@ -0,0 +1,135 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet; + +import net.java.sip.communicator.impl.protocol.jabber.extensions.*; + +/** + * The packet extension is used by Jicofo to broadcast versions of all video + * conferencing system components. This packets extension is added to jicofo's + * MUC presence. It will contain {@link Component} children which carry each + * component's name and version. + * + * @author Pawel Domas + */ +public class ComponentVersionsExtension + extends AbstractPacketExtension +{ + /** + * The XML element name of {@link ComponentVersionsExtension}. + */ + public static final String ELEMENT_NAME = "versions"; + + /** + * The name of XML sub-elements which carry the info about particular + * component's version. + */ + public static final String COMPONENT_ELEMENT_NAME = "component"; + + /** + * Constant for {@link Component} name used to signal the version of + * conference focus. + */ + public static final String COMPONENT_FOCUS = "focus"; + + /** + * Constant for {@link Component} name used to signal the version of + * XMPP server. + */ + public static final String COMPONENT_XMPP_SERVER = "xmpp"; + + /** + * Constant for {@link Component} name used to signal the version of + * the videobridge. + */ + public static final String COMPONENT_VIDEOBRIDGE = "videobridge"; + + /** + * The XML element namespace of {@link ComponentVersionsExtension}. + */ + public static final String NAMESPACE = "http://jitsi.org/jitmeet"; + + /** + * Creates an {@link AbstractPacketExtension} instance for the specified + * namespace and elementName. + */ + public ComponentVersionsExtension() + { + super(NAMESPACE, ELEMENT_NAME); + } + + /** + * Adds component's version to this extension. + * + * @param componentName the name of the component for which + * child {@link Component} extension will be added. + * @param versionStr human readable string that describes component's + * version. + */ + public void addComponentVersion(String componentName, String versionStr) + { + Component v = new Component(); + + v.setName(componentName); + v.setText(versionStr); + + addChildExtension(v); + } + + /** + * Component child element of {@link ComponentVersionsExtension}. The name + * of the component is carried in name attribute and the version string is + * the text value. + */ + public class Component + extends AbstractPacketExtension + { + /** + * The name of that attribute that carries component's name. + */ + private final String NAME_ATTR_NAME = "name"; + + /** + * Creates new instance of {@link Component} packet extension. + */ + public Component() + { + super(NAMESPACE, COMPONENT_ELEMENT_NAME); + } + + /** + * Returns the value of the name attribute. + * @return String which describes the name of video + * conferencing system component. + */ + public String getName() + { + return getAttributeAsString(NAME_ATTR_NAME); + } + + /** + * Sets new value for the component's name attribute. + * @param name a String which describes the name of video + * conferencing system component. + */ + public void setName(String name) + { + setAttribute(NAME_ATTR_NAME, name); + } + } +} -- cgit v1.1 From 7245b9570e8123aa634c272634bcf840a3dd7330 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Mon, 14 Mar 2016 15:23:21 -0500 Subject: Adds missing java doc and removes unused attributes from Jibri IQs --- .../protocol/jabber/extensions/jibri/JibriIq.java | 144 +++++++++++++++++---- .../jabber/extensions/jibri/JibriIqProvider.java | 34 ++--- .../extensions/jibri/JibriStatusPacketExt.java | 21 ++- .../jabber/extensions/jibri/RecordingStatus.java | 27 ++-- 4 files changed, 170 insertions(+), 56 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index 0e34fe6..9cda358 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -24,64 +24,125 @@ import org.jivesoftware.smack.packet.*; import java.util.*; /** + * The IQ used to control conference recording with Jibri component. + * + * Start the recording: + * + * 1. Send Jibri IQ with {@link Action#START} to Jibri. + * 2. Jibri replies with RESULT and status {@link Status#PENDING}. + * 3. Jibri sends SET IQ with status {@link Status#ON} once recording actually + * starts. + * + * Stop the recording: + * + * 1. Send Jibri IQ with {@link Action#STOP} to Jibri. + * 2. Jibri replies with {@link Status#OFF} immediately if the recording has + * been stopped already or sends separate Jibri SET IQ later on if it takes + * more time. + * * @author lishunyang * @author Pawel Domas */ public class JibriIq extends IQ { - public static final String NAMESPACE = "http://jitsi.org/protocol/jibri"; + /** + * Attribute name of "action". + */ + public static final String ACTION_ATTR_NAME = "action"; + /** + * XML element name of the Jibri IQ. + */ public static final String ELEMENT_NAME = "jibri"; /** - * Attribute name of "action". + * XML namespace of the Jibri IQ. */ - public static final String ACTION_ATTR_NAME = "action"; + public static final String NAMESPACE = "http://jitsi.org/protocol/jibri"; + + /** + * The name of XML attribute which stores the recording status. + */ + static final String STATUS_ATTR_NAME = "status"; + + /** + * The name of XML attribute which stores the stream id. + */ + static final String STREAM_ID_ATTR_NAME = "streamid"; /** - * Attribute name of "status". + * The name of XML attribute which stores the url. */ - public static final String STATUS_ATTR_NAME = "status"; + static final String URL_ATTR_NAME = "url"; + /** + * Holds the action. + */ private Action action = Action.UNDEFINED; - private Status status = Status.UNDEFINED; - private String url = null; - public String getFollowEntity() - { - return followEntity; - } + /** + * Holds recording status. + */ + private Status status = Status.UNDEFINED; - public void setFollowEntity(String followEntity) - { - this.followEntity = followEntity; - } + /** + * The ID of the stream which will be used to record the conference. The + * value depends on recording service provider. + */ + private String streamId = null; - private String followEntity = null; + /** + * The conference URL which contains the full address like + * "https://conference.com/room1". + */ + private String url = null; + /** + * Returns the value of {@link #STREAM_ID_ATTR_NAME} attribute. + * @return a String which contains the value of "stream id" + * attribute or null if empty. + */ public String getStreamId() { return streamId; } + /** + * Sets the value for {@link #STREAM_ID_ATTR_NAME} attribute. + * @param streamId a String for the stream id attribute or + * null to remove it from XML element. + */ public void setStreamId(String streamId) { this.streamId = streamId; } + /** + * Returns the value of {@link #URL_ATTR_NAME} attribute. + * @return a String which contains the value of the URL attribute + * or null if empty. + * @see #url + */ public String getUrl() { return url; } + /** + * Sets the value for {@link #URL_ATTR_NAME} attribute. + * @param url a String for the URL attribute or + * null to remove it from XML element. + * @see #url + */ public void setUrl(String url) { this.url = url; } - private String streamId = null; - + /** + * {@inheritDoc} + */ @Override public String getChildElementXML() { @@ -102,20 +163,14 @@ public class JibriIq if (url != null) { - printStringAttribute(xml, "url", url); + printStringAttribute(xml, URL_ATTR_NAME, url); } if (streamId != null) { - printStringAttribute(xml, "streamid", streamId); + printStringAttribute(xml, STREAM_ID_ATTR_NAME, streamId); } - if (followEntity != null) - { - printStringAttribute(xml, "follow-entity", followEntity); - } - - Collection extensions = getExtensions(); if (extensions.size() > 0) { @@ -185,8 +240,17 @@ public class JibriIq */ public enum Action { + /** + * Start the recording. + */ START("start"), + /** + * Stop the recording. + */ STOP("stop"), + /** + * Unknown/uninitialized + */ UNDEFINED("undefined"); private String name; @@ -227,20 +291,48 @@ public class JibriIq } } + /** + * The enumeration of recording status values. + */ public enum Status { + /** + * Recording is in progress. + */ ON("on"), + + /** + * Recording stopped. + */ OFF("off"), + + /** + * Starting the recording process. + */ PENDING("pending"), + + /** + * Unknown/uninitialized. + */ UNDEFINED("undefined"); + /** + * Status name holder. + */ private String name; + /** + * Creates new {@link Status} instance. + * @param name a string corresponding to one of {@link Status} values. + */ Status(String name) { this.name = name; } + /** + * {@inheritDoc} + */ @Override public String toString() { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java index d4b08f6..5313a76 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -17,11 +17,16 @@ */ package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; +import org.jitsi.util.*; + import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.provider.*; import org.xmlpull.v1.*; +/** + * Parses {@link JibriIq}. + */ public class JibriIqProvider implements IQProvider { @@ -50,21 +55,26 @@ public class JibriIqProvider String action = parser.getAttributeValue("", JibriIq.ACTION_ATTR_NAME); - String status - = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME); - iq.setAction(JibriIq.Action.parse(action)); + String status + = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME); iq.setStatus(JibriIq.Status.parse(status)); - String url = parser.getAttributeValue("", "url"); - String streamId = parser.getAttributeValue("", "streamid"); - if (url != null) + String url + = parser.getAttributeValue("", JibriIq.URL_ATTR_NAME); + if (!StringUtils.isNullOrEmpty(url)) iq.setUrl(url); - if (streamId != null) + + String streamId + = parser.getAttributeValue("", JibriIq.STREAM_ID_ATTR_NAME); + if (!StringUtils.isNullOrEmpty(streamId)) iq.setStreamId(streamId); - String followEntity = parser.getAttributeValue("", "follow-entity"); - if (followEntity != null) + + String followEntity + = parser.getAttributeValue( + "", JibriIq.FOLLOW_ENTITY_ATTR_NAME); + if (!StringUtils.isNullOrEmpty(followEntity)) iq.setFollowEntity(followEntity); } else @@ -88,12 +98,6 @@ public class JibriIqProvider } break; } - - case XmlPullParser.TEXT: - { - // Parse some text here - break; - } } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java index ddab0a1..e046b68 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java @@ -1,12 +1,31 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; + import org.jitsi.util.*; + import org.jivesoftware.smack.provider.*; /** * Status extension included in MUC presence by Jibri to indicate it's status. - * On of: + * One of: *
  • idle
  • - the instance is idle and can be used for recording *
  • busy
  • - the instance is currently recording or doing something very * important and should not be disturbed diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java index f456261..80e6c42 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java @@ -20,8 +20,8 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; /** - * The packet extension added to Jicofo presence to broadcast current recording - * status to all conference participants. + * The packet extension added to Jicofo MUC presence to broadcast current + * recording status to all conference participants. * * Status meaning: * {@link JibriIq.Status#UNDEFINED} - recording not available @@ -42,15 +42,20 @@ public class RecordingStatus */ public static final String ELEMENT_NAME = "jibri-recording-status"; + /** + * The name of XML attribute which holds the recording status. + */ private static final String STATUS_ATTRIBUTE = "status"; - private static final String URL_ATTRIBUTE = "url"; - public RecordingStatus() { super(NAMESPACE, ELEMENT_NAME); } + /** + * Returns the value of current recording status stored in it's attribute. + * @return one of {@link JibriIq.Status} + */ public JibriIq.Status getStatus() { String statusAttr = getAttributeAsString(STATUS_ATTRIBUTE); @@ -58,18 +63,12 @@ public class RecordingStatus return JibriIq.Status.parse(statusAttr); } + /** + * Sets new value for the recording status. + * @param status one of {@link JibriIq.Status} + */ public void setStatus(JibriIq.Status status) { setAttribute(STATUS_ATTRIBUTE, String.valueOf(status)); } - - public String getUrl() - { - return getAttributeAsString(URL_ATTRIBUTE); - } - - public void setAttribute(String url) - { - setAttribute(URL_ATTRIBUTE, url); - } } -- cgit v1.1 From 4767ae1978ac0d6c77c7aeb0f3289143073a8c7c Mon Sep 17 00:00:00 2001 From: paweldomas Date: Mon, 14 Mar 2016 15:29:09 -0500 Subject: Fixes compilation error. --- .../impl/protocol/jabber/extensions/jibri/JibriIqProvider.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java index 5313a76..e7ea311 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -70,12 +70,6 @@ public class JibriIqProvider = parser.getAttributeValue("", JibriIq.STREAM_ID_ATTR_NAME); if (!StringUtils.isNullOrEmpty(streamId)) iq.setStreamId(streamId); - - String followEntity - = parser.getAttributeValue( - "", JibriIq.FOLLOW_ENTITY_ATTR_NAME); - if (!StringUtils.isNullOrEmpty(followEntity)) - iq.setFollowEntity(followEntity); } else { -- cgit v1.1 From 130b15cf21fd077b09233da07e2241021493cd0f Mon Sep 17 00:00:00 2001 From: paweldomas Date: Tue, 22 Mar 2016 11:31:44 -0500 Subject: Renames the URL attribute in JibriIQ to "room" --- .../protocol/jabber/extensions/jibri/JibriIq.java | 36 +++++++++++----------- .../jabber/extensions/jibri/JibriIqProvider.java | 8 ++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index 9cda358..87abf9a 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -72,9 +72,10 @@ public class JibriIq static final String STREAM_ID_ATTR_NAME = "streamid"; /** - * The name of XML attribute which stores the url. + * The name of XML attribute which stores the name of the conference room to + * be recorded. */ - static final String URL_ATTR_NAME = "url"; + static final String ROOM_ATTR_NAME = "room"; /** * Holds the action. @@ -93,10 +94,9 @@ public class JibriIq private String streamId = null; /** - * The conference URL which contains the full address like - * "https://conference.com/room1". + * The name of the conference room to be recorded. */ - private String url = null; + private String room = null; /** * Returns the value of {@link #STREAM_ID_ATTR_NAME} attribute. @@ -119,25 +119,25 @@ public class JibriIq } /** - * Returns the value of {@link #URL_ATTR_NAME} attribute. - * @return a String which contains the value of the URL attribute + * Returns the value of {@link #ROOM_ATTR_NAME} attribute. + * @return a String which contains the value of the room attribute * or null if empty. - * @see #url + * @see #room */ - public String getUrl() + public String getRoom() { - return url; + return room; } /** - * Sets the value for {@link #URL_ATTR_NAME} attribute. - * @param url a String for the URL attribute or - * null to remove it from XML element. - * @see #url + * Sets the value for {@link #ROOM_ATTR_NAME} attribute. + * @param room a String for the room attribute or null to + * remove it from XML element. + * @see #room */ - public void setUrl(String url) + public void setRoom(String room) { - this.url = url; + this.room = room; } /** @@ -161,9 +161,9 @@ public class JibriIq printStringAttribute(xml, STATUS_ATTR_NAME, status.toString()); } - if (url != null) + if (room != null) { - printStringAttribute(xml, URL_ATTR_NAME, url); + printStringAttribute(xml, ROOM_ATTR_NAME, room); } if (streamId != null) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java index e7ea311..ad3a134 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -61,10 +61,10 @@ public class JibriIqProvider = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME); iq.setStatus(JibriIq.Status.parse(status)); - String url - = parser.getAttributeValue("", JibriIq.URL_ATTR_NAME); - if (!StringUtils.isNullOrEmpty(url)) - iq.setUrl(url); + String room + = parser.getAttributeValue("", JibriIq.ROOM_ATTR_NAME); + if (!StringUtils.isNullOrEmpty(room)) + iq.setRoom(room); String streamId = parser.getAttributeValue("", JibriIq.STREAM_ID_ATTR_NAME); -- cgit v1.1 From 8cbe6c805be155443ed48d5a40f0a38cb40a8db6 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 31 Mar 2016 07:19:44 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1634 of 1634 strings translated (0 fuzzy). --- resources/languages/resources_ru.properties | 276 ++++++++++++++++++++-------- 1 file changed, 201 insertions(+), 75 deletions(-) diff --git a/resources/languages/resources_ru.properties b/resources/languages/resources_ru.properties index 0e67e5b..7021ad1 100644 --- a/resources/languages/resources_ru.properties +++ b/resources/languages/resources_ru.properties @@ -30,7 +30,7 @@ service.gui.ACCEPT=&Принять service.gui.ACCOUNT=Аккаунт service.gui.ACCOUNT_ME=Я service.gui.ACCOUNT_REGISTRATION_WIZARD=Мастер регистрации учетных записей -service.gui.ACCOUNTS=Аккаунты +service.gui.ACCOUNTS=Учётные записи service.gui.ADD=&Добавить service.gui.ADD_ACCOUNT=Добавить аккаунт service.gui.ADD_CONTACT=&Добавить контакт @@ -45,7 +45,7 @@ service.gui.ADD_CONTACT_NOT_SUPPORTED=Не удалось добавить ко service.gui.ADD_CONTACT_IDENTIFIER=В поле ниже введите идентификатор контакта который вы желаете добавить. service.gui.ADD_CONTACT_WIZARD=Мастер добавления контактов service.gui.ADD_CONTACT_NOT_CONNECTED=Вы должны быть подключены для того, чтобы добавить контакт. Пожалуйста, выполните вход и попробуйте снова. -service.gui.ADD_GROUP_LOCAL_ERROR=Не удалось добавить группу с именем: {0}. Сбой произошёл во время операции ввода-вывода. +service.gui.ADD_GROUP_LOCAL_ERROR=Не удалось добавить группу с именем: {0}. Произошёл сбой во время операции ввода-вывода. service.gui.ADD_GROUP_EXIST_ERROR=Группа {0} уже существует в списке контактов. Пожалуйста, выберите другое имя. service.gui.ADD_GROUP_NET_ERROR=Не удалось добавить группу с именем: {0}. Сбой произошёл по причине отказа сети. Пожалуйста, проверьте ваше сетевое подключение и попробуйте снова. service.gui.ADD_GROUP_ERROR=Не удалось добавить группу: {0}. @@ -64,7 +64,7 @@ service.gui.ARE_NOW=Вы сейчас {0} service.gui.AT=время service.gui.AUTHORIZE=&Авторизовать service.gui.AUTHORIZATION_ACCEPTED={0} собеседник принял запрос на авторизацию. -service.gui.AUTHENTICATION_FAILED=Проверка подлинности для {0} не удалась. Введённый пароль неверен. +service.gui.AUTHENTICATION_FAILED=Проверка подлинности для {0} не удалась. Введённый вами пароль неверен. service.gui.AUTHENTICATION_REQUESTED=Запрошена проверка подлинности service.gui.AUTHENTICATION_REQUESTED_SERVER=Сервер {0} запросил проверку подлинности. service.gui.AUTHENTICATION_REJECTED={0} собеседник отверг запрос на авторизацию. @@ -92,7 +92,7 @@ service.gui.CALL_HISTORY_GROUP_NAME=История вызовов service.gui.CALL_VIA=Позвонить через: service.gui.CALL_NAME_OR_NUMBER=Введите имя или номер service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=Этот звонок поддерживает только участников из сети {0} и вашего {1} аккаунта. {2} не содержит адресов для этой сети или аккаунта. -service.gui.CALL_WITH=Абонент +service.gui.CALL_WITH=Вызов с помощью service.gui.CALL_NO_AUDIO_DEVICE=Вы не выбрали ни одного аудиоустройства. service.gui.CALL_NO_AUDIO_CODEC=У вас не установлены аудиокодеки. service.gui.CALL_NO_DEVICE_CODECS_Q=Хотите продолжить вызов? @@ -115,11 +115,14 @@ service.gui.CHAT_ROOM_CONFIGURATION_FAILED=Не удалось открыть н service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=Не удалось отобразить конфигурацию комнаты {0}. Только владелец комнаты может увидеть или изменить конфигурацию. service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=Произошла ошибка во время применения конфигурации конференции {0}. service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=Редактировать список участников +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=Список справа содержит пользователей, имеющих членство в этой комнате. Когда чат-комната 'Только для участников', в комнате будут лишь те, кто допущен к подключению. service.gui.CHAT_ROOM_USER_JOINED=подключился к {0} service.gui.CHAT_ROOM_USER_LEFT=покинул {0} service.gui.CHAT_ROOM_USER_KICKED=был исключён из {0} service.gui.CHAT_ROOM_USER_QUIT=вышел из {0} -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Удалить выбранную комнату из списка сохранённых +service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Отправка сообщения запрещена (голос отозван) +service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Сохраняет чат-комнату для последующего использования +service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Удаляет выбранную комнату из списка сохранённых service.gui.CHAT_ROOM_NAME=Имя конференции service.gui.CLEAR_CUSTOM_MESSAGES=Очистка пользовательских сообщений service.gui.ROOM_NAME=Конференция @@ -136,6 +139,8 @@ service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Конференция {0} запрос service.gui.CHAT_ROOMS=Конференции service.gui.CHAT_ROOM=Комната service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} изменил тему на {1} +service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=Вы можете продолжать разговор в следующей чат-комнате: {0} +service.gui.CHAT_NICKNAME_CHANGE={0} теперь известен как {1} service.gui.CHOOSE_CONTACT=Выберите контакт service.gui.CHOOSE_NUMBER=Выберите номер service.gui.CHOOSE_ACCOUNT=Пожалуйста, выберите один из указанных контактов. @@ -144,7 +149,7 @@ service.gui.COUNTRY=Страна service.gui.SHOW_MORE_TOOLTIP=Нажмите для подробностей service.gui.CLEAR=Очистить service.gui.CLOSE=За&крыть -service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Вы получили новое сообщение меньше, чем 2 секунды назад. Вы уверены, что желаете закрыть этот чат? +service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Вы получили новое сообщение менее, чем 2 секунды назад. Вы уверены, что желаете закрыть этот чат? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=У вас имеются активные передачи файлов. Вы уверенны, что желаете прервать их? service.gui.CONFIRM=Подтвердить service.gui.CONNECTED_STATUS=Подключен @@ -159,7 +164,7 @@ service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Выбранный контакт { service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Выбранный контакт {0} не поддерживает чат в конференции. service.gui.CONTACT_PAUSED_TYPING={0} перестал печатать сообщение service.gui.CONTACT_TYPING={0} печатает сообщение -service.gui.CONTACT_TYPING_SEND_FAILED=собеседник {0} не увидит процесс создания сообщения +service.gui.CONTACT_TYPING_SEND_FAILED=ой-ой... мы не смогли сообщить {0} , что вы печатаете service.gui.CONTACT_INFO=&Контактная информация service.gui.CONTACTLIST=Список контактов service.gui.CONTACTS=Контакты @@ -185,6 +190,7 @@ service.gui.DATE=Дата service.gui.DELETE=Удалить service.gui.DENY=&Отклонить service.gui.DESKTOP_SHARING_WARNING=Вы уверены, что хотите предоставить доступ к вашему экрану?
    Нажатие OK позволит абонентам, участвующим в разговоре, видеть содержимое вашего экрана. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Вы показыаете свой экран service.gui.DIALPAD=Номеронабиратель service.gui.DISPLAY_NAME=Отображаемое имя service.gui.DISCONNECTED_STATUS=Отключено @@ -208,6 +214,7 @@ service.gui.ENTER_PHONE_NUMBER=Введите номер телефона service.gui.ENTER_NAME_OR_NUMBER=Введите имя или номер service.gui.ERROR=Ошибка service.gui.ERROR_WAS=Ошибка была: {0} +service.gui.ERROR_RECEIVED_FROM=От {0} получено сообщение об ошибке service.gui.ESTIMATED_TIME=Приблизительное время: service.gui.EVENTS=События service.gui.EXIT=В&ыйти @@ -269,14 +276,15 @@ service.gui.HIDE_MAIN_WINDOW=
    Нажатие крестика в углу о service.gui.HISTORY=&История service.gui.HISTORY_CONTACT=История - {0} service.gui.HISTORY_TOGGLE_PER_CONTACT=Выключить историю для этого контакта -service.gui.HISTORY_TOGGLE_PER_CHATROOM=Выключить историю для этого контакта -service.gui.HISTORY_ERASE_PER_CONTACT=Стереть всю историю контакта -service.gui.HISTORY_ERASE_PER_CHATROOM=Стереть всю историю комнаты +service.gui.HISTORY_TOGGLE_PER_CHATROOM=Выключить историю для этой комнаты +service.gui.HISTORY_TOGGLE_ALL=Выключить историю для всех бесед и контактов +service.gui.HISTORY_ERASE_PER_CONTACT=Стереть всю историю для этого контакта +service.gui.HISTORY_ERASE_PER_CHATROOM=Стереть всю историю этой комнаты service.gui.HISTORY_ERASE_ALL=Стереть всю историю в {0} service.gui.HISTORY_REMOVE_PER_CONTACT_WARNING=Действительно окончательно уничтожить все локально сохраненные сообщения {0}? service.gui.HISTORY_REMOVE_ALL_WARNING=Действительно окончательно уничтожить все локально сохраненные сообщения? service.gui.HISTORY_REMOVE_ERROR=Ошибка удаления локально сохраненных сообщений. -service.gui.HOME=Домой +service.gui.HOME=На главную service.gui.HOME_PAGE=Домашняя страница service.gui.HOUR=Время service.gui.ICE=ICE @@ -284,16 +292,18 @@ service.gui.IDENTIFIER=Идентификатор service.gui.IGNORE=&Игнорировать service.gui.INSERT_SMILEY=Вставить смайлик service.gui.INCOMING_CALL=Входящий звонок от: {0} +service.gui.INCOMING_SCREEN_SHARE=Входящее предложение показать экран от: {0} service.gui.INCOMING_CALL_STATUS=Входящий звонок +service.gui.INCOMING_SCREEN_SHARE_STATUS=Входящее предложение показать экран service.gui.INSTANT_MESSAGINGS=IMs service.gui.IM=IM service.gui.INITIATING_CALL_STATUS=Осуществление вызова service.gui.INVITATION=Текст приглашения service.gui.INVITATION_RECEIVED=Приглашение принято -service.gui.INVITATION_RECEIVED_MSG={0} пригласил Вас в конференцию {1}. Вы можете принять, отклонить или игнорировать приглашение. -service.gui.INVITATION_REJECTED={0} отклонил Ваше приглашение в конференцию. Причина: {1}. +service.gui.INVITATION_RECEIVED_MSG={0} пригласил вас в конференцию {1}. Вы можете принять, отклонить или игнорировать приглашение. +service.gui.INVITATION_REJECTED={0} отклонил ваше приглашение в конференцию. Причина: {1}. service.gui.INVITE=&Пригласить -service.gui.INVITE_CONTACT_MSG=Выберите имена контактов, которые хотите добавить к этому обсуждению и нажмите Пригласить. +service.gui.INVITE_CONTACT_MSG=Выберите имена контактов, которые вы хотите добавить к этой конференции и нажмите Пригласить. service.gui.INVITE_CONTACT_TO_CHAT=Пригласить контакты в чат service.gui.INVITE_CONTACT_TO_CALL=Пригласить контакты к звонку service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Пригласить контакты в видеомост @@ -304,6 +314,8 @@ service.gui.JITSI_WARNING=SIP Communicator был переименован в Ji service.gui.JITSI_WARNING_TITLE=SIP Communicator теперь стал Jitsi service.gui.JOIN=&Войти service.gui.JOIN_AS=В&ойти как +service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Подключиться к существующей видеоконференции +service.gui.JOIN_VIDEO=Подключиться к видео service.gui.CLOSE_CHAT_ROOM_DIALOG=З&акрыть service.gui.JOB_TITLE=Должность service.gui.JOIN_CHAT_ROOM=&Войти в конференцию... @@ -311,6 +323,7 @@ service.gui.JOIN_CHAT_ROOM_TITLE=Войти в конференцию service.gui.JOIN_CHAT_ROOM_NAME=Пожалуйста, введите имя конференции, в которую хотите войти. service.gui.JOIN_CHAT_ROOM_WIZARD=Мастер присоединения к конференции service.gui.JOIN_AUTOMATICALLY=Присоединяться автоматически +service.gui.DONT_JOIN_AUTOMATICALLY=Не подключаться автоматически service.gui.KICK=&Выгнать service.gui.KICK_FAILED=Не удалось выгнать service.gui.KICK_FAILED_GENERAL_ERROR=Не удалось выгнать {0}. Произошла общая ошибка сервера. @@ -319,11 +332,11 @@ service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Не удалось выгнат service.gui.LAST=Последний service.gui.LAST_NAME=Фамилия service.gui.LEAVE=&Покинуть -service.gui.LIMIT_REACHED_FOR_IP=У вас слишком много регистраций с локального IP адреса и сервер {0} не позволяет больше регистраций. -service.gui.LIST=Последний +service.gui.LIMIT_REACHED_FOR_IP=У вас слишком много регистраций с локального IP адреса. Сервер {0} не позволяет больше регистраций. +service.gui.LIST=Список service.gui.LOADING_ROOMS=Загружаю конференции... service.gui.LOADING=Загрузка... -service.gui.LOCALLY_ON_HOLD_STATUS=В ожидании +service.gui.LOCALLY_ON_HOLD_STATUS=Удерживается на линии service.gui.LOGIN_NETWORK_ERROR=Не удаётся подключить аккаунт: Имя пользователя: {0}, Имя сервера: {1}, в связи со сбоем сети. Пожалуйста, проверьте ваше сетевое подключение. service.gui.LOGIN_GENERAL_ERROR=Произошла ошибка во время подключения аккаунта: Имя пользователя: {0}, Имя сервера: {1}:{2}. service.gui.LOGIN_INTERNAL_ERROR=Произошла ошибка во время подключения аккаунта: Имя пользователя: {0}, Имя сервера: {1}. Скорее всего это внутренняя ошибка приложения. Пожалуйста, сообщите о проблеме в наш список рассылки (dev@jitsi.java.net). @@ -351,6 +364,7 @@ service.gui.MSG_DELIVERY_NOT_SUPPORTED=Используемый вами про service.gui.MSG_DELIVERY_INTERNAL_ERROR=Произошла внутренняя ошибка приложения. Возможно это баг. Пожалуйста, сообщите о ней сюда: https://jitsi.org/Development/BugsAndIssues. service.gui.MSG_DELIVERY_ERROR=Не удалось доставить сообщение. service.gui.MSG_DELIVERY_UNKNOWN_ERROR=Произошла неизвестная ошибка во время доставки вашего сообщения. +service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION=Неподдерживаемая операция. service.gui.MSG_NOT_DELIVERED=Произошла сетевая ошибка. Пожалуйста, проверьте вашу сетевую конфигурацию и попробуйте снова. service.gui.MSG_NOT_POSSIBLE=Обмен сообщениями невозможен для данного контакта (не поддерживается протоколом) service.gui.MSG_RECEIVED={0} написал @@ -359,7 +373,7 @@ service.gui.MULTIPLE_LOGINS=Вы подключены больше одного service.gui.MY_CHAT_ROOMS=Добавить комнату service.gui.MY_CHAT_ROOMS_TITLE=Добавить комнату service.gui.MUTE=Отключить звук -service.gui.MUTUALLY_ON_HOLD_STATUS=В ожидании +service.gui.MUTUALLY_ON_HOLD_STATUS=Совместное удержание service.gui.NAME=Имя service.gui.NETWORK=Сеть service.gui.NETWORK_FAILURE=Сбой сети @@ -369,19 +383,20 @@ service.gui.NEW_MESSAGE=Новое сообщение service.gui.NEW_NAME=Новое имя service.gui.NEW_STATUS_MESSAGE=Новый статус сообщения service.gui.NEW_STATUS_MESSAGE_SAVE=Сохранить собственное сообщение +service.gui.NICKNAME=Псевдоним service.gui.NO=Нет service.gui.NONE=Нет -service.gui.NO_CAMERA_AVAILABLE=Камера не подключена +service.gui.NO_CAMERA_AVAILABLE=Камера не обнаружена service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=Демонстрация рабочего стола не поддерживается данным протоколом service.gui.NO_VIDEO_ENCODINGS=Видеокодеки не определены в конфигурации service.gui.NO_VIDEO_FOR_PROTOCOL=Передача видео не поддерживается для данного протокола service.gui.NO_AVAILABLE_ROOMS=Список комнат для этого сервера в настоящее время не доступен. service.gui.NO_CONTACTS_FOUND=Соответствующие контакты не найдены. Нажмите Ctrl+Enter, чтобы позвонить {0} или используйте кнопки ниже. -service.gui.NO_CONTACTS_FOUND_SHORT=Соответствующие контакты не найдены. +service.gui.NO_CONTACTS_FOUND_SHORT=Подходящих контактов не найдено. service.gui.NO_MESSAGE=Нет сообщений service.gui.NO_GROUP_CHAT_ACCOUNT_AVAILABLE=Не обнаружены аккаунты с поддержкой многопользовательского чата. Посетите jitsi.org для получения более подробной информации о том какие протоколы поддерживает многопользовательский чат. service.gui.NO_ONLINE_CONFERENCING_ACCOUNT=Аккаунт не поддерживает конференции. Проверьте https://jitsi.org для получения информации о протоколах с поддержкой конференций. -service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=По крайней мере один SIP Аккаунт необходим для того, чтобы сделать звонок. Войдите в один из ваших SIP аккаунтов и повторите попытку. +service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=По крайней мере один SIP аккаунт необходим для того, чтобы сделать звонок. Войдите в один из ваших SIP аккаунтов и повторите попытку. service.gui.NOT_AUTHORIZED=Не авторизован service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=В этом чате есть не отправленное сообщение. Вы уверены, что хотите закрыть этот чат? service.gui.NON_EXISTING_USER_ID=На сервере {0} нет такого пользователя. @@ -397,11 +412,20 @@ service.gui.OPEN_FOLDER=Открыть папку service.gui.OPEN_IN_BROWSER=Открыть в &браузере service.gui.OPTIONS=Опции service.gui.OPEN_AUTOMATICALLY=Открыть комнату автоматически в случае +service.gui.OPEN_ON_ACTIVITY=Открыть активность +service.gui.OPEN_ON_MESSAGE=Открыть только по сообщению service.gui.OPEN_ON_IMPORTANT_MESSAGE=Открывать только для важных сообщений service.gui.OR=или service.gui.OR_ENTER_PHONE_NUMBER=Или введите номер телефона здесь... service.gui.ORGANIZATION=Организация service.gui.OTHER=Другое +service.gui.chat.role.OWNER=Владелец +service.gui.chat.role.ADMINISTRATOR=Администратор +service.gui.chat.role.MODERATOR=Модератор +service.gui.chat.role.MEMBER=Участник +service.gui.chat.role.GUEST=Гость +service.gui.chat.role.SILENT_MEMBER=Безмолвный участник +service.gui.chat.role.OUTCAST=Запрещено подключаться service.gui.OWNER=владелец комнаты service.gui.ON_MOBILE_TOOLTIP=(на мобильный) service.gui.PASSWORD=Пароль @@ -416,6 +440,7 @@ service.gui.PREFIX=Префикс service.gui.PRESENCE=Присутствие service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' для предложений service.gui.PRESS_FOR_CALL_INFO=Нажмите для получения информации о звонке +service.gui.PRESS_TO_OPEN_CRM=Нажмите для открытия приложения CRM service.gui.PREVIOUS=Предыдущий service.gui.PREVIOUS_TOOLTIP=Обзор старых разговоров service.gui.PRINT=&Печать @@ -428,6 +453,7 @@ service.gui.QUIT=&Выйти service.gui.READY=Готово service.gui.RECENT_MESSAGES=Последние разговоры service.gui.REASON=Причина +service.gui.RECEIVED={0} получено service.gui.RECONNECTION_LIMIT_EXCEEDED=Вы были отключены и подключены к серверу слишком быстро. Следующий аккаунт: Имя пользователя: {0}, Сервер: {1} временно заблокирован и придется немного подождать, прежде чем пробовать войти снова. service.gui.RE_REQUEST_AUTHORIZATION=Запрос повторной авторизации service.gui.REFERRED_STATUS=Переведен @@ -447,7 +473,8 @@ service.gui.RENAME_CONTACT=Переименовать &контакт service.gui.RENAME_CONTACT_WIZARD=В поле ниже можно указать имя, которое вы хотели бы использовать для данного контакта. service.gui.RENAME_GROUP=Переименовать &группу service.gui.RENAME_GROUP_INFO=В поле ниже можно указать название, которое хотите использовать для данной группы. -service.gui.RINGING_STATUS=Вызываю +service.gui.RENAME_CLEAR_USER_DEFINED=Восстановить +service.gui.RINGING_STATUS=Звонит service.gui.REQUEST=&Запрос service.gui.REQUEST_AUTHORIZATION=&Запрос авторизации service.gui.REQUEST_AUTHORIZATION_MSG=Не удается добавить {0} в список контактов. {0} должен разрешить запрос на добавление. Пожалуйста, введите Ваш запрос ниже. @@ -473,6 +500,8 @@ service.gui.SELECT_GROUP_WIZARD=Укажите группу service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Представленный ниже список содержит все учетные записи, которые поддерживают многопользовательский чат. Выберите тот, который хотите использовать для создания конференции. service.gui.SELECT_PROVIDERS_WIZARD_MSG=Приведенный ниже перечень содержит все зарегистрированные учетные записи. Выберите ту, которую хотите использовать для общения с новым контактом. service.gui.SELECT_PROVIDERS_WIZARD=Выберите аккаунт +service.gui.SELECT_VIDEO_CONFERENCE=Выбрать видеоконференцию +service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Выберите чат-комнату из списка и нажмите OK чтобы добавить ее service.gui.SEND=&Отправить service.gui.SEND_FILE=Отправить &файл service.gui.SELECT_CONTACT_SUPPORTING_INFO=Информация об этом контакте отсутствует. @@ -485,13 +514,13 @@ service.gui.SEND_SMS_NOT_SUPPORTED=Выбранный протокол не по service.gui.SMS=СМС service.gui.SEND_VIA=Отправить по service.gui.SENT=посланный -service.gui.SERVER_CHAT_ROOMS=Сервер комнаты +service.gui.SERVER_CHAT_ROOMS=Серверные чат комнаты service.gui.SET_GLOBAL_STATUS=Установить глобальный статус service.gui.SET_STATUS_MESSAGE=Установить статус сообщения service.gui.SET_SUBJECT=Задать тему service.gui.SETTINGS=&Опции -service.gui.SHARE_DESKTOP=&Открыть рабочий стол -service.gui.SHARE_DESKTOP_WITH_CONTACT=Открыть рабочий стол контакту +service.gui.SHARE_DESKTOP=&Предоставить доступ к рабочему столу +service.gui.SHARE_DESKTOP_WITH_CONTACT=Предоставить контакту доступ к рабочему столу service.gui.SHARE_FULL_SCREEN=Открыть рабочий стол в полноэкранном режиме service.gui.SHARE_REGION=Открыть часть service.gui.SHOW=Показать @@ -521,16 +550,16 @@ service.gui.TOOLS=&Инструменты service.gui.TRANSFER=Передача service.gui.TO=&Кому: service.gui.TRANSFER_CALL_MSG=Выберите контакт, который хотите передать, и нажмите Передача. -service.gui.TRANSFER_CALL_TITLE=Перевести звонок +service.gui.TRANSFER_CALL_TITLE=Передача вызова service.gui.TRANSFER_CALL_TO=Перевод на: -service.gui.TRANSPARENCY_NOT_ENABLED=Прозрачность не поддерживается текущей конфигурацией. +service.gui.TRANSPARENCY_NOT_ENABLED=Прозрачность не поддерживается вашей текущей конфигурацией. service.gui.TYPE_YOUR_REQUEST=Введите свой запрос здесь service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Не удалось изменить качество видео для этого вызова. service.gui.UNMUTE=Включить звук service.gui.USER_IDENTIFIER=Идентификатор пользователя: service.gui.USER_EXISTS_ERROR=Этот пользователь уже существует в выбранной сети. Пожалуйста, выберите другого пользователя или сеть. service.gui.USERNAME_NULL=Пожалуйста, заполните свое имя пользователя и пароль. -service.gui.WEBPAGE=Открыть веб страницу +service.gui.WEBPAGE=Открыть веб-страницу service.gui.ACCOUNT_CREATION_FAILED=Мы не смогли создать учетную запись из-за следующей ошибки: {0} service.gui.UNKNOWN=Неизвестный пользователь service.gui.UNKNOWN_STATUS=Неизвестное состояние @@ -545,7 +574,7 @@ service.gui.VIEW_HISTORY=Показать &историю service.gui.VIEW_SMILEYS=Показать &смайлы service.gui.VIEW_TOOLBAR=Показать &тулбар service.gui.VIEW_SIMPLE_CHAT_THEME=Простой вид чата -service.gui.VOICEMAIL_NEW_URGENT_OLD_RECEIVED={0} новых ({1} важных) и {2} старых сообщений +service.gui.VOICEMAIL_NEW_URGENT_OLD_RECEIVED={0} новых ({1} срочных) и {2} старых сообщений service.gui.VOICEMAIL_NEW_URGENT_RECEIVED={0} новых ({1} срочных) сообщений service.gui.VOICEMAIL_NEW_OLD_RECEIVED={0} новых и {1} старых сообщений service.gui.VOICEMAIL_NEW_RECEIVED={0} новых сообщений @@ -553,7 +582,7 @@ service.gui.VOICEMAIL_OLD_RECEIVED={0} старых сообщений service.gui.VOICEMAIL_NO_MESSAGES=Нет сообщений. service.gui.VOICEMAIL_TITLE=Голосовые сообщения service.gui.VOICEMAIL_TOOLTIP=Голосовые сообщения для: -service.gui.VOICEMAIL_TIP=Нажмите кнопку вызова для прослушивания сообщений. +service.gui.VOICEMAIL_TIP=Нажмите кнопку вызова, чтобы прослушать ваши сообщения. service.gui.VOICEMAIL_TIP_NO_ACCOUNT=Пожалуйста, настройте URI для проверки голосовой почты в учетной записи service.gui.VOLUME_CONTROL_TOOL_TIP=Регулировка громкости service.gui.WAITING_AUTHORIZATION=Ожидание авторизации @@ -569,13 +598,17 @@ service.gui.NEW_GMAIL_MANY_FOOTER={1} еще непрочитанный разг service.gui.ACTIVATE=Активировать service.gui.DEACTIVATE=Деактивировать service.gui.NEW=Новый -service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Развернуть на весь экран +service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Войти в полноэкранный режим service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Выйти из полноэкранного режима service.gui.HOLD_BUTTON_TOOL_TIP=Удержание разговора service.gui.MUTE_BUTTON_TOOL_TIP=Выключить микрофон или удерживайте кнопку для настройки громкости микрофона +service.gui.PARK=Удержание +service.gui.PARKING_SLOT=Место для удержания: +service.gui.PARK_BUTTON_TOOL_TIP=Поставить звонок на удержание service.gui.RECORD_BUTTON_TOOL_TIP=Запись разговора service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=Включить видеосвязь service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Показать/скрыть свое видео +service.gui.SHOW_HIDE_PEERS_TOOL_TIP=Показать/скрыть список участников конференции service.gui.TRANSFER_BUTTON_TOOL_TIP=Переадресовать вызов service.gui.TRANSFER_TO=Переадресовать на... service.gui.SECURITY_INFO=Информация о безопасности @@ -591,7 +624,9 @@ service.gui.WORK_PHONE=Рабочий service.gui.PHONE=Телефон service.gui.PHONES=Телефон service.gui.EDIT_NOT_SUPPORTED=Редактирование этой учетной записи не поддерживается -service.gui.SHOW_PREVIEW=(показать превью) +service.gui.SHOW_PREVIEW=(предварительный просмотр) +service.gui.SHOW_PREVIEW_WARNING_DESCRIPTION=Вы хотите отобразить это изображение ?\n\nИмейте в виду, что предпросмотр изображений/видео можеть нарушить Вашу анонимность и раскрыть Вашу активность в сети. +service.gui.SHOW_PREVIEW_DIALOG_TITLE=Показать предпросмотр изображения/видео service.gui.ZID_NAME_SET=Имя ZRTP идентификатора: service.gui.ZID_NAME_NOT_SET=Не задано имя ZRTP идентификатора. @@ -621,6 +656,9 @@ service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Шифрование включено service.gui.callinfo.CALL_TRANSPORT=Транспорт сигнализации service.gui.callinfo.CALL_DURATION=Длительность вызова service.gui.callinfo.TLS_PROTOCOL=Протокол TLS +service.gui.callinfo.TLS_CIPHER_SUITE=набор шифров TLS +service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=цепочка сертификатов TLS сервера +service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Содержимое сертификата TLS сервера показано ниже. service.gui.callinfo.VIEW_CERTIFICATE=Просмотр сертификата service.gui.callinfo.CODEC=Кодек / Частота service.gui.callinfo.NA=N.A. @@ -655,7 +693,9 @@ service.gui.callinfo.HARVESTING_MS_FOR=мс (для service.gui.callinfo.HARVESTS=результатов) service.gui.callinfo.DECODED_WITH_FEC=Пакетов декодированных с FEC service.gui.callinfo.DISCARDED_PERCENT=Отброшенных пакетов -service.gui.callinfo.DISCARDED_TOTAL=Всего отброшенных пакетов +service.gui.callinfo.DISCARDED_TOTAL=Количество отброшенных пакетов +service.gui.callinfo.ADAPTIVE_JITTER_BUFFER=Адаптивный буфер синхронизации +service.gui.callinfo.JITTER_BUFFER_DELAY=Буфер синхронизации service.gui.ALWAYS_TRUST=Всегда доверять этому сертификату service.gui.CERT_DIALOG_TITLE=Проверить сертификат @@ -664,18 +704,24 @@ service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} не может про service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} не может проверить подлинность клиента.

    Сертификат не является доверенным, это означает, что клиент не
    может быть автоматически проверен. Вы хотите принять подключение?

    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} не может проверить подлинность клиента {1}.

    Сертификат не является доверенным, это означает, что клиент не
    может быть автоматически проверен. Вы хотите продолжить подключение?

    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". service.gui.CONTINUE_ANYWAY=Все равно продолжить +service.gui.CERT_INFO_CHAIN=Цепочка сертификатов: +service.gui.CERT_INFO_ISSUED_TO=Выпущен для service.gui.CERT_INFO_CN=Имя сертификата: service.gui.CERT_INFO_O=Организация: service.gui.CERT_INFO_C=Страна: service.gui.CERT_INFO_ST=Штат или область: service.gui.CERT_INFO_L=Населенный пункт: +service.gui.CERT_INFO_ISSUED_BY=Выдан service.gui.CERT_INFO_OU=Подразделение: +service.gui.CERT_INFO_VALIDITY=Срок действия service.gui.CERT_INFO_ISSUED_ON=Действителен с: service.gui.CERT_INFO_EXPIRES_ON=Действителен по: -service.gui.CERT_INFO_FINGERPRINTS=Ключ +service.gui.CERT_INFO_FINGERPRINTS=Отпечатки +service.gui.CERT_INFO_CERT_DETAILS=Информация о сертификате service.gui.CERT_INFO_SER_NUM=Серийный номер: service.gui.CERT_INFO_VER=Версия: service.gui.CERT_INFO_SIGN_ALG=Алгоритм подписи: +service.gui.CERT_INFO_PUB_KEY_INFO=Информация об открытом ключе service.gui.CERT_INFO_ALG=Алгоритм: service.gui.CERT_INFO_PUB_KEY=Открытый ключ: service.gui.CERT_INFO_KEY_BYTES_PRINT={0} байт: {1} @@ -699,6 +745,8 @@ service.gui.AUTO_ANSWER_FWD_CALLS=Переадресация звонков service.gui.AUTO_ANSWER_FWD_CALLS_TO=Переадресовывать все звонки на номер или URI: service.gui.AUTO_ANSWER_VIDEO=Видеовызовы service.gui.AUTO_ANSWER_VIDEO_CALLS_WITH_VIDEO=Отвечать на видеозвонки с видео +service.gui.LOCAL_VIDEO_ERROR_TITLE=Ошибка с локальным видео +service.gui.LOCAL_VIDEO_ERROR_MESSAGE=Невозможно включить/выключить локальное видео. service.gui.security.SECURE_AUDIO=Аудиопоток защищен service.gui.security.AUDIO_NOT_SECURED=Аудиопоток не защищен @@ -713,12 +761,13 @@ service.gui.security.COMPARE_WITH_PARTNER=Сверьте ключ с собес # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Сверьте ключ с собеседником: service.gui.security.STRING_COMPARED=Ключ подтвержден! +service.gui.security.SAS_INFO_TOOLTIP=Чтобы полностью быть защищённым, Вам
    следует голосом сверитькороткую
    строку аутентификации, указанную здесь,
    с партнером и нажать кнопку подтверждения, когда
    строка будет проверена.

    Если Вы очистите подтверждение, Вам потребуется заново проверять собеседника
    при следующем звонке этому партнеру. service.gui.security.SECURITY_ALERT=Инициализация защиты вызова. Отключение через -service.gui.avatar.CHOOSE_ICON=Выбрать аватар +service.gui.avatar.CHOOSE_ICON=Выбрать картинку service.gui.avatar.REMOVE_ICON=Удалить текущий аватар service.gui.avatar.CLEAR_RECENT=Очистить список -service.gui.avatar.RECENT_ICONS=Аватары: +service.gui.avatar.RECENT_ICONS=Недавние картинки: # service.gui.avatar.imagepicker service.gui.avatar.imagepicker.CANCEL=Отмена service.gui.avatar.imagepicker.CHOOSE_FILE=Обзор ... @@ -734,6 +783,7 @@ service.gui.avatar.imagepicker.WEBCAM_ERROR=Ошибка вебкамеры service.gui.security.encryption.required=Требуется шифрование! +service.protocol.ICE_FAILED=Невозможно установить подключение (сбой ICE, не найдено трансляции) # impl.protocol.ssh #Contact Details Seperator(must not be part of contact data stored as persistent @@ -764,6 +814,10 @@ impl.ldap.GENERAL=Общие impl.ldap.FIELDS=Поля impl.ldap.QUERY=Запрос impl.ldap.QUERY_DEFAULT=Создать автоматически +impl.ldap.QUERY_CUSTOM=Индивидуальный запрос +impl.ldap.QUERY_CUSTOM_HINT=Используйте {0} в качестве шаблона для поиска термина. +impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Автоматически добавить метасимволы в текст запроса +impl.ldap.QUERY_PHOTO_INLINE=Получать фото вместе с остальными атрибутами impl.ldap.NEW=Новый impl.ldap.EDIT=изменить impl.ldap.REMOVE=Удалить @@ -804,9 +858,11 @@ plugin.addrbook.ADDRESS_BOOKS=Адресная книга plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Включить поиск в адресной книге MacOSX plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK=Включить поиск контактов в Microsoft Outlook plugin.addrbook.DESCRIPTION=Если включено, будет производиться поиск в системной адресной книге и все соответствующие контакты из адресной книги появятся в вашем списке контактов. -plugin.addrbook.DEFAULT_IM_APP=Сделать Jitsi клиентом для мгновенного обмена сообщениями по умолчанию (Интеграция с Outlook) +plugin.addrbook.DEFAULT_IM_APP=Сделать Jitsi клиентом для обмена мгновенными сообщениями по умолчанию (Интеграция с Outlook) plugin.addrbook.PREFIX=Телефонный префикс plugin.addrbook.PREFIX_EXAMPLE=Например: +7 +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE=Ошибка доступа к контактам Microsoft Outlook +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT={0} не может в данный момент получить доступ к контактам Microsoft Outlook, так как Outlook не является почтовой программой по умолчанию. plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Сделать Outlook почтовым клиентом по умолчанию # Google Contacts @@ -836,14 +892,17 @@ plugin.accountinfo.NICKNAME=Ник: plugin.accountinfo.URL=URL: plugin.accountinfo.AGE=Возраст: plugin.accountinfo.BDAY=Дата рождения: +plugin.accountinfo.BDAY_FORMAT=МММ дд, гггг plugin.accountinfo.GENDER=Пол: plugin.accountinfo.STREET=Адрес: plugin.accountinfo.CITY=Город: plugin.accountinfo.REGION=Область: plugin.accountinfo.POST=Почтовый индекс: -plugin.accountinfo.COUNTRY=Страна +plugin.accountinfo.COUNTRY=Страна: plugin.accountinfo.EMAIL=Электронный ящик: +plugin.accountinfo.WORK_EMAIL=Рабочий E-mail: plugin.accountinfo.PHONE=Телефон: +plugin.accountinfo.WORK_PHONE=Рабочий телефон: plugin.accountinfo.MOBILE_PHONE=Мобильный телефон: plugin.accountinfo.ORGANIZATION=Организация: plugin.accountinfo.JOB_TITLE=Должность: @@ -856,6 +915,7 @@ plugin.accountinfo.CHANGE=Изменить plugin.accountinfo.ONLY_MESSAGE=Только сообщения # connection info +plugin.connectioninfo.TITLE=Информация о соединении # contact info plugin.contactinfo.TITLE=Информация о контакте @@ -863,7 +923,7 @@ plugin.contactinfo.CONTACT_SUMMARY_DESCRIPTION=Суммарная информа plugin.contactinfo.CONTACT_EXTENDED_DESCRIPTION=Расширенный контактные данные plugin.contactinfo.NOT_SPECIFIED=[Не указано] plugin.contactinfo.USER_PICTURES=Фотография пользователя -plugin.contactinfo.USER_STATUS_MESSAGE=Статус +plugin.contactinfo.USER_STATUS_MESSAGE=Сообщение о состоянии # aimaccregwizz plugin.aimaccregwizz.PROTOCOL_NAME=AIM @@ -883,6 +943,8 @@ plugin.branding.WELCOME_MESSAGE=
    {1} в настоящее вре plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Все права защищены. Посетите https://jitsi.org.
    plugin.branding.LICENSE=
    Jitsi распространяется по лицензии LGPL (http://www.gnu.org).
    +plugin.busylampfield.PICKUP=Поднять трубку + # Dict protocol service.protocol.DICTIONARIES=Словари plugin.dictaccregwizz.ANY_DICTIONARY=Любой словарь @@ -918,7 +980,7 @@ plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Имя пользователя # generalconfig plugin.generalconfig.AUTO_START=Автоматический запуск {0} при загрузке компьютера -plugin.generalconfig.CHATALERTS_ON_MESSAGE=Использовать панель задач / область уведомлений для входящих звонков и сообщений +plugin.generalconfig.CHATALERTS_ON_MESSAGE=Использовать панель задач / область уведомлений для входящих звонков и бесед plugin.generalconfig.GROUP_CHAT_MESSAGES=Группировать текстовые чаты в одном окне plugin.generalconfig.LOG_HISTORY=История чата plugin.generalconfig.SHOW_HISTORY=Показывать @@ -938,13 +1000,18 @@ plugin.generalconfig.ERROR_PORT_NUMBER=Неверный номер порта plugin.generalconfig.CHECK_FOR_UPDATES=Проверять наличие обновлений при запуске plugin.generalconfig.STARTUP_CONFIG=Запуск plugin.generalconfig.LEAVE_CHATROOM_ON_WINDOW_CLOSE=Сообщить о выходе из чата при закрытии окна +plugin.generalconfig.SHOW_RECENT_MESSAGES=Показать недавние беседы (зависит от истории разговоров) plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Удалить специальные символы из телефонного номера, прежде чем сделать вызов plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Преобразовывать буквы в цифры телефонного номера plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=напр. +1-800-MYPHONE преобразуется в +1-800-694663 plugin.generalconfig.SIP_CALL_CONFIG=SIP plugin.generalconfig.OPUS_CONFIG=Кодек Opus +plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Частота выборки: +plugin.generalconfig.OPUS_BITRATE=Средняя скорость кодировщика (кбит/с) plugin.generalconfig.OPUS_USE_DTX=Использовать DTX: plugin.generalconfig.OPUS_USE_FEC=Использовать Inband FEC: +plugin.generalconfig.OPUS_COMPLEXITY=Сложность кодировщика: +plugin.generalconfig.OPUS_MIN_EXPECTED_PACKET_LOSS=Минимальные ожидаемые потери пакетов(%): plugin.generalconfig.SILK_CONFIG=Silk plugin.generalconfig.SILK_USE_FEC=Использовать Inband FEC: plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Всегда учитывать потери пакетов: @@ -969,12 +1036,24 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Регистрация новой уч plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=Протокол IRC. plugin.ircaccregwizz.USERNAME_AND_PASSWORD=UIN и пароль +plugin.ircaccregwizz.USERNAME=Псевдоним +plugin.ircaccregwizz.EXAMPLE_USERNAME=Пример: IRC-пользователь plugin.ircaccregwizz.INFO_PASSWORD=Большинство IRC серверов не требуют пароля. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Автоматически менять ник, когда он уже используется plugin.ircaccregwizz.USE_DEFAULT_PORT=Использовать порт по умолчанию plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=Мой ник не требует идентификации plugin.ircaccregwizz.HOST=Хост: plugin.ircaccregwizz.IRC_SERVER=Сервер +plugin.ircaccregwizz.EXAMPLE_SERVER=Пример: chat.freenode.net +plugin.ircaccregwizz.USE_SECURE_CONNECTION=Использовать безопасное подключение +plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Включить присутствие контакта +plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Включить присутствие чат комнаты +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=SASL аутентификация +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=Включить SASL аутентификацию +plugin.ircaccregwizz.SASL_USERNAME=Имя пользователя +plugin.ircaccregwizz.SASL_AUTHZ_ROLE=Должность +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=Вышеупомянутый IRC пароль используется для SASL аутентификации +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Всегда разрешать DNS имена через прокси # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP @@ -998,7 +1077,7 @@ plugin.jabberaccregwizz.RESOURCE=Ресурс plugin.jabberaccregwizz.AUTORESOURCE=Автоматическое создание ресурса plugin.jabberaccregwizz.PRIORITY=Приоритет plugin.jabberaccregwizz.XMPP_ERROR=Ошибка XMPP -plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Неизвестная ошибка XMPP ({0)}. Убедитесь, что имя сервера, является правильным. +plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Неизвестная ошибка XMPP ({0)}. Убедитесь, что имя сервера является правильным. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Пароли не совпадают. plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Переопределить параметры сервера по умолчанию plugin.jabberaccregwizz.ADVANCED_OPTIONS=Дополнительные параметры @@ -1007,7 +1086,7 @@ plugin.jabberaccregwizz.USE_GOOGLE_ICE=Использовать Google Jingle/IC plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Автоматически обнаруживать STUN/TURN сервера plugin.jabberaccregwizz.SUPPORT_TURN=Поддерживать TURN plugin.jabberaccregwizz.TURN_USERNAME=Имя пользователя TURN -plugin.jabberaccregwizz.IP_ADDRESS=IP Адрес +plugin.jabberaccregwizz.IP_ADDRESS=IP-Адрес plugin.jabberaccregwizz.ADD_STUN_SERVER=Добавить STUN-сервер plugin.jabberaccregwizz.EDIT_STUN_SERVER=Редактировать STUN-сервер plugin.jabberaccregwizz.ADDITIONAL_STUN_SERVERS=Дополнительные STUN-сервера @@ -1027,6 +1106,7 @@ plugin.jabberaccregwizz.EXISTING_ACCOUNT=Существующий аккаунт plugin.jabberaccregwizz.DOMAIN_BYPASS_CAPS=Домен, для которого будут использоваться GTalk-вызовы plugin.jabberaccregwizz.TELEPHONY_DOMAIN=Домен для телефонии plugin.jabberaccregwizz.ALLOW_NON_SECURE=Разрешить небезопасные подключения +plugin.jabberaccregwizz.DISABLE_CARBON=Отключить мультиклиентный обмен сообщениями plugin.jabberaccregwizz.DTMF_AUTO=Автоматически выбирать между RTP и Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Параметры сервера plugin.jabberaccregwizz.CHANGE_PASSWORD=Изменить пароль @@ -1039,7 +1119,7 @@ plugin.jabberaccregwizz.TLS_REQUIRED=Соединение не использу plugin.jabberaccregwizz.PASSWORD_CHANGED=Пароль успешно изменен plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Ваш XMPP сервер не поддерживает изменение пароля. plugin.jabberaccregwizz.PASSWORD_NOT_STORED=Пароль был изменен на сервере, но локальные настройки обновлены не были -plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=Пожалуйста, введите Ваш новый пароль в оба поля: +plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=Пожалуйста, введите ваш новый пароль в оба поля: plugin.jabberaccregwizz.OVERRIDE_ENCODINGS=Переопределить глобальные настройки кодеков plugin.jabberaccregwizz.ENCODINGS=Кодеки plugin.jabberaccregwizz.AUDIO=Аудио @@ -1103,6 +1183,8 @@ plugin.sipaccregwizz.KEEP_ALIVE=Поддерживать активным plugin.sipaccregwizz.KEEP_ALIVE_METHOD=Метод поддержки plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=Интервал переподключения plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=От 1 до 3600 секунд +plugin.sipaccregwizz.DTMF_MINIMAL_TONE_DURATION=Минимальная длительность RTP DTMF тона (мс) +plugin.sipaccregwizz.DTMF_MINIMAL_TONE_DURATION_INFO=Длительность RTP DTMF по умолчанию 70 мс plugin.sipaccregwizz.DTMF=DTMF plugin.sipaccregwizz.DTMF_METHOD=Метод DTMF plugin.sipaccregwizz.DTMF_AUTO=Автоматически выбирать между RTP и Inband (нет SIP INFO) @@ -1144,9 +1226,9 @@ plugin.sipaccregwizz.SDES_OPTION=Опция SDES # skin manager plugin.skinmanager.SKINS=Скины -plugin.skinmanager.DEFAULT_SKIN=Скин по умолчанию -plugin.skinmanager.ADD_NEW_SKIN=Добавить новый скин... -plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Скин приложения по умолчанию. +plugin.skinmanager.DEFAULT_SKIN=Оболочка по умолчанию +plugin.skinmanager.ADD_NEW_SKIN=Добавить новую оболочку... +plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Оболочка приложения по умолчанию. # ssh accregwizz plugin.sshaccregwizz.PROTOCOL_NAME=SSH @@ -1160,7 +1242,7 @@ plugin.sshaccregwizz.ACCOUNT_DETAILS=Информация об учетной з # status update plugin.autoaway.AUTO_STATUS=Авто отсуствие plugin.autoaway.ENABLE_CHANGE_STATUS=Изменить статус, когда отошел -plugin.autoaway.AWAY_MINUTES=Минут до переключения в ''Нет на месте'': +plugin.autoaway.AWAY_MINUTES=Минут до переключения в режим ''Нет на месте'': # updatechecker plugin.updatechecker.DIALOG_TITLE=Установить обновления @@ -1170,6 +1252,7 @@ plugin.updatechecker.BUTTON_DOWNLOAD=Скачать plugin.updatechecker.BUTTON_CLOSE=Закрыть plugin.updatechecker.BUTTON_INSTALL=Установить plugin.updatechecker.UPDATE_MENU_ENTRY=Проверить обновления +plugin.updatechecker.DIALOG_WARN={0} необходимо выйти перед тем, как он сможет установить обновления. Любые беседы или звонки будут временно отключены. Следует ли {0} продолжить установку обновлений? plugin.updatechecker.DIALOG_NOUPDATE=Ваша версия является актуальной. plugin.updatechecker.DIALOG_NOUPDATE_TITLE=Нет новой версии plugin.updatechecker.DIALOG_MISSING_UPDATE=Обновление установщика не удалось. @@ -1276,7 +1359,7 @@ plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Сочетание клави plugin.keybindings.globalchooser.SHORTCUT_SECOND=Дополнительно plugin.keybindings.globalchooser.PRESS_BTN=Нажмите для назначения сочетания клавиш plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Ожидание -plugin.keybindings.globalchooser.PUSH_TO_TALK=Push to talk +plugin.keybindings.globalchooser.PUSH_TO_TALK=Нажмите, чтобы говорить plugin.keybindings.globalchooser.ENABLE_SPECIAL=Включить обнаружение специальных клавиш plugin.keybindings.PLUGIN_NAME=Сочетания клавиш plugin.keybindings.CHAT=Чат @@ -1376,11 +1459,13 @@ impl.media.configform.AUDIO=&Аудио система: impl.media.configform.AUDIO_IN=Микрофон: impl.media.configform.AUDIO_NOTIFY=&Уведомления: impl.media.configform.AUDIO_OUT=Динамики: +impl.media.configform.AUTOMATICGAINCONTROL=Автоматическая регулировка усиления impl.media.configform.DENOISE=Включить подавления шума impl.media.configform.DEVICES=Устройства impl.media.configform.DOWN=&Вниз impl.media.configform.ECHOCANCEL=Включить подавление эха impl.media.configform.ENCODINGS=Кодеки +impl.media.configform.NO_AVAILABLE_AUDIO_DEVICE=Нет доступного звукового устройства. Пожалуйста, подключите его. impl.media.configform.NO_DEVICE=<Нет устройства> impl.media.configform.NO_PREVIEW=Предварительный просмотр impl.media.configform.UP=&Вверх @@ -1388,25 +1473,31 @@ impl.media.configform.VIDEO=&Выбрать веб-камеру: impl.media.configform.VIDEO_MORE_SETTINGS=Дополнительно impl.media.configform.VIDEO_RESOLUTION=Разрешение видео impl.media.configform.VIDEO_FRAME_RATE=Количество кадров (в сек.) +impl.media.configform.VIDEO_PACKETS_POLICY=Пороговая скорость RTP (кБайт/с) +impl.media.configform.VIDEO_BITRATE=Скорость передачи данных видео (килобит/с) impl.media.configform.VIDEO_RESET=Сброс настроек -impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_IN=Выбрано новое устройство для ввода звука: -impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_OUT=Выбрано новое устройство для вывода звука: -impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS=Выбрано новое устройство для оповещений: -impl.media.configform.VIDEO_DEVICE_SELECTED=Выбрано новое устройство для видео: +impl.media.configform.AUDIO_DEVICE_CONNECTED=Подключенное устройство: +impl.media.configform.AUDIO_DEVICE_DISCONNECTED=Отключенное устройство: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_IN=Новое выбранное устройство для ввода звука: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_OUT=Новое выбранное устройство для вывода звука: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS=Новое выбранное устройство для оповещений: +impl.media.configform.VIDEO_DEVICE_SELECTED=Новое выбранное устройство для видео: impl.media.configform.AUDIO_DEVICE_CONFIG_MANAGMENT_CLICK=Нажмите для настройки устройств impl.neomedia.configform.AUDIO=Аудио impl.neomedia.configform.VIDEO=Видео impl.neomedia.configform.H264=H.264 +impl.neomedia.configform.H264.defaultIntraRefresh=Периодическое обновление интра-данных impl.neomedia.configform.H264.defaultProfile=Профиль для кодирования: impl.neomedia.configform.H264.defaultProfile.baseline=Базовый impl.neomedia.configform.H264.defaultProfile.high=Высокое impl.neomedia.configform.H264.defaultProfile.main=Основной +impl.neomedia.configform.H264.keyint=Максимальный интервал между ключевыми кадрами impl.neomedia.configform.H264.preferredKeyFrameRequester=Метод запроса ключевых кадров: impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTCP impl.neomedia.configform.H264.preferredKeyFrameRequester.signaling=Сигнализация -impl.neomedia.configform.H264.preset=Предустановки кодеков +impl.neomedia.configform.H264.preset=Предустановка шифратора # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -1422,7 +1513,7 @@ plugin.callrecordingconfig.CALL_SAVED_TO={0} plugin.securityconfig.TITLE=Безопасность plugin.securityconfig.masterpassword.TITLE=Пароли plugin.securityconfig.masterpassword.CHANGE_MASTER_PASSWORD=Изменить Мастер-пароль... -plugin.securityconfig.masterpassword.USE_MASTER_PASSWORD=Использовать Мастер-пароль +plugin.securityconfig.masterpassword.USE_MASTER_PASSWORD=Использовать мастер-пароль plugin.securityconfig.masterpassword.SAVED_PASSWORDS=Сохраненные пароли... plugin.securityconfig.masterpassword.INFO_TEXT=Мастер-пароль используется для защиты сохраненных паролей к учетным записям. Пожалуйста, убедитесь, что вы запомнили его. plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Текущий пароль: @@ -1430,7 +1521,7 @@ plugin.securityconfig.masterpassword.ENTER_PASSWORD=Введите новый п plugin.securityconfig.masterpassword.REENTER_PASSWORD=Введите пароль повторно: plugin.securityconfig.masterpassword.MP_TITLE=Мастер-пароль plugin.securityconfig.masterpassword.MP_NOT_SET=(не установлено) -plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Вы ввели неправильный текущий Мастер-пароль. Пожалуйста, попробуйте еще раз. +plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Вы ввели неправильный текущий мастер-пароль. Пожалуйста, попробуйте еще раз. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Мастер-пароль неправильный! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Изменение пароля не удалось plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS=Пароль успешно изменен @@ -1455,11 +1546,14 @@ plugin.securityconfig.masterpassword.PASSWORD_QUALITY_METER=Сложность plugin.securityconfig.masterpassword.MP_INPUT=Пожалуйста введите ваш мастер-пароль:\n\n # otr plugin -plugin.otr.menu.TITLE=Шифрование +plugin.otr.menu.TITLE=Безопасная беседа plugin.otr.menu.START_OTR=Начать приватный разговор plugin.otr.menu.END_OTR=Закончить приватный разговор +plugin.otr.menu.FINISHED=Ваш приятель закончил личную беседу. Вам следует сделать то же самое +plugin.otr.menu.VERIFIED=Ваша личная беседа является проверенной +plugin.otr.menu.UNVERIFIED=Ваша личная беседа не является проверенной. Пожалуйста, удостоверьтесь в подлинности вашего приятеля plugin.otr.menu.LOADING_OTR=Начать приватный разговор... -plugin.otr.menu.TIMED_OUT=Начать приватный разговор +plugin.otr.menu.TIMED_OUT=Начало личной беседы просрочено (время вышло). plugin.otr.menu.REFRESH_OTR=Обновить приватный разговор plugin.otr.menu.AUTHENTICATE_BUDDY=Проверка собеседника plugin.otr.menu.WHATS_THIS=О технологии @@ -1469,13 +1563,23 @@ plugin.otr.menu.CB_ENABLE=Включить шифрование сообщени plugin.otr.menu.CB_REQUIRE=Требовать шифрование сообщений plugin.otr.menu.CB_RESET=Сброс plugin.otr.menu.OTR_TOOLTIP=Шифрование переписки OTR -plugin.otr.authbuddydialog.AUTHENTICATION_METHOD=Как бы вы хотели проходить авторизацию? +plugin.otr.authbuddydialog.HELP_URI=https://jitsi.org/GSOC2009/OTR +plugin.otr.authbuddydialog.AUTHENTICATION_INFO=Удостоверение в подлинности собеседника гарантирует, что человек, с которым вы говорите, является тем, за кого он себя выдает. +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD=Как бы вы хотели пройти авторизацию? plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_QUESTION=Вопрос для авторизации +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_SECRET=Авторизация методом секретных данных plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_FINGERPRINT=Авторизация по отпечатку +plugin.otr.authbuddydialog.AUTHENTICATION_FINGERPRINT=Чтобы проверить отпечаток, свяжитесь со своим приятелем через другой подтверждённый канал, такой как телефон или электронная почта с CPG-подписью. Каждому из вас следует сообщить ваш отпечаток друг другу. Если всё совпадает, вы должны пометить следующий диалог как *действительно* проверенный с помощью отпечатка. plugin.otr.authbuddydialog.LOCAL_FINGERPRINT=Ваш ключ, {0}: {1} plugin.otr.authbuddydialog.REMOTE_FINGERPRINT=Ключ собеседника {0}: {1} -plugin.otr.authbuddydialog.QUESTION_INIT=Введите свой вопрос: +plugin.otr.authbuddydialog.AUTH_BY_QUESTION_INFO_INIT=Чтобы проверить подлинность с помощью вопроса, вам необходимо составить вопрос, ответ на который известен только вам и вашему приятелю. Вашему собеседнику зададут этот вопрос и если ответы не будут совпадать, тогда, возможно, вы разговариваете с самозванцем. +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_INIT=Для проверки подлинности с помощью секретных данных вам следует подобрать данные, которые известны только вам и вашему приятелю. Затем вашего приятеля тоже попросят подобрать данные и если они не будут совпадать, тогда, возможно, вы беседуете с самозванцем. +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_RESPOND=Ваш приятель пытается определить, разговаривает ли он с вами или с самозванцем. Он задал вам вопрос. Если вы хотите пройти проверку подлинности, пожалуйста, введите ответ ниже. +plugin.otr.authbuddydialog.SHARED_SECRET=Введите ваш общий секрет: +plugin.otr.authbuddydialog.QUESTION_RESPOND=Ваш приятель задаёт вам вопрос: +plugin.otr.authbuddydialog.QUESTION_INIT=Введите ваш вопрос здесь: plugin.otr.authbuddydialog.ANSWER=Введите свой ответ (с учетом регистра): +plugin.otr.authbuddydialog.AUTHENTICATION_FROM=Проверка подлинности от {0}. plugin.otr.authbuddydialog.CANCEL=Отмена plugin.otr.authbuddydialog.HELP=Помощь plugin.otr.authbuddydialog.TITLE=Проверка собеседника @@ -1484,6 +1588,7 @@ plugin.otr.authbuddydialog.I_HAVE=Есть plugin.otr.authbuddydialog.I_HAVE_NOT=Я не plugin.otr.authbuddydialog.VERIFY_ACTION=подтверждаю, что это действительно правильный ключ для {0}. plugin.otr.authbuddydialog.FINGERPRINT_CHECK=Пожалуйста, введите уникальный код, полученный от {0}. +plugin.otr.smpprogressdialog.TITLE=Процесс проверки подлинности plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS=Проверка прошла успешно! plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL=Сбой проверки подлинности! plugin.otr.configform.MY_PRIVATE_KEYS=Собственные ключи @@ -1496,7 +1601,7 @@ plugin.otr.configform.GENERATE=Создать plugin.otr.configform.REGENERATE=Обновить plugin.otr.configform.FINGERPRINT=Ключ plugin.otr.configform.VERIFY_FINGERPRINT=Подтвердить ключ -plugin.otr.configform.FORGET_FINGERPRINT=Отклонить ключ +plugin.otr.configform.FORGET_FINGERPRINT=Забыть отпечаток plugin.otr.configform.COLUMN_NAME_CONTACT=Контакт plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=Проверен plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=Да @@ -1504,12 +1609,23 @@ plugin.otr.configform.COLUMN_VALUE_VERIFIED_FALSE=Нет plugin.otr.activator.unverifiedsessionwarning={0} связывается с Вами с недоверенного компьютера. Вы должны проверить подлинность собеседника {0}. plugin.otr.activator.unverifiedsessionstared=Непроверенный приватный разговор с {0} начался. plugin.otr.activator.sessionstared=Приватный разговор с {0} начался. -plugin.otr.activator.sessionfinished={0} закончил приватный разговор с Вами. Вы должны сделать то же самое. +plugin.otr.activator.sessionfinished={0} закончил приватный разговор с вами. Вы должны сделать то же самое. plugin.otr.activator.sessionlost=Приватный разговор с {0} закончен. -plugin.otr.activator.unreadablemsgreceived={0} отправил нечитаемое шифрованное сообщение. +plugin.otr.activator.historyon={0} записывает эту беседу на ваше устройство. Вы можете отключить историю разговора здесь. +plugin.otr.activator.historyoff={0} НЕ записывает эту беседу. Вы можете активировать историю разговора здесь. +plugin.otr.activator.sessionfinishederror=Ваше сообщение [{0}] не было отправлено. Пожалуйста, закончите вашу личную беседу с {1}. +plugin.otr.activator.smpaborted={0} прервал процесс проверки подлинности. +plugin.otr.activator.smperror=В процессе проверки подлинности произошла ошибка. +plugin.otr.activator.unencryptedmsgreceived=Сообщение было получено в незашифрованном виде. +plugin.otr.activator.unreadablemsgreceived={0} отправил вам неразборчивое зашифрованное сообщение. +plugin.otr.activator.requireencryption=Ваше сообщение [{0}] не было отправлено. Требуется конфиденциальный обмен сообщениями. +plugin.otr.activator.unreadablemsgreply=Вы отправили {0} неразборчивое зашифрованное сообщение. Пожалуйста, закончите вашу личную беседу с {1} или обновите её. +plugin.otr.activator.fallbackmessage={0} пытается начать с вами зашифрованную беседу в формате Off-The-Record. Однако, ваше программное обеспечение не поддерживает Off-The-Record. Для большей информации смотрите http://en.wikipedia.org/wiki/Off-the-Record_Messaging +plugin.otr.activator.multipleinstancesdetected=Ваш приятель {0} вошёл в систему много раз и ОТР установила несколько сеансов. Вы можете выбрать исходящий сеанс из меню ниже. +plugin.otr.activator.msgfromanotherinstance={0} отправил вам сообщение, которое было предназначено для другой сессии. Если вы вошли в систему несколько раз, другая сессия, возможно, получила это сообщение. # global proxy plugin -plugin.globalproxy.GLOBAL_PROXY_CONFIG=Прокси-сервер +plugin.globalproxy.GLOBAL_PROXY_CONFIG=Глобальный прокси-сервер plugin.globalproxy.PROXY_TYPE=Тип прокси-сервера plugin.globalproxy.PROXY_ADDRESS=Прокси-сервер plugin.globalproxy.PROXY_PORT=Порт @@ -1518,8 +1634,10 @@ plugin.globalproxy.PROXY_PASSWORD=Пароль plugin.globalproxy.DESCRIPTION={0} будет использовать перечисленные параметры прокси-сервера для всех сетей при следующем подключении. \nПоддержка прокси в настоящее время экспериментальная и работает только с некоторыми протоколами. Смотрите таблицу ниже для более подробной информации: plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT -plugin.globalproxy.FWD_DNS_ADDR=Адрес сервера DNS Proxy -plugin.globalproxy.FWD_DNS_PORT=Порт сервера DNS Proxy +plugin.globalproxy.FWD_DNS=Также проксифицировать DNS +plugin.globalproxy.FWD_DNS_NOTE=Полезно с Тор. Помогает избежать утечки DNS, направляя весь DNS трафик через Тор прокси. Требуется перезагрузка. +plugin.globalproxy.FWD_DNS_ADDR=Адрес сервера DNS Прокси +plugin.globalproxy.FWD_DNS_PORT=Порт сервера DNS Прокси # plugin reconnect plugin.reconnectplugin.CONNECTION_FAILED_MSG=Не удалось соединение для следующего аккаунта:\nИмя пользователя: {0}, Имя сервера: {1}.\nПожалуйста, проверьте ваше сетевое подключение или свяжитесь с администратором. @@ -1531,18 +1649,21 @@ plugin.reconnectplugin.NETWORK_DOWN=Подключение к сети прер plugin.chatconfig.TITLE=Чат plugin.chatconfig.replacement.TITLE=Фото/Видео: plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Включить поддержку смайликов -plugin.chatconfig.replacement.REPLACEMENT_TITLE=Включить предпросмотр для фото и видео +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Замещение Изображения/Видео plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Включить +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL=Отключено (показать ссылку для предварительного просмотра) +plugin.chatconfig.replacement.DISABLE_REPLACEMENT=Отключить +plugin.chatconfig.replacement.CONFIGURE_REPLACEMENT=Изменить настройки замещения Изображения/Видео plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Источники: plugin.chatconfig.spellcheck.TITLE=Проверка правописания #provisioning plugin -plugin.provisioning.PROVISIONING=Автонастройка -plugin.provisioning.ENABLE_DISABLE=Автоматическое обнаружение адреса автонастройки +plugin.provisioning.PROVISIONING=Резервирование +plugin.provisioning.ENABLE_DISABLE=Включить резервирование plugin.provisioning.AUTO=Автоматическое обнаружение адреса автонастройки plugin.provisioning.DHCP=DHCP plugin.provisioning.DNS=DNS -plugin.provisioning.BONJOUR=Bonjour +plugin.provisioning.BONJOUR=Приветсвие plugin.provisioning.MANUAL=Вручную задать адрес URI автонастройки plugin.provisioning.URI=URI plugin.provisioning.RESTART_WARNING=Изменения вступят в силу только при следующем запуске {0}! @@ -1554,7 +1675,7 @@ plugin.provisioning.CREDENTIALS=Учетная запись для автона plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Вы действительно хотите сбросить пароль для автонастройки? plugin.provisioning.PROV_FAILED=Автонастройка не удалась plugin.provisioning.PROV_FAILED_MSG=Автонастройка не удалась. {0}!
    Пожалуйста, попробуйте позже или свяжитесь с администратором. -plugin.provisioning.FORGET_PASSWORD=Сброс сохраненных паролей +plugin.provisioning.FORGET_PASSWORD=Забыть пароль # packet logging service plugin.loggingutils.PACKET_LOGGING_CONFIG=Протоколирование @@ -1564,7 +1685,7 @@ plugin.loggingutils.PACKET_LOGGING_RTP_DESCRIPTION=(записывает 1 из plugin.loggingutils.PACKET_LOGGING_ICE4J=ice4j.org plugin.loggingutils.PACKET_LOGGING_DESCRIPTION=Записывать отладочные сведения различных протоколов в папку журналов
    в формате pcap (tcpdump/wireshark). plugin.loggingutils.PACKET_LOGGING_FILE_COUNT=Количество файлов журнала -plugin.loggingutils.PACKET_LOGGING_FILE_SIZE=Максимальный размер файла (в Кб) +plugin.loggingutils.PACKET_LOGGING_FILE_SIZE=Максимальный размер файла (в КБ) plugin.loggingutils.ARCHIVE_BUTTON=Архивировать журналы plugin.loggingutils.UPLOAD_LOGS_BUTTON=Загрузить журналы plugin.loggingutils.UPLOAD_BUTTON=Загрузить @@ -1582,9 +1703,9 @@ plugin.dnsconfig.chkBackupDnsEnabled.text=Задействовать допол plugin.dnsconfig.lblBackupResolver.text=Имя DNS-сервера plugin.dnsconfig.lblBackupResolverFallbackIP.text=IP-адрес DNS-сервера plugin.dnsconfig.lblBackupPort.text=Порт -plugin.dnsconfig.lblRedemption.text=Возврат на первичный DNS +plugin.dnsconfig.lblRedemption.text=Вернуться к первичному ДНС plugin.dnsconfig.lblRedemption.description=Число откликов первичного DNS-сервера перед тем, как задействовать его опять вместо резервного -plugin.dnsconfig.lblPatience.text=Использовать дополнительный DNS после +plugin.dnsconfig.lblPatience.text=Запускать дополнительный ДНС после plugin.dnsconfig.lblPatience.description=Количество миллисекунд ожидания ответа от первичного DNS, прежде чем использовать резервный plugin.dnsconfig.dnssec.chkEnabled=Задействовать DNSSEC plugin.dnsconfig.dnssec.lblDefault=Режим по умолчанию @@ -1652,15 +1773,20 @@ plugin.certconfig.FILE_TYPE_DESCRIPTION=Хранилище сертификат plugin.certconfig.ALIAS_LOAD_EXCEPTION=Не удается получить псевдонимы из хранилища ключей ({0}). plugin.certconfig.INVALID_KEYSTORE_TYPE=Выбранный тип хранилища ключей неверен ({0}). plugin.certconfig.BROWSE_KEYSTORE=Открыть хранилище ключей +plugin.certconfig.REVOCATION_TITLE=Настройки отзыва сертификатов +plugin.certconfig.REVOCATION_CHECK_ENABLED=Проверка СОС (Списка Отозванных Сертификатов) включена +plugin.certconfig.REVOCATION_OCSP_ENABLED=Проверка статуса сертификата на предмет отозванности включена # Phone number contact source plugin plugin.phonenumbercontactsource.DISPLAY_NAME=Телефонные номера # properties editor plugin.propertieseditor.TITLE=Редактор свойств -plugin.propertieseditor.NEW_PROPERTY_TITLE=Добавить свойство +plugin.propertieseditor.NEW_PROPERTY_TITLE=Добавить новое свойство plugin.propertieseditor.CHECK_BOX=Показать это предупреждение в следующий раз -plugin.propertieseditor.IM_AWARE=Я осознаю риск +plugin.propertieseditor.DESCRIPTION=Следующая кнопка позволяет изменять свойства конфигурации Jitsi. Изменение этих продвинутых настроек может пагубно влиять на стабильность, безопасность и производительность данного приложения. Вам следует продолжить только если вы уверены в том, что вы делаете. +plugin.propertieseditor.IM_AWARE=Я отдаю себе отчет о рисках +plugin.propertieseditor.NEED_RESTART=На заметку: некоторые свойства могут потребовать перезапуска перед тем, как новые настройки вступят в силу. #Thunderbird address book plugin plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird -- cgit v1.1 From cd6b77bb0e342ca4a8593f9272400ecda14a7b92 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 31 Mar 2016 12:04:59 -0500 Subject: Modifies ColibriBuilder to be able to send RTP, SSRC and transport updates in a single request --- .../jabber/extensions/colibri/ColibriBuilder.java | 561 +++++++++++++++------ .../extensions/colibri/ColibriConferenceIQ.java | 19 + .../jingle/IceUdpTransportPacketExtension.java | 21 + 3 files changed, 433 insertions(+), 168 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java index 547ebe8..502c362 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java @@ -37,9 +37,9 @@ import java.util.*; * Add one or multiple requests of the same type by calling * {@link #addAllocateChannelsReq(boolean, String, boolean, java.util.List)}} * or {@link #addExpireChannelsReq(ColibriConferenceIQ)} - * or {@link #addTransportUpdateReq(boolean, java.util.Map, ColibriConferenceIQ)} - * or {@link #addBundleTransportUpdateReq( - * boolean, IceUdpTransportPacketExtension, ColibriConferenceIQ)}. + * or {@link #addRtpDescription(Map, ColibriConferenceIQ)} + * and {@link #addSSSRCGroupsInfo(Map, ColibriConferenceIQ)} + * and {@link #addSSSRCInfo(Map, ColibriConferenceIQ)}. * *
  • * Compile the request by calling {@link #getRequest(String)}. Then send it to @@ -161,18 +161,26 @@ public class ColibriBuilder * @param contents the list of {@link ContentPacketExtension} describing * channels media. * - * @return this instance fo calls chaining purpose. + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. */ - public ColibriBuilder addAllocateChannelsReq( - boolean useBundle, - String endpointName, - boolean peerIsInitiator, + public boolean addAllocateChannelsReq( + boolean useBundle, + String endpointName, + boolean peerIsInitiator, List contents) { + Objects.requireNonNull(endpointName, "endpointName"); + Objects.requireNonNull(contents, "contents"); + assertRequestType(RequestType.ALLOCATE_CHANNELS); request.setType(IQ.Type.GET); + boolean hasAnyChanges = false; + for (ContentPacketExtension cpe : contents) { MediaType mediaType = JingleUtils.getMediaType(cpe); @@ -193,7 +201,7 @@ public class ColibriBuilder remoteChannelRequest.setChannelBundleId(endpointName); } - if (mediaType != MediaType.DATA) + if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel) { RtpDescriptionPacketExtension rdpe = cpe.getFirstChildOfType( @@ -221,13 +229,17 @@ public class ColibriBuilder copyTransportOnChannel(cpe, remoteChannelRequest); } - if (mediaType != MediaType.DATA) + if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel) { + hasAnyChanges = true; + contentRequest.addChannel( (ColibriConferenceIQ.Channel) remoteChannelRequest); } else { + hasAnyChanges = true; + contentRequest.addSctpConnection( (ColibriConferenceIQ.SctpConnection) remoteChannelRequest); } @@ -246,6 +258,8 @@ public class ColibriBuilder IceUdpTransportPacketExtension.class); if (transport != null) { + hasAnyChanges = true; + bundle.setTransport( IceUdpTransportPacketExtension .cloneTransportAndCandidates(transport, true)); @@ -254,106 +268,38 @@ public class ColibriBuilder request.addChannelBundle(bundle); } - return this; + return hasAnyChanges; } /** - * Adds next ICE transport update request to - * {@link RequestType#TRANSPORT_UPDATE} query currently being built. - * - * @param initiator the value that will be set in 'initiator' - * attribute({@link ColibriConferenceIQ.Channel#initiator}). - * @param map the map of content name to transport extensions. Maps - * transport to media types. - * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about - * Colibri channels to be updated. - * - * @return this instance fo calls chaining purpose. - */ - public ColibriBuilder addTransportUpdateReq( - boolean initiator, - Map map, - ColibriConferenceIQ localChannelsInfo) - { - if (conferenceState == null - || StringUtils.isNullOrEmpty(conferenceState.getID())) - { - // We are not initialized yet - return null; - } - - assertRequestType(RequestType.TRANSPORT_UPDATE); - - request.setType(IQ.Type.SET); - - for (Map.Entry e - : map.entrySet()) - { - String contentName = e.getKey(); - ColibriConferenceIQ.ChannelCommon channel - = getColibriChannel(localChannelsInfo, contentName); - - if (channel != null) - { - IceUdpTransportPacketExtension transport - = IceUdpTransportPacketExtension - .cloneTransportAndCandidates(e.getValue(), true); - - ColibriConferenceIQ.ChannelCommon channelRequest - = channel instanceof ColibriConferenceIQ.Channel - ? new ColibriConferenceIQ.Channel() - : new ColibriConferenceIQ.SctpConnection(); - - channelRequest.setID(channel.getID()); - channelRequest.setEndpoint(channel.getEndpoint()); - channelRequest.setInitiator(initiator); - channelRequest.setTransport(transport); - - if (channelRequest instanceof ColibriConferenceIQ.Channel) - { - request.getOrCreateContent(contentName) - .addChannel( - (ColibriConferenceIQ.Channel) channelRequest); - } - else - { - request.getOrCreateContent(contentName) - .addSctpConnection( - (ColibriConferenceIQ.SctpConnection) channelRequest); - } - } - } - return this; - } - - /** - * Adds next request to {@link RequestType#BUNDLE_TRANSPORT_UPDATE} query. - * @param initiator the value that will be set in 'initiator' - * attribute({@link ColibriConferenceIQ.Channel#initiator}). + * Adds next request to {@link RequestType#CHANNEL_INFO_UPDATE} query. * @param localChannelsInfo the {@link ColibriConferenceIQ} instance that * describes the channel for which bundle transport will be updated. * It should contain the description of only one "channel bundle". * If it contains more than one then the first one will be used. - * @return this instance for calls chaining purpose. + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. * @throws IllegalArgumentException if localChannelsInfo does not * describe any channel bundles. */ - public ColibriBuilder addBundleTransportUpdateReq( - boolean initiator, - IceUdpTransportPacketExtension transport, - ColibriConferenceIQ localChannelsInfo) + public boolean addBundleTransportUpdateReq( + IceUdpTransportPacketExtension transport, + ColibriConferenceIQ localChannelsInfo) throws IllegalArgumentException { - // FIXME:'initiator' not used on bundle transport update ? + Objects.requireNonNull(transport, "transport"); + Objects.requireNonNull(localChannelsInfo, "localChannelsInfo"); if (conferenceState == null || StringUtils.isNullOrEmpty(conferenceState.getID())) { // We are not initialized yet - return null; + return false; } - assertRequestType(RequestType.BUNDLE_TRANSPORT_UPDATE); + assertRequestType(RequestType.CHANNEL_INFO_UPDATE); request.setType(IQ.Type.SET); @@ -371,7 +317,7 @@ public class ColibriBuilder else { throw new IllegalArgumentException( - "Expected ChannelBundle as not found"); + "Expected ChannelBundle as not found"); } ColibriConferenceIQ.ChannelBundle bundleUpdate @@ -387,7 +333,7 @@ public class ColibriBuilder request.addChannelBundle(bundleUpdate); - return this; + return true; } /** @@ -395,15 +341,20 @@ public class ColibriBuilder * {@link RequestType#EXPIRE_CHANNELS} query currently being built. * @param channelInfo the {@link ColibriConferenceIQ} instance that contains * info about the channels to be expired. - * @return this instance for the purpose of calls chaining. + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. */ - public ColibriBuilder addExpireChannelsReq(ColibriConferenceIQ channelInfo) + public boolean addExpireChannelsReq(ColibriConferenceIQ channelInfo) { + Objects.requireNonNull(channelInfo, "channelInfo"); + // Formulate the ColibriConferenceIQ request which is to be sent. if (conferenceState == null || StringUtils.isNullOrEmpty(conferenceState.getID())) { - return null; + return false; } assertRequestType(RequestType.EXPIRE_CHANNELS); @@ -411,7 +362,7 @@ public class ColibriBuilder request.setType(IQ.Type.SET); for (ColibriConferenceIQ.Content expiredContent - : channelInfo.getContents()) + : channelInfo.getContents()) { ColibriConferenceIQ.Content stateContent = conferenceState.getContent(expiredContent.getName()); @@ -420,7 +371,7 @@ public class ColibriBuilder { ColibriConferenceIQ.Content requestContent = request.getOrCreateContent( - stateContent.getName()); + stateContent.getName()); for (ColibriConferenceIQ.Channel expiredChannel : expiredContent.getChannels()) @@ -490,7 +441,7 @@ public class ColibriBuilder */ /*if (stateContent.getChannelCount() == 1) { - stateChannel = stateContent.getChannel(0); + stateChannel = stateContent.getRtpChannel(0); ColibriConferenceIQ.Channel channelRequest = new ColibriConferenceIQ.Channel(); @@ -537,7 +488,293 @@ public class ColibriBuilder } } - return this; + return hasAnyChannelsToExpire; + } + + /** + * Adds next payload type information update request to + * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built. + * + * @param map the map of content name to RTP description packet extension. + * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about + * Colibri channels to be updated. + * + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. + */ + public boolean addRtpDescription( + Map map, + ColibriConferenceIQ localChannelsInfo) + { + Objects.requireNonNull(map, "map"); + Objects.requireNonNull(localChannelsInfo, "localChannelsInfo"); + + if (conferenceState == null + || StringUtils.isNullOrEmpty(conferenceState.getID())) + { + // We are not initialized yet + return false; + } + + assertRequestType(RequestType.CHANNEL_INFO_UPDATE); + + request.setType(IQ.Type.SET); + + boolean anyUpdates = false; + + for (Map.Entry e + : map.entrySet()) + { + String contentName = e.getKey(); + ColibriConferenceIQ.ChannelCommon channel + = getColibriChannel(localChannelsInfo, contentName); + + if (channel != null + && channel instanceof ColibriConferenceIQ.Channel) + { + RtpDescriptionPacketExtension rtpPE = e.getValue(); + if (rtpPE == null) + { + continue; + } + + List pts = rtpPE.getPayloadTypes(); + if (pts == null || pts.isEmpty()) + { + continue; + } + + anyUpdates = true; + + ColibriConferenceIQ.Channel channelRequest + = request.getOrCreateContent(contentName) + .getChannel(channel.getID()); + if (channelRequest == null) + { + channelRequest = new ColibriConferenceIQ.Channel(); + channelRequest.setID(channel.getID()); + } + + for (PayloadTypePacketExtension ptPE : pts) + { + channelRequest.addPayloadType(ptPE); + } + } + } + + return anyUpdates; + } + + /** + * Adds next SSRC information update request to + * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built. + * + * @param ssrcMap the map of content name to the list of + * SourcePacketExtension. + * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about + * Colibri channels to be updated. + * + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. + */ + public boolean addSSSRCInfo( + Map> ssrcMap, + ColibriConferenceIQ localChannelsInfo) + { + Objects.requireNonNull(ssrcMap, "ssrcMap"); + Objects.requireNonNull(localChannelsInfo, "localChannelsInfo"); + + if (conferenceState == null + || StringUtils.isNullOrEmpty(conferenceState.getID())) + { + // We are not initialized yet + return false; + } + + assertRequestType(RequestType.CHANNEL_INFO_UPDATE); + + request.setType(IQ.Type.SET); + + boolean anyUpdates = false; + + // Go over SSRCs + for (String contentName : ssrcMap.keySet()) + { + // Get channel from local channel info + ColibriConferenceIQ.ChannelCommon rtpChanel + = getRtpChannel(localChannelsInfo, contentName); + if (rtpChanel == null) + { + // There's no channel for this content name in localChannelsInfo + continue; + } + + anyUpdates = true; + + // Ok we have channel for this content, let's add SSRCs + ColibriConferenceIQ.Channel reqChannel + = (ColibriConferenceIQ.Channel) getRequestChannel( + request.getOrCreateContent(contentName), rtpChanel); + + for (SourcePacketExtension ssrc : ssrcMap.get(contentName)) + { + reqChannel.addSource(ssrc.copy()); + } + + if (reqChannel.getSources() == null + || reqChannel.getSources().isEmpty()) + { + // Put an empty source to remove all sources + SourcePacketExtension emptySource = new SourcePacketExtension(); + emptySource.setSSRC(-1L); + reqChannel.addSource(emptySource); + } + } + + return anyUpdates; + } + + /** + * Adds next SSRC group information update request to + * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built. + * + * @param ssrcGroupMap the map of content name to the list of + * SourceGroupPacketExtension. + * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about + * Colibri channels to be updated. + * + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. + */ + public boolean addSSSRCGroupsInfo( + Map> ssrcGroupMap, + ColibriConferenceIQ localChannelsInfo) + { + Objects.requireNonNull(ssrcGroupMap, "ssrcGroupMap"); + Objects.requireNonNull(localChannelsInfo, "localChannelsInfo"); + + if (conferenceState == null + || StringUtils.isNullOrEmpty(conferenceState.getID())) + { + // We are not initialized yet + return false; + } + + assertRequestType(RequestType.CHANNEL_INFO_UPDATE); + + request.setType(IQ.Type.SET); + + boolean anyUpdates = false; + + // Go over SSRC groups + for (String contentName : ssrcGroupMap.keySet()) + { + // Get channel from local channel info + ColibriConferenceIQ.Channel rtpChannel + = getRtpChannel(localChannelsInfo, contentName); + if (rtpChannel == null) + { + // There's no channel for this content name in localChannelsInfo + continue; + } + + List groups + = ssrcGroupMap.get(contentName); + + // Ok we have channel for this content, let's add SSRCs + ColibriConferenceIQ.Channel reqChannel + = (ColibriConferenceIQ.Channel) getRequestChannel( + request.getOrCreateContent(contentName), rtpChannel); + + if (groups.isEmpty() && "video".equalsIgnoreCase(contentName)) + { + anyUpdates = true; + + // Put empty source group to turn off simulcast layers + reqChannel.addSourceGroup( + SourceGroupPacketExtension.createSimulcastGroup()); + } + + for (SourceGroupPacketExtension group : groups) + { + anyUpdates = true; + + reqChannel.addSourceGroup(group); + } + } + + return anyUpdates; + } + + /** + * Adds next ICE transport update request to + * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built. + * + * @param map the map of content name to transport extensions. Maps + * transport to media types. + * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about + * Colibri channels to be updated. + * + * @return true if the request yields any changes in Colibri + * channels state on the bridge or false otherwise. + * In general when false is returned for all + * combined requests it makes no sense to send it. + */ + public boolean addTransportUpdateReq( + Map map, + ColibriConferenceIQ localChannelsInfo) + { + Objects.requireNonNull(map, "map"); + Objects.requireNonNull(localChannelsInfo, "localChannelsInfo"); + + if (conferenceState == null + || StringUtils.isNullOrEmpty(conferenceState.getID())) + { + // We are not initialized yet + return false; + } + + boolean hasAnyChanges = false; + + assertRequestType(RequestType.CHANNEL_INFO_UPDATE); + + request.setType(IQ.Type.SET); + + for (Map.Entry e + : map.entrySet()) + { + String contentName = e.getKey(); + ColibriConferenceIQ.ChannelCommon channel + = getColibriChannel(localChannelsInfo, contentName); + + if (channel != null) + { + IceUdpTransportPacketExtension transport + = IceUdpTransportPacketExtension + .cloneTransportAndCandidates(e.getValue(), true); + + ColibriConferenceIQ.ChannelCommon channelRequest + = channel instanceof ColibriConferenceIQ.Channel + ? new ColibriConferenceIQ.Channel() + : new ColibriConferenceIQ.SctpConnection(); + + channelRequest.setID(channel.getID()); + channelRequest.setEndpoint(channel.getEndpoint()); + channelRequest.setTransport(transport); + + request.getOrCreateContent(contentName) + .addChannelCommon(channelRequest); + + hasAnyChanges = true; + } + } + return hasAnyChanges; } /** @@ -583,10 +820,12 @@ public class ColibriBuilder request.setTo(videobridge); - if (requestType == RequestType.EXPIRE_CHANNELS - && !hasAnyChannelsToExpire) + if (requestType == RequestType.EXPIRE_CHANNELS) { - return null; + if (!hasAnyChannelsToExpire) + return null; + + hasAnyChannelsToExpire = false; } return request; @@ -732,69 +971,64 @@ public class ColibriBuilder } /** - * Adds next payload type information update request to - * {@link RequestType#RTP_DESCRIPTION_UPDATE} query currently being built. + * Creates a new instance of localChannelInfo and initializes only + * the fields required to identify particular Colibri channel on the bridge. + * This instance is meant to be used in Colibri + * {@link RequestType#CHANNEL_INFO_UPDATE} requests. This instance is also + * added to given requestContent which used to construct current + * request. * - * @param map the map of content name to RTP description packet extension. - * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about - * Colibri channels to be updated. + * @param requestContent Content of Colibri update request to which + * new instance wil be automatically added after has been created. + * @param localChannelInfo the original channel for which "update request" + * equivalent is to be created with this call. * - * @return this instance for calls chaining purpose. + * @return new instance of localChannelInfo and initialized with + * only those fields required to identify particular Colibri channel on + * the bridge. */ - public ColibriBuilder addRtpDescription( - Map map, - ColibriConferenceIQ localChannelsInfo) { - - if (conferenceState == null - || StringUtils.isNullOrEmpty(conferenceState.getID())) - { - // We are not initialized yet - return null; - } - - assertRequestType(RequestType.RTP_DESCRIPTION_UPDATE); - - request.setType(IQ.Type.SET); - - for (Map.Entry e - : map.entrySet()) + private ColibriConferenceIQ.ChannelCommon getRequestChannel( + ColibriConferenceIQ.Content requestContent, + ColibriConferenceIQ.ChannelCommon localChannelInfo) + { + ColibriConferenceIQ.ChannelCommon reqChannel + = requestContent.getChannel(localChannelInfo.getID()); + if (reqChannel == null) { - String contentName = e.getKey(); - ColibriConferenceIQ.ChannelCommon channel - = getColibriChannel(localChannelsInfo, contentName); - - if (channel != null - && channel instanceof ColibriConferenceIQ.Channel) + if (localChannelInfo instanceof ColibriConferenceIQ.Channel) { - RtpDescriptionPacketExtension rtpPE = e.getValue(); - if (rtpPE == null) - { - continue; - } - - List pts = rtpPE.getPayloadTypes(); - if (pts == null || pts.isEmpty()) - { - continue; - } - - ColibriConferenceIQ.Channel channelRequest - = new ColibriConferenceIQ.Channel(); + reqChannel = new ColibriConferenceIQ.Channel(); + } + else if ( + localChannelInfo instanceof ColibriConferenceIQ.SctpConnection) + { + reqChannel = new ColibriConferenceIQ.SctpConnection(); + } + else + { + throw new RuntimeException( + "Unsupported ChannelCommon class: " + + localChannelInfo.getClass()); + } - channelRequest.setID(channel.getID()); + reqChannel.setID(localChannelInfo.getID()); - for (PayloadTypePacketExtension ptPE : rtpPE.getPayloadTypes()) - { - channelRequest.addPayloadType(ptPE); - } + requestContent.addChannelCommon(reqChannel); + } + return reqChannel; + } - request.getOrCreateContent(contentName) - .addChannel(channelRequest); - } + private ColibriConferenceIQ.Channel getRtpChannel( + ColibriConferenceIQ localChannelsInfo, + String contentName) + { + ColibriConferenceIQ.Content content + = localChannelsInfo.getContent(contentName); - } + if (content == null) + return null; - return this; + return content.getChannelCount() > 0 ? content.getChannel(0) : null; } /** @@ -808,19 +1042,10 @@ public class ColibriBuilder ALLOCATE_CHANNELS, /** - * Updates transport information for channels that use RTP bundle. - */ - BUNDLE_TRANSPORT_UPDATE, - - /** - * Updates channel transport information(ICE transport candidates). - */ - TRANSPORT_UPDATE, - - /** - * Updates the RTP description of a channel (payload types). + * An update request which is meant to modify some values of existing + * Colibri channels on the bridge. */ - RTP_DESCRIPTION_UPDATE, + CHANNEL_INFO_UPDATE, /** * Expires specified Colibri channels. diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java index 48e344b..3fefc9f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java @@ -1925,6 +1925,25 @@ public class ColibriConferenceIQ } /** + * Adds ChannelCommon to this Content. + * @param channelCommon {@link ChannelCommon} instance to be added to + * this content. + * @return true if given channelCommon has been + * actually added to this Content instance. + */ + public boolean addChannelCommon(ChannelCommon channelCommon) + { + if (channelCommon instanceof Channel) + { + return addChannel((Channel) channelCommon); + } + else + { + return addSctpConnection((SctpConnection) channelCommon); + } + } + + /** * Adds a specific SctpConnection to the list of * SctpConnections included into this Content. * diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java index 1112c8c..173701f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java @@ -191,6 +191,27 @@ public class IceUdpTransportPacketExtension } /** + * Removes given PacketExtension from the list of child packet + * extensions. CandidatePacketExtension are not taken into account + * in this method and {@link #removeCandidate(CandidatePacketExtension)} + * should be used instead. + * + * @param childExtension PacketExtension instance to be removed + * from child packet extensions list. + * + * @return true if given childExtension has been in the + * list and was removed or false otherwise. + */ + public boolean removeChildExtension(PacketExtension childExtension) + { + List childExtensions + = super.getChildExtensions(); + + return childExtensions != null + && childExtensions.remove(childExtension); + } + + /** * Returns the list of {@link CandidatePacketExtension}s currently * registered with this transport. * -- cgit v1.1 From db8970fc0135c018326baea5fd7218545eaeb688 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Tue, 5 Apr 2016 18:40:03 -0500 Subject: List a jitsi-specific version of jitsi/libjitsi We made an effort to support reproducible builds. That made us specify explicit jitsi/libjitsi and jitsi/jitsi-universe (artifact) versions. The jitsi Maven project is the only one which did not specify an explicit jitsi/libjitsi version. However, jitsi/jitsi-videobridge depends on jitsi/jitsi and, consequently, sees a mixture of jitsi/libjitsi and jitsi/jitsi-universe versions during its build. --- m2/pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/m2/pom.xml b/m2/pom.xml index f5dc422..69f77fc 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -44,6 +44,16 @@ jitsi-version + + + + ${project.groupId} + libjitsi + 1.0-20160202.214638-87 + + + + ../../src -- cgit v1.1 From 56fee8b324f4390f51ed9558986119d83ed3f7b4 Mon Sep 17 00:00:00 2001 From: Lyubomir Marinov Date: Tue, 5 Apr 2016 18:56:06 -0500 Subject: Update jitsi/jitsi to jitsi/jitsi-universe@205c971 The project jitsi/jitsi started listing an explicit org.jitsi.libjitsi artifact version in order to comply with our policy which was put into effect in our other projects. Now jitsi/jitsi-universe does not have to specify any default artifact version for org.jitsi.libjitsi. --- m2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m2/pom.xml b/m2/pom.xml index 69f77fc..65ad9b3 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -7,7 +7,7 @@ org.jitsi jitsi-universe - 1.0-20160202.203332-11 + 1.0-20160405.235512-16 jitsi -- cgit v1.1 From 0b110ade7b9f47c860f6b0e06ae7613425454801 Mon Sep 17 00:00:00 2001 From: champtar Date: Wed, 6 Apr 2016 11:02:34 +0200 Subject: use bcprov-jdk15on jitsi-universe version Signed-off-by: Etienne CHAMPETIER --- m2/jitsi-certificate/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/m2/jitsi-certificate/pom.xml b/m2/jitsi-certificate/pom.xml index a14f1ed..a486b92 100644 --- a/m2/jitsi-certificate/pom.xml +++ b/m2/jitsi-certificate/pom.xml @@ -20,11 +20,6 @@ org.bouncycastle bcprov-jdk15on - - 1.51-jitsi-1 org.apache.httpcomponents -- cgit v1.1 From 531547f258d2d2b0e019ac8d5b21d168ce684e7a Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 6 Apr 2016 16:33:54 -0500 Subject: Fix issue with RTP description updates in Colibri --- .../impl/protocol/jabber/extensions/colibri/ColibriBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java index 502c362..4c703a9 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java @@ -549,8 +549,9 @@ public class ColibriBuilder anyUpdates = true; ColibriConferenceIQ.Channel channelRequest - = request.getOrCreateContent(contentName) - .getChannel(channel.getID()); + = (ColibriConferenceIQ.Channel) getRequestChannel( + request.getOrCreateContent(contentName), + channel); if (channelRequest == null) { channelRequest = new ColibriConferenceIQ.Channel(); -- cgit v1.1 From 292f506964f3f5a9af08c0a8f09ddf12c9306558 Mon Sep 17 00:00:00 2001 From: Matteo Campana Date: Mon, 11 Apr 2016 10:43:26 +0200 Subject: Parse ptime parameter into media format. --- .../communicator/impl/protocol/jabber/jinglesdp/JingleUtils.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/jinglesdp/JingleUtils.java b/src/net/java/sip/communicator/impl/protocol/jabber/jinglesdp/JingleUtils.java index 93cdead..8094f68 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/jinglesdp/JingleUtils.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/jinglesdp/JingleUtils.java @@ -179,12 +179,17 @@ public class JingleUtils else paramsMap.put(paramName, param.getValue()); } - - // video-related attributes in payload-type element + for(String attr : payloadType.getAttributeNames()) { + //video-related attributes in payload-type element if(attr.equals("width") || attr.equals("height")) paramsMap.put(attr, payloadType.getAttributeAsString(attr)); + + //update ptime with the actual value from the payload + if (attr.equals(PayloadTypePacketExtension.PTIME_ATTR_NAME)) + advancedMap.put(PayloadTypePacketExtension.PTIME_ATTR_NAME, + Integer.toString(payloadType.getPtime())); } //now create the format. -- cgit v1.1 From e0e0c7f9afd6be5828bfe38f5b3efa0892847fcd Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 11 Apr 2016 22:29:36 +0200 Subject: Simplify build Some of our dependencies are already OSGi bundles. Copy them directly in one target. At a later time, this will allow us to resolve them with centrally from Maven instead of copying. --- build.xml | 112 ++++++++++++++++++-------------------------------------------- 1 file changed, 33 insertions(+), 79 deletions(-) diff --git a/build.xml b/build.xml index 5cca731..2369c36 100644 --- a/build.xml +++ b/build.xml @@ -1054,13 +1054,13 @@ bundle-icq-slick,bundle-mock,bundle-smacklib,bundle-jmdnslib, bundle-jabber,bundle-jabber-slick,bundle-swing-ui,bundle-ui-service, bundle-jnalib,bundle-phonenumbers, - bundle-irc-api,bundle-irc,bundle-irc-commands,bundle-plugin-ircaccregwizz, + bundle-irc,bundle-irc-commands,bundle-plugin-ircaccregwizz, bundle-yahoo,bundle-yahoo-slick, bundle-contactlist,meta-contactlist,meta-contactlist-slick, bundle-plugin-icqaccregwizz,bundle-plugin-jabberaccregwizz, bundle-plugin-sipaccregwizz, bundle-plugin-yahooaccregwizz,bundle-plugin-aimaccregwizz, - bundle-commons-codec,bundle-commons-lang,bundle-httputil,bundle-plugin-spellcheck, + bundle-httputil,bundle-plugin-spellcheck, bundle-version-impl,bundle-shutdown-timeout,bundle-windows-clean-shutdown, bundle-growlnotification,bundle-swingnotification,bundle-galagonotification, bundle-sparkle, bundle-plugin-branding, @@ -1076,10 +1076,10 @@ bundle-jfontchooserlib,bundle-update,bundle-plugin-update, bundle-plugin-simpleaccreg,bundle-plugin-generalconfig, bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service, - bundle-argdelegation,bundle-zrtp4j,bundle-sdes4j,bundle-json, + bundle-argdelegation,bundle-zrtp4j,bundle-json, bundle-filehistory,bundle-metahistory,bundle-metahistory-slick, bundle-plugin-ippiaccregwizz, - bundle-bouncycastle,bundle-plugin-otr,bundle-plugin-iptelaccregwizz, + bundle-plugin-otr,bundle-plugin-iptelaccregwizz, bundle-contactsource,bundle-plugin-reconnect,bundle-plugin-securityconfig, bundle-plugin-advancedconfig, bundle-credentialsstorage,bundle-credentialsstorage-slick, @@ -1093,14 +1093,34 @@ bundle-provisioning,bundle-addrbook,bundle-plugin-ldap, bundle-thunderbird, bundle-plugin-contactsourceconfig,bundle-plugin-certconfig, - bundle-globalshortcut,bundle-plugin-msofficecomm,bundle-libjitsi, + bundle-globalshortcut,bundle-plugin-msofficecomm, bundle-customcontactactions, bundle-phonenumbercontactsource, bundle-demuxcontactsource, bundle-muc, bundle-desktoputil,bundle-globaldisplaydetails, - bundle-usersearch, + bundle-usersearch, bundle-plugin-propertieseditor,bundle-plugin-accountinfo, bundle-plugin-connectioninfo, - bundle-guava,bundle-hsql,bundle-slf4j"/> + bundle-bundles"/> + + + + + + + + + + + + + + + + + + + + @@ -1308,18 +1328,9 @@ - - - - - - - - - + - - - - - - - - - - - - - - - - + - + @@ -2083,7 +2075,7 @@ javax.swing.event, javax.swing.border"/> - + @@ -2102,17 +2094,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - - - - - - - - - @@ -2144,11 +2113,6 @@ javax.swing.event, javax.swing.border"/> - - - @@ -2172,7 +2136,7 @@ javax.swing.event, javax.swing.border"/> - + @@ -2482,11 +2446,6 @@ org.bouncycastle.util"/> - - - - - - - - - - - @@ -2536,6 +2489,7 @@ org.bouncycastle.util"/> + Date: Mon, 11 Apr 2016 22:45:14 +0200 Subject: Update dependencies * bccontrib: 1.0 is released on Central * jmork: 1.0.5 is released on Central * bcprov/bcpkix: 1.54 is a prerequisite for newer libjitsi --- .classpath | 6 +++--- build.xml | 8 ++++---- lib/installer-exclude/bccontrib-1.0-SNAPSHOT.jar | Bin 40669 -> 0 bytes lib/installer-exclude/bccontrib-1.0.jar | Bin 0 -> 41570 bytes lib/installer-exclude/bcpkix-jdk15on-1.54.jar | Bin 0 -> 673715 bytes lib/installer-exclude/bcpkix-jdk15on-151.jar | Bin 605519 -> 0 bytes lib/installer-exclude/bcprov-jdk15on-1.54.jar | Bin 0 -> 3277268 bytes lib/installer-exclude/bcprov-jdk15on-151.jar | Bin 2842667 -> 0 bytes lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar | Bin 44218 -> 0 bytes lib/installer-exclude/jmork-1.0.5.jar | Bin 0 -> 45171 bytes 10 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 lib/installer-exclude/bccontrib-1.0-SNAPSHOT.jar create mode 100644 lib/installer-exclude/bccontrib-1.0.jar create mode 100644 lib/installer-exclude/bcpkix-jdk15on-1.54.jar delete mode 100755 lib/installer-exclude/bcpkix-jdk15on-151.jar create mode 100644 lib/installer-exclude/bcprov-jdk15on-1.54.jar delete mode 100755 lib/installer-exclude/bcprov-jdk15on-151.jar delete mode 100644 lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar create mode 100644 lib/installer-exclude/jmork-1.0.5.jar diff --git a/.classpath b/.classpath index 8a39b4d..010edcc 100755 --- a/.classpath +++ b/.classpath @@ -75,10 +75,10 @@ - - + + - + diff --git a/build.xml b/build.xml index 2369c36..c31cbb3 100644 --- a/build.xml +++ b/build.xml @@ -1107,7 +1107,6 @@ - @@ -1118,8 +1117,10 @@ - - + + + + @@ -2775,7 +2776,6 @@ org.bouncycastle.util"/> - diff --git a/lib/installer-exclude/bccontrib-1.0-SNAPSHOT.jar b/lib/installer-exclude/bccontrib-1.0-SNAPSHOT.jar deleted file mode 100644 index 719078e..0000000 Binary files a/lib/installer-exclude/bccontrib-1.0-SNAPSHOT.jar and /dev/null differ diff --git a/lib/installer-exclude/bccontrib-1.0.jar b/lib/installer-exclude/bccontrib-1.0.jar new file mode 100644 index 0000000..47a6a89 Binary files /dev/null and b/lib/installer-exclude/bccontrib-1.0.jar differ diff --git a/lib/installer-exclude/bcpkix-jdk15on-1.54.jar b/lib/installer-exclude/bcpkix-jdk15on-1.54.jar new file mode 100644 index 0000000..86f7f0b Binary files /dev/null and b/lib/installer-exclude/bcpkix-jdk15on-1.54.jar differ diff --git a/lib/installer-exclude/bcpkix-jdk15on-151.jar b/lib/installer-exclude/bcpkix-jdk15on-151.jar deleted file mode 100755 index 57e0080..0000000 Binary files a/lib/installer-exclude/bcpkix-jdk15on-151.jar and /dev/null differ diff --git a/lib/installer-exclude/bcprov-jdk15on-1.54.jar b/lib/installer-exclude/bcprov-jdk15on-1.54.jar new file mode 100644 index 0000000..bd95185 Binary files /dev/null and b/lib/installer-exclude/bcprov-jdk15on-1.54.jar differ diff --git a/lib/installer-exclude/bcprov-jdk15on-151.jar b/lib/installer-exclude/bcprov-jdk15on-151.jar deleted file mode 100755 index 4076e11..0000000 Binary files a/lib/installer-exclude/bcprov-jdk15on-151.jar and /dev/null differ diff --git a/lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar b/lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar deleted file mode 100644 index 671c474..0000000 Binary files a/lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar and /dev/null differ diff --git a/lib/installer-exclude/jmork-1.0.5.jar b/lib/installer-exclude/jmork-1.0.5.jar new file mode 100644 index 0000000..f87ee11 Binary files /dev/null and b/lib/installer-exclude/jmork-1.0.5.jar differ -- cgit v1.1 From 3c2285cccee21c9bb4d5618279e0093097295b5b Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 11 Apr 2016 22:52:25 +0200 Subject: Update weupnp and use directly as bundle --- .classpath | 1 - build.xml | 2 +- lib/felix.client.run.properties | 3 ++- lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar | Bin 11516 -> 0 bytes lib/installer-exclude/weupnp-0.1.4.jar | Bin 0 -> 29645 bytes 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar create mode 100644 lib/installer-exclude/weupnp-0.1.4.jar diff --git a/.classpath b/.classpath index 010edcc..707090f 100755 --- a/.classpath +++ b/.classpath @@ -71,7 +71,6 @@ - diff --git a/build.xml b/build.xml index c31cbb3..540d598 100644 --- a/build.xml +++ b/build.xml @@ -1121,6 +1121,7 @@ + @@ -1472,7 +1473,6 @@ javax.swing.event, javax.swing.border"/> - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 649afc8..82ff800 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -42,7 +42,8 @@ felix.auto.start.10= \ reference:file:sc-bundles/bccontrib.jar \ reference:file:sc-bundles/commons-lang.jar \ reference:file:sc-bundles/guava.jar \ - reference:file:sc-bundles/slf4j-api.jar + reference:file:sc-bundles/slf4j-api.jar \ + reference:file:sc-bundles/weupnp.jar # file:lib/bundle/shell.jar \ # file:lib/bundle/servicebinder.jar \ diff --git a/lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar b/lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar deleted file mode 100644 index 5051f8f..0000000 Binary files a/lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar and /dev/null differ diff --git a/lib/installer-exclude/weupnp-0.1.4.jar b/lib/installer-exclude/weupnp-0.1.4.jar new file mode 100644 index 0000000..a03b9e2 Binary files /dev/null and b/lib/installer-exclude/weupnp-0.1.4.jar differ -- cgit v1.1 From cd62892c2706370b23d334ee28e07b2090269090 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 11 Apr 2016 23:36:22 +0200 Subject: Update ice4j and jain-sip dependencies * ice4j: v1.0 * jain-sip-api: move to FLOSS version from Opentelecoms (v1.2) * jain-sdp-api: move to FLOSS version from Opentelecoms (v1.0) * jain-sip-ri: jitsi branch with oss-only components, based on 1.2.279 (tag v1.2.279-jitsi-oss1) * sdp-nist-bridge: v1.1 These libraries are used as released on Maven Central. * Update OSGi manifests Now that jain-sip and ice4j are no longer directly bundled, import the required packages. --- .classpath | 9 +++++---- build.xml | 9 +++++---- lib/felix.client.run.properties | 12 +++++++++++- lib/felix.unit.test.properties | 15 +++++++++++++-- lib/installer-exclude/ice4j-1.0.jar | Bin 0 -> 471913 bytes lib/installer-exclude/ice4j.jar | Bin 427749 -> 0 bytes lib/installer-exclude/jain-sdp.jar | Bin 151866 -> 0 bytes lib/installer-exclude/jain-sip-api.jar | Bin 53813 -> 0 bytes .../jain-sip-ri-ossonly-1.2.279-jitsi-oss1.jar | Bin 0 -> 1029073 bytes lib/installer-exclude/jain-sip-ri.jar | Bin 750829 -> 0 bytes lib/installer-exclude/java-sdp-nist-bridge-1.1.jar | Bin 0 -> 8266 bytes lib/installer-exclude/sdp-api-1.0.jar | Bin 0 -> 16131 bytes lib/installer-exclude/sip-api-1.2-1.2.jar | Bin 0 -> 58898 bytes .../sip/communicator/impl/netaddr/netaddr.manifest.mf | 15 +++++---------- .../impl/protocol/sip/net/SslNetworkLayer.java | 6 ++++++ .../communicator/impl/protocol/sip/sdp/SdpUtils.java | 3 ++- .../impl/protocol/sip/sip.provider.manifest.mf | 18 +++++++++++++++--- .../service/protocol/media/protocol.media.manifest.mf | 1 - 18 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 lib/installer-exclude/ice4j-1.0.jar delete mode 100644 lib/installer-exclude/ice4j.jar delete mode 100644 lib/installer-exclude/jain-sdp.jar delete mode 100644 lib/installer-exclude/jain-sip-api.jar create mode 100644 lib/installer-exclude/jain-sip-ri-ossonly-1.2.279-jitsi-oss1.jar delete mode 100644 lib/installer-exclude/jain-sip-ri.jar create mode 100644 lib/installer-exclude/java-sdp-nist-bridge-1.1.jar create mode 100644 lib/installer-exclude/sdp-api-1.0.jar create mode 100644 lib/installer-exclude/sip-api-1.2-1.2.jar diff --git a/.classpath b/.classpath index 707090f..4ce3dcc 100755 --- a/.classpath +++ b/.classpath @@ -31,14 +31,15 @@ - - + + + + + - - diff --git a/build.xml b/build.xml index 540d598..c078ed9 100644 --- a/build.xml +++ b/build.xml @@ -1122,6 +1122,11 @@ + + + + + @@ -1472,7 +1477,6 @@ javax.swing.event, javax.swing.border"/> prefix="net/java/sip/communicator/service/netaddr" /> - @@ -1512,9 +1516,6 @@ javax.swing.event, javax.swing.border"/> manifest="${src}/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf"> - - - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 82ff800..15e34f2 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -25,7 +25,9 @@ org.osgi.framework.system.packages.extra= \ sun.net.dns; \ sun.security.action; \ sun.security.pkcs11;\ - sun.audio + sun.audio;\ + sun.nio.ch;\ + com.sun.nio.sctp felix.auto.start.5=reference:file:sc-bundles/splash-screen.jar @@ -45,6 +47,14 @@ felix.auto.start.10= \ reference:file:sc-bundles/slf4j-api.jar \ reference:file:sc-bundles/weupnp.jar +felix.auto.start.11= \ + reference:file:sc-bundles/sip-api.jar \ + reference:file:sc-bundles/sdp-api.jar \ + reference:file:sc-bundles/jain-sip-ri.jar \ + reference:file:sc-bundles/java-sdp-nist-bridge.jar \ + reference:file:sc-bundles/ice4j.jar + + # file:lib/bundle/shell.jar \ # file:lib/bundle/servicebinder.jar \ # file:lib/bundle/tablelayout.jar diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 415af6d..044f24e 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -32,7 +32,9 @@ org.osgi.framework.system.packages.extra= \ sun.security.pkcs11; \ sun.reflect; \ org.xbill.DNS;\ - sun.audio + sun.audio;\ + sun.nio.ch;\ + com.sun.nio.sctp # @@ -58,7 +60,16 @@ felix.auto.start.10= \ reference:file:sc-bundles/bccontrib.jar \ reference:file:sc-bundles/hsqldb.jar \ reference:file:sc-bundles/commons-lang.jar \ - reference:file:sc-bundles/guava.jar + reference:file:sc-bundles/guava.jar \ + reference:file:sc-bundles/weupnp.jar + +felix.auto.start.11= \ + reference:file:sc-bundles/sip-api.jar \ + reference:file:sc-bundles/sdp-api.jar \ + reference:file:sc-bundles/jain-sip-ri.jar \ + reference:file:sc-bundles/java-sdp-nist-bridge.jar \ + reference:file:sc-bundles/ice4j.jar + # file:lib/bundle/shell.jar \ # file:lib/bundle/bundlerepository.jar \ # file:lib/bundle/servicebinder.jar \ diff --git a/lib/installer-exclude/ice4j-1.0.jar b/lib/installer-exclude/ice4j-1.0.jar new file mode 100644 index 0000000..f899c28 Binary files /dev/null and b/lib/installer-exclude/ice4j-1.0.jar differ diff --git a/lib/installer-exclude/ice4j.jar b/lib/installer-exclude/ice4j.jar deleted file mode 100644 index 0bdde1c..0000000 Binary files a/lib/installer-exclude/ice4j.jar and /dev/null differ diff --git a/lib/installer-exclude/jain-sdp.jar b/lib/installer-exclude/jain-sdp.jar deleted file mode 100644 index 8f4b7a6..0000000 Binary files a/lib/installer-exclude/jain-sdp.jar and /dev/null differ diff --git a/lib/installer-exclude/jain-sip-api.jar b/lib/installer-exclude/jain-sip-api.jar deleted file mode 100644 index 3ed1a74..0000000 Binary files a/lib/installer-exclude/jain-sip-api.jar and /dev/null differ diff --git a/lib/installer-exclude/jain-sip-ri-ossonly-1.2.279-jitsi-oss1.jar b/lib/installer-exclude/jain-sip-ri-ossonly-1.2.279-jitsi-oss1.jar new file mode 100644 index 0000000..f19d986 Binary files /dev/null and b/lib/installer-exclude/jain-sip-ri-ossonly-1.2.279-jitsi-oss1.jar differ diff --git a/lib/installer-exclude/jain-sip-ri.jar b/lib/installer-exclude/jain-sip-ri.jar deleted file mode 100644 index e5298b6..0000000 Binary files a/lib/installer-exclude/jain-sip-ri.jar and /dev/null differ diff --git a/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar b/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar new file mode 100644 index 0000000..77b8b59 Binary files /dev/null and b/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar differ diff --git a/lib/installer-exclude/sdp-api-1.0.jar b/lib/installer-exclude/sdp-api-1.0.jar new file mode 100644 index 0000000..fc50919 Binary files /dev/null and b/lib/installer-exclude/sdp-api-1.0.jar differ diff --git a/lib/installer-exclude/sip-api-1.2-1.2.jar b/lib/installer-exclude/sip-api-1.2-1.2.jar new file mode 100644 index 0000000..3adf4c3 Binary files /dev/null and b/lib/installer-exclude/sip-api-1.2-1.2.jar differ diff --git a/src/net/java/sip/communicator/impl/netaddr/netaddr.manifest.mf b/src/net/java/sip/communicator/impl/netaddr/netaddr.manifest.mf index f02d7e4..935ff09 100644 --- a/src/net/java/sip/communicator/impl/netaddr/netaddr.manifest.mf +++ b/src/net/java/sip/communicator/impl/netaddr/netaddr.manifest.mf @@ -12,21 +12,16 @@ Import-Package: org.jitsi.service.configuration, net.java.sip.communicator.service.sysactivity, net.java.sip.communicator.service.sysactivity.event, org.osgi.framework, + org.ice4j, + org.ice4j.ice, + org.ice4j.ice.harvest, + org.ice4j.security, org.ice4j.stack, org.xml.sax, org.xml.sax.helpers, javax.crypto, javax.crypto.spec, - javax.sdp, - gov.nist.javax.sdp.fields, com.sun.jna, com.sun.jna.ptr Export-Package: net.java.sip.communicator.service.netaddr, - net.java.sip.communicator.service.netaddr.event, - org.ice4j, - org.ice4j.socket, - org.ice4j.stack, - org.ice4j.ice, - org.ice4j.ice.harvest, - org.ice4j.ice.sdp, - org.ice4j.security + net.java.sip.communicator.service.netaddr.event diff --git a/src/net/java/sip/communicator/impl/protocol/sip/net/SslNetworkLayer.java b/src/net/java/sip/communicator/impl/protocol/sip/net/SslNetworkLayer.java index f1c5856..9d088a2 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/net/SslNetworkLayer.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/net/SslNetworkLayer.java @@ -18,6 +18,7 @@ package net.java.sip.communicator.impl.protocol.sip.net; import gov.nist.core.net.*; +import gov.nist.javax.sip.*; import java.io.*; import java.net.*; @@ -421,4 +422,9 @@ public class SslNetworkLayer return 0; } + + @Override + public void setSipStack(SipStackImpl sipStack) + { + } } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java index c51a96c..47c26a9 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java @@ -36,6 +36,7 @@ import org.jitsi.service.neomedia.*; import org.jitsi.service.neomedia.MediaType; import org.jitsi.service.neomedia.format.*; import org.jitsi.util.*; +import org.opentelecoms.javax.sdp.*; /** * The class contains a number of utility methods that are meant to facilitate @@ -64,7 +65,7 @@ public class SdpUtils /** * A reference to the currently valid SDP factory instance. */ - private static final SdpFactory sdpFactory = SdpFactory.getInstance(); + private static final SdpFactory sdpFactory = new NistSdpFactory(); /** * The name of the SDP attribute that defines zrtp hello hash. diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf index c15c025..2015a17 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf +++ b/src/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf @@ -5,9 +5,22 @@ Bundle-Vendor: jitsi.org Bundle-Version: 0.0.1 Bundle-SymbolicName: net.java.sip.communicator.protocol.sip Import-Package: ch.imvs.sdes4j.srtp, + gov.nist.core, + gov.nist.core.net, + gov.nist.javax.sip, + gov.nist.javax.sip.address, + gov.nist.javax.sip.header, + gov.nist.javax.sip.header.extensions, + gov.nist.javax.sip.message, + gov.nist.javax.sip.stack, javax.net, javax.net.ssl, javax.security.auth.x500, + javax.sdp, + javax.sip, + javax.sip.address, + javax.sip.header, + javax.sip.message, javax.xml.datatype, javax.xml.namespace, javax.xml.parsers, @@ -76,6 +89,7 @@ Import-Package: ch.imvs.sdes4j.srtp, org.jitsi.util.xml, org.json.simple, org.osgi.framework, + org.opentelecoms.javax.sdp, org.w3c.dom, org.xml.sax Export-Package: net.java.sip.communicator.impl.protocol.sip, @@ -88,6 +102,4 @@ Export-Package: net.java.sip.communicator.impl.protocol.sip, net.java.sip.communicator.impl.protocol.sip.xcap.model.resourcelists, net.java.sip.communicator.impl.protocol.sip.xcap.model.xcapcaps, net.java.sip.communicator.impl.protocol.sip.xcap.model.xcaperror, - net.java.sip.communicator.impl.protocol.sip.xcap.utils, - javax.sdp, - gov.nist.javax.sdp.fields + net.java.sip.communicator.impl.protocol.sip.xcap.utils diff --git a/src/net/java/sip/communicator/service/protocol/media/protocol.media.manifest.mf b/src/net/java/sip/communicator/service/protocol/media/protocol.media.manifest.mf index 4436e93..7bac7aa 100644 --- a/src/net/java/sip/communicator/service/protocol/media/protocol.media.manifest.mf +++ b/src/net/java/sip/communicator/service/protocol/media/protocol.media.manifest.mf @@ -15,7 +15,6 @@ Import-Package: javax.xml.parsers, org.ice4j, org.ice4j.ice, org.ice4j.ice.harvest, - org.ice4j.ice.sdp, org.ice4j.security, org.ice4j.socket, org.ice4j.stack, -- cgit v1.1 From e6eef7de549686ae8271f56b848d94cba99d1a2d Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 12 Apr 2016 00:09:23 +0200 Subject: Update fmj (rev 115) --- lib/installer-exclude/fmj-1.0-SNAPSHOT.jar | Bin 1138198 -> 1138875 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/installer-exclude/fmj-1.0-SNAPSHOT.jar b/lib/installer-exclude/fmj-1.0-SNAPSHOT.jar index a9757b3..9e56a31 100644 Binary files a/lib/installer-exclude/fmj-1.0-SNAPSHOT.jar and b/lib/installer-exclude/fmj-1.0-SNAPSHOT.jar differ -- cgit v1.1 From 18d8c5bd786c584d05585f56e557adb798711c07 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Mon, 7 Mar 2016 10:30:04 +0100 Subject: Implements getDouble in JdbcConfigService ConfigurationService recently added abstract getDouble https://github.com/jitsi/libjitsi/commit/0e392064435bbc83a7b69e6d52769132e5932b7f Signed-off-by: Etienne CHAMPETIER --- .../impl/configuration/JdbcConfigService.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java b/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java index 7ba362e..c9c9c3c 100644 --- a/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java +++ b/src/net/java/sip/communicator/impl/configuration/JdbcConfigService.java @@ -595,6 +595,35 @@ public final class JdbcConfigService * (non-Javadoc) * * @see + * org.jitsi.service.configuration.ConfigurationService#getDouble(java.lang + * .String, double) + */ + @Override + public double getDouble(String propertyName, double defaultValue) + { + Object value = this.getProperty(propertyName); + if (value == null || "".equals(value.toString())) + { + return defaultValue; + } + + try + { + return Double.parseDouble(value.toString()); + } + catch (NumberFormatException ex) + { + logger.error(String.format( + "'%s' for property %s not a double, returning default (%s)", + value, propertyName, defaultValue), ex); + return defaultValue; + } + } + + /* + * (non-Javadoc) + * + * @see * org.jitsi.service.configuration.ConfigurationService#getLong(java.lang * .String, long) */ -- cgit v1.1 From a79eae9087fc82ca440c91861d9e06a0044dbd86 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 12 Apr 2016 23:32:16 +0200 Subject: Update libjitsi jitsi/libjitsi@610c7ff106bf879be2d2e0e62a78b1d215d80d53+PR#137 Closes #234 Closes #193 --- lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar | Bin 7709743 -> 7787716 bytes m2/pom.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar index b51dcb5..c29218e 100644 Binary files a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar and b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar differ diff --git a/m2/pom.xml b/m2/pom.xml index 65ad9b3..b057965 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -49,7 +49,7 @@ ${project.groupId} libjitsi - 1.0-20160202.214638-87 + 1.0-20160411.220648-140 -- cgit v1.1 From dcfd2ccc46a0e4eeb21e39d1c63debbe574bb135 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Fri, 15 Apr 2016 22:42:37 +0200 Subject: Update nist-bridge to 1.2 Fixes establishing SIP calls when the origin field is checked by the server (always had "null" for address and type). --- .classpath | 6 +++--- build.xml | 2 +- lib/installer-exclude/java-sdp-nist-bridge-1.1.jar | Bin 8266 -> 0 bytes lib/installer-exclude/java-sdp-nist-bridge-1.2.jar | Bin 0 -> 8302 bytes 4 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 lib/installer-exclude/java-sdp-nist-bridge-1.1.jar create mode 100644 lib/installer-exclude/java-sdp-nist-bridge-1.2.jar diff --git a/.classpath b/.classpath index 4ce3dcc..194ed36 100755 --- a/.classpath +++ b/.classpath @@ -31,15 +31,15 @@ - + - - + + diff --git a/build.xml b/build.xml index c078ed9..94db76c 100644 --- a/build.xml +++ b/build.xml @@ -1125,7 +1125,7 @@ - + diff --git a/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar b/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar deleted file mode 100644 index 77b8b59..0000000 Binary files a/lib/installer-exclude/java-sdp-nist-bridge-1.1.jar and /dev/null differ diff --git a/lib/installer-exclude/java-sdp-nist-bridge-1.2.jar b/lib/installer-exclude/java-sdp-nist-bridge-1.2.jar new file mode 100644 index 0000000..2efa7fc Binary files /dev/null and b/lib/installer-exclude/java-sdp-nist-bridge-1.2.jar differ -- cgit v1.1 From 56994a6829faab50f87436c963bd7fcc7de69028 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 2 May 2016 23:37:22 +0200 Subject: Add SHA256 signatures to Windows binaries Close #254 --- resources/install/build.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/resources/install/build.xml b/resources/install/build.xml index 3922296..d00b397 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -1006,6 +1006,25 @@ + + + + + + + + + + + + + + + + + + @@ -652,6 +652,15 @@ if="is.running.windows" depends="init-native"> + + + + + + + + + + -- cgit v1.1 From 984f1a42940ff8f218135a97fdc2edbee762987f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 10 May 2016 00:07:30 +0200 Subject: Update binaries --- lib/native/windows-64/jmsofficecomm.dll | Bin 300798 -> 333066 bytes lib/native/windows/jmsofficecomm.dll | Bin 293227 -> 325497 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/native/windows-64/jmsofficecomm.dll b/lib/native/windows-64/jmsofficecomm.dll index 974b617..6ce3901 100755 Binary files a/lib/native/windows-64/jmsofficecomm.dll and b/lib/native/windows-64/jmsofficecomm.dll differ diff --git a/lib/native/windows/jmsofficecomm.dll b/lib/native/windows/jmsofficecomm.dll index 7d59f64..e51bc3b 100755 Binary files a/lib/native/windows/jmsofficecomm.dll and b/lib/native/windows/jmsofficecomm.dll differ -- cgit v1.1 From 0fa38fccc460cbcd755cfd2f391eb011cc538f7b Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 10 May 2016 00:15:57 +0200 Subject: Update Felix to 5.4.0 --- lib/felix.jar | Bin 690242 -> 690862 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/felix.jar b/lib/felix.jar index ec4e81a..c91e86b 100644 Binary files a/lib/felix.jar and b/lib/felix.jar differ -- cgit v1.1 From fd2723ba9bba35262f1af1aa3e97efbe9c1c8918 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 11 May 2016 21:30:47 +0200 Subject: Update libjitsi jitsi/libjitsi@fabf4024464a98be45f93163e31d8baae3667923 (build 848) --- lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar | Bin 7787716 -> 7800273 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar index c29218e..5f2c62b 100644 Binary files a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar and b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar differ -- cgit v1.1 From 49f146fb1aea4fe94090de15ceabdb45c3c77fcb Mon Sep 17 00:00:00 2001 From: Tom Uijldert Date: Thu, 12 May 2016 19:35:39 +0200 Subject: Improved SIP Contact comparison. (#7) --- .../impl/protocol/sip/ContactSipImpl.java | 36 ++++++++++++++++++++-- .../sip/TestProtocolProviderServiceSipImpl.java | 25 ++++++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java index 0d0b5e8..3bd574e 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java @@ -535,9 +535,7 @@ public class ContactSipImpl if(obj instanceof String) { String sobj = (String)obj; - - if(sobj.startsWith("sip:")) - sobj = sobj.substring(4); + sobj = stripScheme(stripAddress(sobj)); if(getAddress().equalsIgnoreCase(sobj)) return true; @@ -556,6 +554,38 @@ public class ContactSipImpl } /** + * Get rid of any parameters, ports etc. within a sip contact + * @param address the address to strip + * @return [sip[s]:]user@host without any params or port numbers. + */ + static String stripAddress(String address) + { + if (address != null && address.length() > 0) + { + int idx = address.indexOf(':', 5); + if (idx > -1) + address = address.substring(0, idx); + idx = address.indexOf(';'); + if (idx > -1) + address = address.substring(0, idx); + } + return address; + } + + /** + * @param from address to strip + * @return the address, stripped from either "sip:" or "sips:" + */ + public static String stripScheme(String from) + { + int i = from.substring(0, 5).indexOf(':'); + + if(from.startsWith("sip") && i > 0) + return from.substring(i + 1); + return from; + } + + /** * Returns the presence operation set that this contact belongs * to. * diff --git a/test/net/java/sip/communicator/slick/protocol/sip/TestProtocolProviderServiceSipImpl.java b/test/net/java/sip/communicator/slick/protocol/sip/TestProtocolProviderServiceSipImpl.java index b475ac9..a799668 100644 --- a/test/net/java/sip/communicator/slick/protocol/sip/TestProtocolProviderServiceSipImpl.java +++ b/test/net/java/sip/communicator/slick/protocol/sip/TestProtocolProviderServiceSipImpl.java @@ -19,7 +19,9 @@ package net.java.sip.communicator.slick.protocol.sip; import java.util.*; +import javax.sip.address.*; import junit.framework.*; +import net.java.sip.communicator.impl.protocol.sip.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; @@ -150,7 +152,7 @@ public class TestProtocolProviderServiceSipImpl /** - * Verifies that all operation sets have the type they are declarded to + * Verifies that all operation sets have the type they are declared to * have. * * @throws java.lang.Exception if a class indicated in one of the keys @@ -175,6 +177,27 @@ public class TestProtocolProviderServiceSipImpl } /** + * Tests the equals() implementation of the SIP Contact class + */ + public void testContactSipImpl() throws Exception + { + ProtocolProviderServiceSipImpl provider = + (ProtocolProviderServiceSipImpl) fixture.provider1; + Address reference = + provider.parseAddressString("sip:User@Host"); + Contact referenceContact = new ContactSipImpl(reference, provider); + + assertTrue("Cannot find user-only part in a SIP Contact compare", + referenceContact.equals("User")); + assertTrue("Cannot find SIP Contact using strings", + referenceContact.equals("sip:User@Host")); + assertTrue("Cannot find SIP Contact when protocol is secure", + referenceContact.equals("sips:User@Host")); + assertTrue("Cannot find SIP Contact when port is specified", + referenceContact.equals("sip:User@Host:5060")); + } + + /** * A class that would plugin as a registration listener to a protocol * provider and simply record all events that it sees and notifyAll() * if it sees an event that notifies us of a completed -- cgit v1.1 From 4d18c954495beecb9b3d918bdc8ecd306a9e8bca Mon Sep 17 00:00:00 2001 From: damencho Date: Wed, 11 May 2016 16:42:03 +0300 Subject: Adds protocol-sip to mavenized bundles. --- m2/jitsi-protocol-sip/pom.xml | 91 +++++++++++++++++++++++++++++++++++++++++++ m2/pom.xml | 3 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 m2/jitsi-protocol-sip/pom.xml diff --git a/m2/jitsi-protocol-sip/pom.xml b/m2/jitsi-protocol-sip/pom.xml new file mode 100644 index 0000000..9feaaa0 --- /dev/null +++ b/m2/jitsi-protocol-sip/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-protocol-sip + jar + + jitsi-protocol-sip + + + + org.opentelecoms.sip + sip-api-1.2 + 1.2 + + + org.opentelecoms.sdp + java-sdp-nist-bridge + + + org.jitsi + jain-sip-ri-ossonly + + + dnsjava + dnsjava + + + org.apache.httpcomponents + httpclient + 4.4 + + + org.apache.httpcomponents + httpcore + 4.4 + + + org.apache.httpcomponents + httpmime + 4.4 + + + org.igniterealtime.smack + smack + + + ${project.groupId} + jitsi-version + + + org.osgi + org.osgi.core + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/protocol/sip/**.java + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/protocol/sip/sip.provider.manifest.mf + + + net/java/sip/communicator/impl/protocol/sip/** + + + + + + diff --git a/m2/pom.xml b/m2/pom.xml index b057965..7b19da3 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -7,7 +7,7 @@ org.jitsi jitsi-universe - 1.0-20160405.235512-16 + 1.0-20160511.125516-17 jitsi @@ -34,6 +34,7 @@ jitsi-packetlogging jitsi-protocol jitsi-protocol-jabber + jitsi-protocol-sip jitsi-protocol-media jitsi-reconnect jitsi-resourcemanager -- cgit v1.1 From de5ba7eba42e12043273b30cb8495eafe00367c9 Mon Sep 17 00:00:00 2001 From: damencho Date: Fri, 13 May 2016 16:38:31 +0300 Subject: Adds argdelegation to mavenized bundles. --- m2/jitsi-argdelegation/pom.xml | 57 ++++++++++++++++++++++++++++++++++++++++++ m2/pom.xml | 1 + 2 files changed, 58 insertions(+) create mode 100644 m2/jitsi-argdelegation/pom.xml diff --git a/m2/jitsi-argdelegation/pom.xml b/m2/jitsi-argdelegation/pom.xml new file mode 100644 index 0000000..7dfb648 --- /dev/null +++ b/m2/jitsi-argdelegation/pom.xml @@ -0,0 +1,57 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-argdelegation + jar + + jitsi-argdelegation + + + + ${project.groupId} + jitsi-util + + + org.osgi + org.osgi.core + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/impl/argdelegation/** + net/java/sip/communicator/service/argdelegation/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/impl/argdelegation/argdelegation.manifest.mf + + + net/java/sip/communicator/impl/argdelegation/** + net/java/sip/communicator/service/argdelegation/** + + + + + + diff --git a/m2/pom.xml b/m2/pom.xml index 7b19da3..55681b2 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -18,6 +18,7 @@ https://jitsi.org + jitsi-argdelegation jitsi-certificate jitsi-configuration jitsi-contactlist -- cgit v1.1 From a07c8181f07d1e5874b3cd3de76f0558a39db6f6 Mon Sep 17 00:00:00 2001 From: damencho Date: Fri, 13 May 2016 17:01:14 +0300 Subject: Adds hid to mavenized bundles. --- m2/jitsi-hid/pom.xml | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ m2/pom.xml | 1 + 2 files changed, 52 insertions(+) create mode 100644 m2/jitsi-hid/pom.xml diff --git a/m2/jitsi-hid/pom.xml b/m2/jitsi-hid/pom.xml new file mode 100644 index 0000000..7b0da97 --- /dev/null +++ b/m2/jitsi-hid/pom.xml @@ -0,0 +1,51 @@ + + 4.0.0 + + + org.jitsi + jitsi + 2.9-SNAPSHOT + ../pom.xml + + + jitsi-hid + jar + + jitsi-hid + + + + org.osgi + org.osgi.core + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + net/java/sip/communicator/service/hid/** + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.sourceDirectory}/net/java/sip/communicator/service/hid/hid.manifest.mf + + + net/java/sip/communicator/service/hid/** + + + + + + diff --git a/m2/pom.xml b/m2/pom.xml index 55681b2..9d299b4 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -28,6 +28,7 @@ jitsi-dnsservice jitsi-fileaccess jitsi-globaldisplaydetails + jitsi-hid jitsi-muc jitsi-neomedia jitsi-netaddr -- cgit v1.1 From 8446ee2895b6223abd238e8c92a068f7808acc87 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Fri, 13 May 2016 12:50:09 -0500 Subject: Add "error" and "busy" state to Jibri --- .../protocol/jabber/extensions/jibri/JibriIq.java | 38 +++++++++ .../jabber/extensions/jibri/JibriIqProvider.java | 12 +++ .../jabber/extensions/jibri/RecordingStatus.java | 52 ++++++++++++ .../jabber/extensions/jibri/XMPPErrorPE.java | 93 ++++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index 87abf9a..c49774b 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -83,6 +83,11 @@ public class JibriIq private Action action = Action.UNDEFINED; /** + * XMPPError stores error details for {@link Status#ERROR}. + */ + private XMPPError error; + + /** * Holds recording status. */ private Status status = Status.UNDEFINED; @@ -232,6 +237,28 @@ public class JibriIq } /** + * Sets the XMPPError which will provide details about Jibri + * failure. It is expected to be set when this IQ's status value is + * {@link Status#ERROR}. + * + * @param error XMPPError to be set on this JibriIq + * instance. + */ + public void setXMPPError(XMPPError error) + { + this.error = error; + } + + /** + * Returns {@link XMPPError} with Jibri error details when the status is + * {@link Status#ERROR}. + */ + public XMPPError getError() + { + return error; + } + + /** * Enumerative value of attribute "action" in recording extension. * * @author lishunyang @@ -312,6 +339,17 @@ public class JibriIq PENDING("pending"), /** + * An error occurred any point during startup, recording or shutdown. + */ + ERROR("error"), + + /** + * There are Jibri instances connected to the system, but all of them + * are currently busy. + */ + BUSY("busy"), + + /** * Unknown/uninitialized. */ UNDEFINED("undefined"); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java index ad3a134..155853c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java @@ -21,6 +21,7 @@ import org.jitsi.util.*; import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.provider.*; +import org.jivesoftware.smack.util.PacketParserUtils; import org.xmlpull.v1.*; @@ -82,6 +83,17 @@ public class JibriIqProvider { switch (parser.next()) { + case XmlPullParser.START_TAG: + { + String name = parser.getName(); + + if ("error".equals(name)) + { + XMPPError error = PacketParserUtils.parseError(parser); + iq.setXMPPError(error); + } + break; + } case XmlPullParser.END_TAG: { String name = parser.getName(); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java index 80e6c42..13177cf 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java @@ -19,6 +19,10 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; +import org.jivesoftware.smack.packet.*; + +import java.util.*; + /** * The packet extension added to Jicofo MUC presence to broadcast current * recording status to all conference participants. @@ -71,4 +75,52 @@ public class RecordingStatus { setAttribute(STATUS_ATTRIBUTE, String.valueOf(status)); } + + /** + * Returns XMPPError associated with current + * {@link RecordingStatus}. + */ + public XMPPError getError() + { + XMPPErrorPE errorPe = getErrorPE(); + return errorPe != null ? errorPe.getError() : null; + } + + /** + * Gets {@link XMPPErrorPE} from the list of child packet + * extensions. + * @return {@link XMPPErrorPE} or null if not found. + */ + private XMPPErrorPE getErrorPE() + { + List errorPe + = getChildExtensionsOfType(XMPPErrorPE.class); + + return (XMPPErrorPE) (!errorPe.isEmpty() ? errorPe.get(0) : null); + } + + /** + * Sets XMPPError on this RecordingStatus. + * @param error XMPPError to add error details to this + * RecordingStatus instance or null to have it removed. + */ + public void setError(XMPPError error) + { + if (error != null) + { + // Wrap and add XMPPError as packet extension + XMPPErrorPE errorPe = getErrorPE(); + if (errorPe == null) + { + errorPe = new XMPPErrorPE(error); + addChildExtension(errorPe); + } + errorPe.setError(error); + } + else + { + // Remove error PE + getChildExtensions().remove(getErrorPE()); + } + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java new file mode 100644 index 0000000..a72f310 --- /dev/null +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java @@ -0,0 +1,93 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri; + +import org.jivesoftware.smack.packet.*; + +import java.util.*; + +/** + * Wraps Smack's XMPPError into PacketExtension, so that it + * can be easily inserted into {@link RecordingStatus}. + */ +public class XMPPErrorPE + implements PacketExtension +{ + /** + * XMPPError wrapped into this XMPPErrorPE. + */ + private XMPPError error; + + /** + * Creates new instance of XMPPErrorPE. + * @param xmppError the instance of XMPPError that will be wrapped + * by the newly created XMPPErrorPE. + */ + public XMPPErrorPE(XMPPError xmppError) + { + setError(xmppError); + } + + /** + * Returns the underlying instance of XMPPError. + */ + public XMPPError getError() + { + return error; + } + + /** + * Sets new instance of XMPPError to be wrapped by this + * XMPPErrorPE. + * @param error XMPPError that will be wrapped by this + * XMPPErrorPE. + */ + public void setError(XMPPError error) + { + Objects.requireNonNull(error, "error"); + + this.error = error; + } + + /** + * {@inheritDoc} + */ + @Override + public String getElementName() + { + return "error"; + } + + /** + * {@inheritDoc} + */ + @Override + public String getNamespace() + { + return ""; + } + + /** + * {@inheritDoc} + */ + @Override + public String toXML() + { + return error.toXML(); + } +} -- cgit v1.1 From 1894e6c8bd36780c884e6650fc8628c25a285871 Mon Sep 17 00:00:00 2001 From: damencho Date: Mon, 16 May 2016 15:14:15 +0300 Subject: Adds version to version bundle. --- m2/jitsi-protocol-sip/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/m2/jitsi-protocol-sip/pom.xml b/m2/jitsi-protocol-sip/pom.xml index 9feaaa0..4f1ec6e 100644 --- a/m2/jitsi-protocol-sip/pom.xml +++ b/m2/jitsi-protocol-sip/pom.xml @@ -56,6 +56,7 @@ ${project.groupId} jitsi-version + 2.9-20160511.122033-1 org.osgi -- cgit v1.1 -- cgit v1.1 From aeaa22c76182670afc4a7fa86d828d22685929e9 Mon Sep 17 00:00:00 2001 From: coypoop Date: Tue, 17 May 2016 22:37:08 +0300 Subject: Use string comparison instead of int comparison (#240) Currently if the architecture is defined differently (such as 'amd64' used in NetBSD), this comparison fails with: [: amd64: bad number --- resources/install/generic/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/generic/run.sh b/resources/install/generic/run.sh index a9bf1cc..bbc6306 100644 --- a/resources/install/generic/run.sh +++ b/resources/install/generic/run.sh @@ -6,7 +6,7 @@ ARCH=`uname -m | sed -e s/x86_64/64/ -e s/i.86/32/` # Additionnal JVM arguments CLIENTARGS="" -if [ $ARCH -eq 32 ] +if [ $ARCH = 32 ] then CLIENTARGS="-client -Xmx256m" fi -- cgit v1.1 From 46cf28ef04df709fa5b5a3688f1d8bb3e3283b08 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 13:23:31 +0200 Subject: Remove transport=tls in registrar URI RFC3261 deprecated this attribute: [...] The use of "transport=tls" has consequently been deprecated, partly because it was specific to a single hop of the request. [...] Closes #2 --- .../sip/communicator/impl/protocol/sip/SipRegistrarConnection.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/SipRegistrarConnection.java b/src/net/java/sip/communicator/impl/protocol/sip/SipRegistrarConnection.java index 99cb0f8..2a3ed00 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/SipRegistrarConnection.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/SipRegistrarConnection.java @@ -1288,8 +1288,11 @@ public class SipRegistrarConnection if(registrarPort != ListeningPoint.PORT_5060) registrarURI.setPort(registrarPort); - if(!registrationTransport.equals(ListeningPoint.UDP)) + if(!registrationTransport.equals(ListeningPoint.UDP) + && !registrationTransport.equals(ListeningPoint.TLS)) + { registrarURI.setTransportParam(registrationTransport); + } } return registrarURI; } -- cgit v1.1 From b8b79607237a78cc7406e2ecf73744e0fe18afed Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 16:37:22 +0200 Subject: Better search for contact results The filter pattern is only null when no filter has been set, thus the matching for phone numbers was never executed. --- .../sip/communicator/impl/gui/main/contactlist/SearchFilter.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java index 837d369..4735892 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java @@ -270,14 +270,13 @@ public class SearchFilter */ private boolean isMatching(String text) { - if (filterPattern != null) - return filterPattern.matcher(text).find(); + if (filterPattern != null && filterPattern.matcher(text).find()) + return true; if(isSearchingPhoneNumber && this.filterString != null) return GuiActivator.getPhoneNumberI18nService() .phoneNumbersMatch(this.filterString, text); return true; - } } -- cgit v1.1 From 8c25c8d0fa5b50c91a29bc76bd825d655b352d73 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 17:13:54 +0200 Subject: Remove dead code --- .../gui/main/contactlist/ContactInfoDialog.java | 131 --------------------- 1 file changed, 131 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/gui/main/contactlist/ContactInfoDialog.java diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactInfoDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactInfoDialog.java deleted file mode 100644 index 325be90..0000000 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactInfoDialog.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.gui.main.contactlist; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.gui.customcontrols.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.contactlist.*; - -/** - * The ContactInfoPanel is a popup dialog containing the contact - * detailed info. - * - * @author Yana Stamcheva - */ -public class ContactInfoDialog - extends SIPCommDialog - implements WindowFocusListener -{ - - private JPanel protocolsPanel = new TransparentPanel(new GridLayout(0, 1)); - - private TransparentBackground bg; - - /** - * Creates an instance of the ContactInfoPanel. - * - * @param owner The frame owner of this dialog. - * @param contactItem The MetaContact for the info. - */ - public ContactInfoDialog(Frame owner, MetaContact contactItem) - { - super(owner); - - this.setUndecorated(true); - - this.setModal(true); - - // Create the transparent background component - this.bg = new TransparentBackground(this); - - this.bg.setLayout(new BorderLayout()); - - this.bg.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - - this.getContentPane().setLayout(new BorderLayout()); - - this.init(); - - this.getContentPane().add(bg, BorderLayout.CENTER); - - this.pack(); - - this.setSize(140, 50); - - this.addWindowFocusListener(this); - } - - /** - * Initializes the ContactInfoPanel. - */ - private void init() - { - /* - * String[] protocolList = this.contactItem.getC(); - * - * if(protocolsPanel.getComponentCount() == 0){ for(int i = 0; i < - * protocolList.length; i ++){ - * - * JLabel protocolLabel = new JLabel(protocolList[i], new - * ImageIcon(Constants.getProtocolIcon(protocolList[i])), JLabel.LEFT); - * - * this.protocolsPanel.add(protocolLabel); } } - * - * this.bg.add(protocolsPanel, BorderLayout.CENTER); - */ - } - - /** - * Returns the panel containing all contact protocols' information. - * - * @return the panel containing all contact protocols' information. - */ - public JPanel getProtocolsPanel() - { - return protocolsPanel; - } - - public void windowGainedFocus(WindowEvent e) - { - - } - - public void windowLostFocus(WindowEvent e) - { - close(false); - } - - public void setPopupLocation(int x, int y) - { - this.setLocation(x, y); - - this.bg.updateBackground(x, y); - } - - @Override - protected void close(boolean isEscaped) - { - this.setVisible(false); - this.dispose(); - } -} -- cgit v1.1 From 4e72851284659c03da5194958c8b885eda54af7c Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 17:15:01 +0200 Subject: Format phone number in tooltips --- .../contactlist/contactsource/SourceUIContact.java | 2 +- .../phonenumbers/PhoneNumberI18nServiceImpl.java | 30 ++++++++++++++++++++++ .../service/contactsource/ContactDetail.java | 10 ++++++++ .../service/protocol/PhoneNumberI18nService.java | 10 ++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java index 72bec25..08aaf7e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java @@ -573,7 +573,7 @@ public class SourceUIContact } else { - labelText = contactDetail.getDetail(); + labelText = contactDetail.getDisplayName(); } jLabels[i] = new JLabel(filterAddressDisplay(labelText)); diff --git a/src/net/java/sip/communicator/impl/phonenumbers/PhoneNumberI18nServiceImpl.java b/src/net/java/sip/communicator/impl/phonenumbers/PhoneNumberI18nServiceImpl.java index d1942b2..4d4d417 100644 --- a/src/net/java/sip/communicator/impl/phonenumbers/PhoneNumberI18nServiceImpl.java +++ b/src/net/java/sip/communicator/impl/phonenumbers/PhoneNumberI18nServiceImpl.java @@ -18,6 +18,9 @@ package net.java.sip.communicator.impl.phonenumbers; import com.google.i18n.phonenumbers.*; +import com.google.i18n.phonenumbers.PhoneNumberUtil.*; +import com.google.i18n.phonenumbers.Phonenumber.*; + import net.java.sip.communicator.service.protocol.*; import org.jitsi.service.configuration.*; @@ -183,6 +186,33 @@ public class PhoneNumberI18nServiceImpl } /** + * Tries to format the passed phone number into the international format. If + * parsing fails or the string is not recognized as a valid phone number, + * the input is returned as is. + * + * @param phoneNumber The phone number to format. + * @return the formatted phone number in the international format. + */ + public String formatForDisplay(String phoneNumber) + { + try + { + PhoneNumber pn = PhoneNumberUtil.getInstance().parse(phoneNumber, + System.getProperty("user.country")); + if (PhoneNumberUtil.getInstance().isPossibleNumber(pn)) + { + return PhoneNumberUtil.getInstance().format(pn, + PhoneNumberFormat.INTERNATIONAL); + } + } + catch (NumberParseException e) + { + } + + return phoneNumber; + } + + /** * Indicates if the given string is possibly a phone number. * * @param possibleNumber the string to be verified diff --git a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java index c062035..332c18d 100644 --- a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java +++ b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java @@ -438,9 +438,19 @@ public class ContactDetail this.contactDetailValue = contactDetailValue; if (!StringUtils.isNullOrEmpty(detailDisplayName)) + { this.detailDisplayName = detailDisplayName; + } + else if (category == Category.Phone) + { + this.detailDisplayName = + ContactSourceActivator.getPhoneNumberI18nService() + .formatForDisplay(contactDetailValue); + } else + { this.detailDisplayName = contactDetailValue; + } // category & labels this.category = category; diff --git a/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java b/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java index fa93ce1..521afc5 100644 --- a/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java +++ b/src/net/java/sip/communicator/service/protocol/PhoneNumberI18nService.java @@ -41,6 +41,16 @@ public interface PhoneNumberI18nService public String normalize(String possibleNumber); /** + * Tries to format the passed phone number into the international format. If + * parsing fails or the string is not recognized as a valid phone number, + * the input is returned as is. + * + * @param phoneNumber The phone number to format. + * @return the formatted phone number in the international format. + */ + public String formatForDisplay(String phoneNumber); + + /** * Determines whether two String phone numbers match. * * @param aPhoneNumber a String which represents a phone number to -- cgit v1.1 From 48b147d4969a9768c5701ec673b20ebabe6dd737 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 20:30:30 +0200 Subject: Update Eclipse-project Java compiler level to 1.7 --- .settings/org.eclipse.jdt.core.prefs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 4d8c8f3..21f2ae2 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,14 +1,15 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.compliance=1.7 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -- cgit v1.1 From e575cdb49da6ca61c0f51e0e68f04be6f5b087e0 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 20:31:48 +0200 Subject: Remove superfluous method definition hashCode is defined in Object --- .../sip/communicator/service/protocol/ProtocolProviderService.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java index 0c85e98..15c5b8d 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java @@ -211,13 +211,6 @@ public interface ProtocolProviderService public void shutdown(); /** - * A hashcode allowing usage of protocol providers as keys in Hashtables. - * @return an int that may be used when storing protocol providers as - * hashtable keys. - */ - public int hashCode(); - - /** * Returns the AccountID that uniquely identifies the account represented by * this instance of the ProtocolProviderService. * @return the id of the account represented by this provider. -- cgit v1.1 From 6fa91bd6cb35dcdc89e32bb9e155f4d01ff1e5b4 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 20:33:26 +0200 Subject: Validate protocol addresses before creating a contact Instead of simply failing after clicking OK when adding a contact, validate the address/ID supplied by the user, show an error and attempt to correct it. --- resources/languages/resources.properties | 6 ++ .../gui/main/contactlist/AddContactDialog.java | 23 ++++++ .../jabber/ProtocolProviderServiceJabberImpl.java | 87 +++++++++++++++++++++ .../impl/protocol/mock/MockProvider.java | 9 +++ .../sip/ProtocolProviderServiceSipImpl.java | 89 +++++++++++++++++++++- .../protocol/AbstractProtocolProviderService.java | 13 ++++ .../service/protocol/ProtocolProviderService.java | 17 +++++ 7 files changed, 240 insertions(+), 4 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index ba631d9..20b0691 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -902,6 +902,12 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Phone prefix impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS=''{0}'' is not a valid SIP address. + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS=''{0}'' is not a valid XMPP JID. + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Address book plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Enable MacOSX Address Book search diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index 856ae5b..f92fbbe 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -21,10 +21,13 @@ import java.awt.*; import java.awt.Container; import java.awt.event.*; import java.util.*; +import java.util.List; import javax.swing.*; import javax.swing.event.*; +import org.jitsi.util.*; + import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.contactlist.addgroup.*; import net.java.sip.communicator.impl.gui.utils.*; @@ -499,6 +502,26 @@ public class AddContactDialog final String contactAddress = contactAddressField.getText().trim(); final String displayName = displayNameField.getText(); + List validationResult = new ArrayList<>(2); + if (!protocolProvider.validateContactAddress(contactAddress, + validationResult)) + { + new ErrorDialog(GuiActivator.getUIService().getMainFrame(), + GuiActivator.getResources() + .getI18NString("service.gui.ADD_CONTACT_ERROR_TITLE"), + validationResult.get(0), ErrorDialog.WARNING).showDialog(); + if (validationResult.size() >= 2) + { + contactAddressField.setText(validationResult.get(1)); + if (StringUtils.isNullOrEmpty(displayName, true)) + { + displayNameField.setText(contactAddress); + } + } + + return; + } + if (!protocolProvider.isRegistered()) { new ErrorDialog( diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 425b70a..888c0aa 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -2040,6 +2040,93 @@ public class ProtocolProviderServiceJabberImpl } /** + * Validates the node part of a JID and returns an error message if + * applicable and a suggested correction. + * + * @param contactId the contact identifier to validate + * @param result Must be supplied as an empty a list. Implementors add + * items: + *
      + *
    1. is the error message if applicable + *
    2. a suggested correction. Index 1 is optional and can only + * be present if there was a validation failure. + *
    + * @return true if the contact id is valid, false otherwise + */ + @Override + public boolean validateContactAddress(String contactId, List result) + { + if (result == null) + { + throw new IllegalArgumentException("result must be an empty list"); + } + + result.clear(); + try + { + contactId = contactId.trim(); + if (contactId.length() == 0) + { + result.add(JabberActivator.getResources().getI18NString( + "impl.protocol.jabber.INVALID_ADDRESS", new String[] + { contactId })); + // no suggestion for an empty id + return false; + } + + String user = contactId; + String remainder = ""; + int at = contactId.indexOf('@'); + if (at > -1) + { + user = contactId.substring(0, at); + remainder = contactId.substring(at); + } + + // ::= #x21 | [#x23-#x25] | [#x28-#x2E] | + // [#x30-#x39] | #x3B | #x3D | #x3F | + // [#x41-#x7E] | [#x80-#xD7FF] | + // [#xE000-#xFFFD] | [#x10000-#x10FFFF] + boolean valid = true; + String suggestion = ""; + for (char c : user.toCharArray()) + { + if (!(c == 0x21 || (c >= 0x23 && c <= 0x25) + || (c >= 0x28 && c <= 0x2e) || (c >= 0x30 && c <= 0x39) + || c == 0x3b || c == 0x3d || c == 0x3f + || (c >= 0x41 && c <= 0x7e) || (c >= 0x80 && c <= 0xd7ff) + || (c >= 0xe000 && c <= 0xfffd))) + { + valid = false; + } + else + { + suggestion += c; + } + } + + if (!valid) + { + result.add(JabberActivator.getResources().getI18NString( + "impl.protocol.jabber.INVALID_ADDRESS", new String[] + { contactId })); + result.add(suggestion + remainder); + return false; + } + + return true; + } + catch (Exception ex) + { + result.add(JabberActivator.getResources().getI18NString( + "impl.protocol.jabber.INVALID_ADDRESS", new String[] + { contactId })); + } + + return false; + } + + /** * Returns the XMPPConnectionopened by this provider * @return a reference to the XMPPConnection last opened by this * provider. diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java b/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java index bcff799..a7b6e5e 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockProvider.java @@ -294,6 +294,15 @@ public class MockProvider } /** + * Always true. + */ + @Override + public boolean validateContactAddress(String contactId, List result) + { + return true; + } + + /** * Mock implementation of the corresponding ProtocolProviderService method. * We have no icon corresponding to this protocol provider. */ diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index d0460fb..a978de8 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -246,6 +246,72 @@ public class ProtocolProviderServiceSipImpl } /** + * Validates the contact identifier and returns an error message if + * applicable and a suggested correction + * + * @param contactId the contact identifier to validate + * @param result Must be supplied as an empty a list. Implementors add + * items: + *
      + *
    1. is the error message if applicable + *
    2. a suggested correction. Index 1 is optional and can only + * be present if there was a validation failure. + *
    + * @return true if the contact id is valid, false otherwise + */ + @Override + public boolean validateContactAddress(String contactId, List result) + { + if (result == null) + { + throw new IllegalArgumentException("result must be an empty list"); + } + + result.clear(); + try + { + Address address = parseAddressString(contactId); + if (address.toString().equals(contactId)) + { + return true; + } + else if (((SipUri) address.getURI()).getUser().equals(contactId)) + { + return true; + } + else + { + result.add(SipActivator.getResources().getI18NString( + "impl.protocol.sip.INVALID_ADDRESS", new String[] + { contactId })); + result.add(((SipUri) address.getURI()).getUser()); + } + } + catch (Exception ex) + { + logger.error("Validating SIP address failed for " + contactId, ex); + result.add(SipActivator.getResources() + .getI18NString("impl.protocol.sip.INVALID_ADDRESS", new String[] + { contactId })); + + String user = contactId; + String remainder = ""; + int at = contactId.indexOf('@'); + if (at > -1) + { + user = contactId.substring(0, at); + remainder = contactId.substring(at); + } + + // replace invalid characters in user part with hex encoding + String banned = "([^a-z0-9-_.!~*'()&=+$,;?/])+"; + result.add(user.replaceAll(banned, "") + remainder); + } + + return false; + } + + /** * Indicates whether or not this provider must registered * when placing outgoing calls. * @@ -2390,21 +2456,36 @@ public class ProtocolProviderServiceSipImpl //we don't know how to handle the "tel:" and "callto:" schemes ... or // rather we handle them same as sip so replace: if(uriStr.toLowerCase().startsWith("tel:")) - uriStr = "sip:" + uriStr.substring("tel:".length()); + uriStr = uriStr.substring("tel:".length()); else if(uriStr.toLowerCase().startsWith("callto:")) - uriStr = "sip:" + uriStr.substring("callto:".length()); + uriStr = uriStr.substring("callto:".length()); + else if(uriStr.toLowerCase().startsWith("sips:")) + uriStr = uriStr.substring("sips:".length()); + + String user = uriStr; + String remainder = ""; + int at = uriStr.indexOf('@'); + if (at > -1) + { + user = uriStr.substring(0, at); + remainder = uriStr.substring(at); + } + + //replace invalid characters in user part with hex encoding + String banned = "([^a-z0-9-_.!~*'()&=+$,;?/])+"; + user = user.replaceAll(banned, "") + remainder; //Handle default domain name (i.e. transform 1234 -> 1234@sip.com) //assuming that if no domain name is specified then it should be the //same as ours. - if (uriStr.indexOf('@') == -1) + if (at == -1) { //if we have a registrar, then we could append its domain name as //default SipRegistrarConnection src = sipRegistrarConnection; if(src != null && !src.isRegistrarless() ) { - uriStr = uriStr + "@" + uriStr = user + "@" + ((SipURI)src.getAddressOfRecord().getURI()).getHost(); } diff --git a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java index 9a78eec..897b74b 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractProtocolProviderService.java @@ -245,6 +245,19 @@ public abstract class AbstractProtocolProviderService } /** + * Default implementation that always returns true. + * + * @param contactId ignored. + * @param result ignored + * @return true + */ + @Override + public boolean validateContactAddress(String contactId, List result) + { + return true; + } + + /** * Returns an array containing all operation sets supported by the current * implementation. When querying this method users must be prepared to * receive any subset of the OperationSet-s defined by this service. They diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java index 15c5b8d..ffc356c 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderService.java @@ -218,6 +218,23 @@ public interface ProtocolProviderService public AccountID getAccountID(); /** + * Validates the given protocol specific contact identifier and returns an + * error message if applicable and a suggested correction. + * + * @param contactId the contact identifier to validate + * @param result Must be supplied as an empty a list. Implementors add + * items: + *
      + *
    1. is the error message if applicable + *
    2. a suggested correction. Index 1 is optional and can only + * be present if there was a validation failure. + *
    + * @return true if the contact id is valid, false otherwise + */ + public boolean validateContactAddress(String contactId, + List result); + + /** * Indicate if the signaling transport of this protocol instance uses a * secure (e.g. via TLS) connection. * -- cgit v1.1 From 812a26f4cecf9e56106a6d93e46c6826fc433685 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 May 2016 21:37:12 +0200 Subject: Add support for Outlook 2016 address book search --- lib/native/windows-64/jmsoutlookaddrbook.dll | Bin 302107 -> 244564 bytes .../windows-64/jmsoutlookaddrbookcomserver32.exe | Bin 249432 -> 246848 bytes .../windows-64/jmsoutlookaddrbookcomserver64.exe | Bin 308098 -> 252108 bytes lib/native/windows/jmsoutlookaddrbook.dll | Bin 242469 -> 239403 bytes .../windows/jmsoutlookaddrbookcomserver32.exe | Bin 249432 -> 246848 bytes .../windows/jmsoutlookaddrbookcomserver64.exe | Bin 308098 -> 252108 bytes src/native/addrbook/msoutlook/MAPIBitness.cxx | 4 +++- src/native/build.xml | 3 +++ 8 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/native/windows-64/jmsoutlookaddrbook.dll b/lib/native/windows-64/jmsoutlookaddrbook.dll index 70095cb..85be249 100755 Binary files a/lib/native/windows-64/jmsoutlookaddrbook.dll and b/lib/native/windows-64/jmsoutlookaddrbook.dll differ diff --git a/lib/native/windows-64/jmsoutlookaddrbookcomserver32.exe b/lib/native/windows-64/jmsoutlookaddrbookcomserver32.exe index 6cfa4f0..8415e77 100755 Binary files a/lib/native/windows-64/jmsoutlookaddrbookcomserver32.exe and b/lib/native/windows-64/jmsoutlookaddrbookcomserver32.exe differ diff --git a/lib/native/windows-64/jmsoutlookaddrbookcomserver64.exe b/lib/native/windows-64/jmsoutlookaddrbookcomserver64.exe index 4202f2d..66d3db2 100755 Binary files a/lib/native/windows-64/jmsoutlookaddrbookcomserver64.exe and b/lib/native/windows-64/jmsoutlookaddrbookcomserver64.exe differ diff --git a/lib/native/windows/jmsoutlookaddrbook.dll b/lib/native/windows/jmsoutlookaddrbook.dll index b8445de..a976aea 100755 Binary files a/lib/native/windows/jmsoutlookaddrbook.dll and b/lib/native/windows/jmsoutlookaddrbook.dll differ diff --git a/lib/native/windows/jmsoutlookaddrbookcomserver32.exe b/lib/native/windows/jmsoutlookaddrbookcomserver32.exe index 849a90e..22fdb2a 100755 Binary files a/lib/native/windows/jmsoutlookaddrbookcomserver32.exe and b/lib/native/windows/jmsoutlookaddrbookcomserver32.exe differ diff --git a/lib/native/windows/jmsoutlookaddrbookcomserver64.exe b/lib/native/windows/jmsoutlookaddrbookcomserver64.exe index a9dc028..dfb52de 100755 Binary files a/lib/native/windows/jmsoutlookaddrbookcomserver64.exe and b/lib/native/windows/jmsoutlookaddrbookcomserver64.exe differ diff --git a/src/native/addrbook/msoutlook/MAPIBitness.cxx b/src/native/addrbook/msoutlook/MAPIBitness.cxx index 46d80a4..9853b10 100644 --- a/src/native/addrbook/msoutlook/MAPIBitness.cxx +++ b/src/native/addrbook/msoutlook/MAPIBitness.cxx @@ -32,13 +32,14 @@ /** * The number of registries known for the different Outlook version. */ -int nbOutlookRegister = 4; +int nbOutlookRegister = 5; /** * The registries known for the different Outlook version. */ TCHAR outlookRegister[][MAX_PATH] = { + TEXT("{5812C571-53F0-4467-BEFA-0A4F47A9437C}"), // Outlook 2016 TEXT("{E83B4360-C208-4325-9504-0D23003A74A5}"), // Outlook 2013 TEXT("{1E77DE88-BCAB-4C37-B9E5-073AF52DFD7A}"), // Outlook 2010 TEXT("{24AAE126-0911-478F-A019-07B875EB9996}"), // Outlook 2007 @@ -91,6 +92,7 @@ int MAPIBitness_getOutlookBitnessVersion(void) int MAPIBitness_getOutlookVersion(void) { int outlookVersions[] = { + 2016, // Outlook 2016 2013, // Outlook 2013 2010, // Outlook 2010 2007, // Outlook 2007 diff --git a/src/native/build.xml b/src/native/build.xml index ad408af..90c0704 100644 --- a/src/native/build.xml +++ b/src/native/build.xml @@ -592,6 +592,9 @@ can directly use command prompt When changing idl file in visual studio console execute midl . + + Microsoft MAPI headers won't compile with gcc. See: + http://lists.jitsi.org/pipermail/dev/2013-April/001313.html --> Date: Sun, 15 May 2016 23:48:46 +0200 Subject: Register Jitsi as default application for sip:, tel:, etc. --- resources/install/windows/SCRegistrySpec.wxi | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/resources/install/windows/SCRegistrySpec.wxi b/resources/install/windows/SCRegistrySpec.wxi index cf07c53..72479b2 100644 --- a/resources/install/windows/SCRegistrySpec.wxi +++ b/resources/install/windows/SCRegistrySpec.wxi @@ -20,6 +20,27 @@ + + + + + + + + + + + + + + Date: Mon, 16 May 2016 13:16:38 +0200 Subject: Update license to Apache in installers --- resources/install/doc/License.rtf | 526 ++---------------------- resources/install/doc/License.txt | 504 ----------------------- resources/install/generic/installer-generic.xml | 2 +- resources/install/linux/installer-linux.xml | 2 +- 4 files changed, 37 insertions(+), 997 deletions(-) delete mode 100644 resources/install/doc/License.txt diff --git a/resources/install/doc/License.rtf b/resources/install/doc/License.rtf index 941293b..aaae7af 100644 --- a/resources/install/doc/License.rtf +++ b/resources/install/doc/License.rtf @@ -1,491 +1,35 @@ -{\rtf1\ansi\deff1\adeflang1025 -{\fonttbl{\f0\froman\fprq2\fcharset0 Nimbus Roman No9 L{\*\falt Times New Roman};}{\f1\fmodern\fprq1\fcharset0 Courier New;}{\f2\fswiss\fprq2\fcharset0 Nimbus Sans L{\*\falt Arial};}{\f3\fmodern\fprq1\fcharset0 Courier New;}{\f4\fnil\fprq2\fcharset0 DejaVu Sans;}} -{\colortbl;\red0\green0\blue0;\red128\green128\blue128;} -{\stylesheet{\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang1036\loch\f1\fs24\lang1036\snext1 Normal;} -{\s2\sb240\sa120\keepn\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs28\lang255\ltrch\dbch\af4\langfe255\hich\f2\fs28\lang1036\loch\f2\fs28\lang1036\sbasedon1\snext3 Heading;} -{\s3\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang1036\loch\f1\fs24\lang1036\sbasedon1\snext3 Body Text;} -{\s4\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang1036\loch\f1\fs24\lang1036\sbasedon3\snext4 List;} -{\s5\sb120\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang255\ai\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang1036\i\loch\f1\fs24\lang1036\i\sbasedon1\snext5 caption;} -{\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs24\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs24\lang1036\loch\f1\fs24\lang1036\sbasedon1\snext6 Index;} -} -{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment StarWriter}{\vern6800}}\deftab720 -{\*\pgdsctbl -{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Standard;}} -{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc -\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab GNU LESSER GENERAL PUBLIC LICENSE} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab Version 2.1, February 1999} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab \tab Preamble} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for al -l its users.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think care -fully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you rece -ive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or i -f you modify it.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the libr -ary, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so tha -t the original author's reputation will not be affected by problems that might be introduced by others.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Finally, software patents pose a constant threat to the existence of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 any free program. We wish to make sure that a company cannot} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 effectively restrict the users of a free program by obtaining a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 restrictive license from a patent holder. Therefore, we insist that} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 any patent license obtained for a version of the library must be} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 consistent with the full freedom of use specified in this license.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Most GNU software, including some libraries, is covered by the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 ordinary GNU General Public License. This license, the GNU Lesser} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 General Public License, applies to certain designated libraries, and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 is quite different from the ordinary General Public License. We use} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this license for certain libraries in order to permit linking those} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 libraries into non-free programs.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 When a program is linked with a library, whether statically or using} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a shared library, the combination of the two is legally speaking a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 combined work, a derivative of the original library. The ordinary} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 General Public License therefore permits such linking only if the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 entire combination fits its criteria of freedom. The Lesser General} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Public License permits more lax criteria for linking other code with} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 We call this license the "Lesser" General Public License because it} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 does Less to protect the user's freedom than the ordinary General} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Public License. It also provides other free software developers Less} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 of an advantage over competing non-free programs. These disadvantages} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 are the reason we use the ordinary General Public License for many} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 libraries. However, the Lesser license provides advantages in certain} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 special circumstances.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 For example, on rare occasions, there may be a special need to} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 encourage the widest possible use of a certain library, so that it becomes} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a de-facto standard. To achieve this, non-free programs must be} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 allowed to use the library. A more frequent case is that a free} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 library does the same job as widely used non-free libraries. In this} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 case, there is little to gain by limiting the free library to free} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 software only, so we use the Lesser General Public License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 In other cases, permission to use a particular library in non-free} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 programs enables a greater number of people to use a large body of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 free software. For example, permission to use the GNU C Library in} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 non-free programs enables many more people to use the whole GNU} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 operating system, as well as its variant, the GNU/Linux operating} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 system.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Although the Lesser General Public License is Less protective of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 users' freedom, it does ensure that the user of a program that is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 linked with the Library has the freedom and the wherewithal to run} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that program using a modified version of the Library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 The precise terms and conditions for copying, distribution and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 modification follow. Pay close attention to the difference between a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 "work based on the library" and a "work that uses the library". The} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 former contains code derived from the library, whereas the latter must} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 be combined with the library in order to run.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab GNU LESSER GENERAL PUBLIC LICENSE} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 0. This License Agreement applies to any software library or other} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 program which contains a notice placed by the copyright holder or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 other authorized party saying it may be distributed under the terms of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this Lesser General Public License (also called "this License").} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Each licensee is addressed as "you".} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 A "library" means a collection of software functions and/or data} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 prepared so as to be conveniently linked with application programs} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 (which use some of those functions and data) to form executables.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 The "Library", below, refers to any such software library or work} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 which has been distributed under these terms. A "work based on the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library" means either the Library or any derivative work under} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 copyright law: that is to say, a work containing the Library or a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 portion of it, either verbatim or with modifications and/or translated} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 straightforwardly into another language. (Hereinafter, translation is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 included without limitation in the term "modification".)} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 "Source code" for a work means the preferred form of the work for} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 making modifications to it. For a library, complete source code means} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 all the source code for all modules it contains, plus any associated} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 interface definition files, plus the scripts used to control compilation} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and installation of the library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Activities other than copying, distribution and modification are not} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 covered by this License; they are outside its scope. The act of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 running a program using the Library is not restricted, and output from} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 such a program is covered only if its contents constitute a work based} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 on the Library (independent of the use of the Library in a tool for} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 writing it). Whether that is true depends on what the Library does} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and what the program that uses the Library does.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch } -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}{\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 1. You may copy and distribute verbatim copies of the Library's} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 complete source code as you receive it, in any medium, provided that} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 you conspicuously and appropriately publish on each copy an} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 appropriate copyright notice and disclaimer of warranty; keep intact} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 all the notices that refer to this License and to the absence of any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 warranty; and distribute a copy of this License along with the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 You may charge a fee for the physical act of transferring a copy,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and you may at your option offer warranty protection in exchange for a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 fee.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 2. You may modify your copy or copies of the Library or any portion} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 of it, thus forming a work based on the Library, and copy and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute such modifications or work under the terms of Section 1} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 above, provided that you also meet all of these conditions:} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a) The modified work must itself be a software library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 b) You must cause the files modified to carry prominent notices} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 stating that you changed the files and the date of any change.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 c) You must cause the whole of the work to be licensed at no} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 charge to all third parties under the terms of this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 d) If a facility in the modified Library refers to a function or a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 table of data to be supplied by an application program that uses} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the facility, other than as an argument passed when the facility} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 is invoked, then you must make a good faith effort to ensure that,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 in the event an application does not supply such function or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 table, the facility still operates, and performs whatever part of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 its purpose remains meaningful.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 (For example, a function in a library to compute square roots has} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a purpose that is entirely well-defined independent of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 application. Therefore, Subsection 2d requires that any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 application-supplied function or table used by this function must} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 be optional: if the application does not supply it, the square} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 root function must still compute square roots.)} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 These requirements apply to the modified work as a whole. If} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 identifiable sections of that work are not derived from the Library,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and can be reasonably considered independent and separate works in} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 themselves, then this License, and its terms, do not apply to those} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 sections when you distribute them as separate works. But when you} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute the same sections as part of a whole which is a work based} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 on the Library, the distribution of the whole must be on the terms of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this License, whose permissions for other licensees extend to the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 entire whole, and thus to each and every part regardless of who wrote} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 it.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Thus, it is not the intent of this section to claim rights or contest} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 your rights to work written entirely by you; rather, the intent is to} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 exercise the right to control the distribution of derivative or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 collective works based on the Library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 In addition, mere aggregation of another work not based on the Library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 with the Library (or with a work based on the Library) on a volume of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a storage or distribution medium does not bring the other work under} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the scope of this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 3. You may opt to apply the terms of the ordinary GNU General Public} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 License instead of this License to a given copy of the Library. To do} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this, you must alter all the notices that refer to this License, so} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that they refer to the ordinary GNU General Public License, version 2,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 instead of to this License. (If a newer version than version 2 of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 ordinary GNU General Public License has appeared, then you can specify} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that version instead if you wish.) Do not make any other change in} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 these notices.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Once this change is made in a given copy, it is irreversible for} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that copy, so the ordinary GNU General Public License applies to all} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 subsequent copies and derivative works made from that copy.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 This option is useful when you wish to copy part of the code of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Library into a program that is not a library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 4. You may copy and distribute the Library (or a portion or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 derivative of it, under Section 2) in object code or executable form} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 under the terms of Sections 1 and 2 above provided that you accompany} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 it with the complete corresponding machine-readable source code, which} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 must be distributed under the terms of Sections 1 and 2 above on a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 medium customarily used for software interchange.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 If distribution of object code is made by offering access to copy} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 from a designated place, then offering equivalent access to copy the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 source code from the same place satisfies the requirement to} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute the source code, even though third parties are not} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 compelled to copy the source along with the object code.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 5. A program that contains no derivative of any portion of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library, but is designed to work with the Library by being compiled or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 linked with it, is called a "work that uses the Library". Such a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 work, in isolation, is not a derivative work of the Library, and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 therefore falls outside the scope of this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 However, linking a "work that uses the Library" with the Library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 creates an executable that is a derivative of the Library (because it} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 contains portions of the Library), rather than a "work that uses the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 library". The executable is therefore covered by this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Section 6 states terms for distribution of such executables.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 When a "work that uses the Library" uses material from a header file} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that is part of the Library, the object code for the work may be a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 derivative work of the Library even though the source code is not.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Whether this is true is especially significant if the work can be} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 linked without the Library, or if the work is itself a library. The} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 threshold for this to be true is not precisely defined by law.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 If such an object file uses only numerical parameters, data} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 structure layouts and accessors, and small macros and small inline} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 functions (ten lines or less in length), then the use of the object} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 file is unrestricted, regardless of whether it is legally a derivative} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 work. (Executables containing this object code plus portions of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library will still fall under Section 6.)} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Otherwise, if the work is a derivative of the Library, you may} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute the object code for the work under the terms of Section 6.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Any executables containing that work also fall under Section 6,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 whether or not they are linked directly with the Library itself.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 6. As an exception to the Sections above, you may also combine or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 link a "work that uses the Library" with the Library to produce a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 work containing portions of the Library, and distribute that work} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 under terms of your choice, provided that the terms permit} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 modification of the work for the customer's own use and reverse} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 engineering for debugging such modifications.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 You must give prominent notice with each copy of the work that the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library is used in it and that the Library and its use are covered by} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this License. You must supply a copy of this License. If the work} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 during execution displays copyright notices, you must include the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 copyright notice for the Library among them, as well as a reference} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 directing the user to the copy of this License. Also, you must do one} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 of these things:} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a) Accompany the work with the complete corresponding} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 machine-readable source code for the Library including whatever} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 changes were used in the work (which must be distributed under} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Sections 1 and 2 above); and, if the work is an executable linked} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 with the Library, with the complete machine-readable "work that} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 uses the Library", as object code and/or source code, so that the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 user can modify the Library and then relink to produce a modified} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 executable containing the modified Library. (It is understood} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that the user who changes the contents of definitions files in the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library will not necessarily be able to recompile the application} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 to use the modified definitions.)} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 b) Use a suitable shared library mechanism for linking with the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library. A suitable mechanism is one that (1) uses at run time a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 copy of the library already present on the user's computer system,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 rather than copying library functions into the executable, and (2)} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 will operate properly with a modified version of the library, if} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the user installs one, as long as the modified version is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 interface-compatible with the version that the work was made with.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 c) Accompany the work with a written offer, valid for at} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 least three years, to give the same user the materials} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 specified in Subsection 6a, above, for a charge no more} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 than the cost of performing this distribution.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 d) If distribution of the work is made by offering access to copy} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 from a designated place, offer equivalent access to copy the above} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 specified materials from the same place.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 e) Verify that the user has already received a copy of these} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 materials or that you have already sent this user a copy.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 For an executable, the required form of the "work that uses the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library" must include any data and utility programs needed for} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 reproducing the executable from it. However, as a special exception,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the materials to be distributed need not include anything that is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 normally distributed (in either source or binary form) with the major} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 components (compiler, kernel, and so on) of the operating system on} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 which the executable runs, unless that component itself accompanies} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the executable.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 It may happen that this requirement contradicts the license} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 restrictions of other proprietary libraries that do not normally} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 accompany the operating system. Such a contradiction means you cannot} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 use both them and the Library together in an executable that you} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 7. You may place library facilities that are a work based on the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library side-by-side in a single library together with other library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 facilities not covered by this License, and distribute such a combined} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 library, provided that the separate distribution of the work based on} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Library and of the other library facilities is otherwise} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 permitted, and provided that you do these two things:} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 a) Accompany the combined library with a copy of the same work} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 based on the Library, uncombined with any other library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 facilities. This must be distributed under the terms of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Sections above.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 b) Give prominent notice with the combined library of the fact} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 that part of it is a work based on the Library, and explaining} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 where to find the accompanying uncombined form of the same work.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 8. You may not copy, modify, sublicense, link with, or distribute} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Library except as expressly provided under this License. Any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 attempt otherwise to copy, modify, sublicense, link with, or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute the Library is void, and will automatically terminate your} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 rights under this License. However, parties who have received copies,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 or rights, from you under this License will not have their licenses} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 terminated so long as such parties remain in full compliance.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 9. You are not required to accept this License, since you have not} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 signed it. However, nothing else grants you permission to modify or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute the Library or its derivative works. These actions are} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 prohibited by law if you do not accept this License. Therefore, by} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 modifying or distributing the Library (or any work based on the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library), you indicate your acceptance of this License to do so, and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 all its terms and conditions for copying, distributing or modifying} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Library or works based on it.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 10. Each time you redistribute the Library (or any work based on the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Library), the recipient automatically receives a license from the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 original licensor to copy, distribute, link with or modify the Library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 subject to these terms and conditions. You may not impose any further} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 restrictions on the recipients' exercise of the rights granted herein.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 You are not responsible for enforcing compliance by third parties with} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 this License.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 11. If, as a consequence of a court judgment or allegation of patent} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 infringement or for any other reason (not limited to patent issues),} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 conditions are imposed on you (whether by court order, agreement or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 otherwise) that contradict the conditions of this License, they do not} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 excuse you from the conditions of this License. If you cannot} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 distribute so as to satisfy simultaneously your obligations under this} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 License and any other pertinent obligations, then as a consequence you} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 may not distribute the Library at all. For example, if a patent} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 license would not permit royalty-free redistribution of the Library by} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 all those who receive copies directly or indirectly through you, then} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the only way you could satisfy both it and this License would be to} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 refrain entirely from distribution of the Library.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 If any portion of this section is held invalid or unenforceable under any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 particular circumstance, the balance of the section is intended to apply,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and the section as a whole is intended to apply in other circumstances.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 It is not the purpose of this section to induce you to infringe any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 patents or other property right claims or to contest validity of any} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 such claims; this section has the sole purpose of protecting the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 integrity of the free software distribution system which is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 implemented by public license practices. Many people have made} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 generous contributions to the wide range of software distributed} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 through that system in reliance on consistent application of that} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 system; it is up to the author/donor to decide if he or she is willing} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 to distribute software through any other system and a licensee cannot} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 impose that choice.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 This section is intended to make thoroughly clear what is believed to} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 be a consequence of the rest of this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 12. If the distribution and/or use of the Library is restricted in} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 certain countries either by patents or by copyrighted interfaces, the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 original copyright holder who places the Library under this License may add} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 an explicit geographical distribution limitation excluding those countries,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 so that distribution is permitted only in or among countries not thus} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 excluded. In such case, this License incorporates the limitation as if} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 written in the body of this License.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 13. The Free Software Foundation may publish revised and/or new} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 versions of the Lesser General Public License from time to time.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Such new versions will be similar in spirit to the present version,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 but may differ in detail to address new problems or concerns.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Each version is given a distinguishing version number. If the Library} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 specifies a version number of this License which applies to it and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 "any later version", you have the option of following the terms and} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 conditions either of that version or of any later version published by} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Free Software Foundation. If the Library does not specify a} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 license version number, you may choose any version ever published by} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 the Free Software Foundation.} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 14. If you wish to incorporate parts of the Library into other free} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 programs whose distribution conditions are incompatible with these,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 write to the author to ask for permission. For software which is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 copyrighted by the Free Software Foundation, write to the Free} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Software Foundation; we sometimes make exceptions for this. Our} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 decision will be guided by the two goals of preserving the free status} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 of all derivatives of our free software and of promoting the sharing} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 and reuse of software generally.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab \tab NO WARRANTY} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 DAMAGES.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 \tab \tab END OF TERMS AND CONDITIONS} -\par \page\pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 How to Apply These Terms to Your New Libraries} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 If you develop a new library, and you want it to be of the greatest} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 possible use to the public, we recommend making it free software that} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 everyone can redistribute and change. You can do so by permitting} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 redistribution under these terms (or, alternatively, under the terms of the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 ordinary General Public License).} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 To apply these terms, attach the following notices to the library. It is} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 safest to attach them to the start of each source file to most effectively} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 convey the exclusion of warranty; and each file should have at least the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 "copyright" line and a pointer to where the full notice is found.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 } -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Copyright (C) } -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 This library is free software; you can redistribute it and/or} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 modify it under the terms of the GNU Lesser General Public} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 License as published by the Free Software Foundation; either} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 version 2.1 of the License, or (at your option) any later version.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 This library is distributed in the hope that it will be useful,} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 but WITHOUT ANY WARRANTY; without even the implied warranty of} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Lesser General Public License for more details.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 You should have received a copy of the GNU Lesser General Public} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 License along with this library; if not, write to the Free Software} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Also add information on how to contact you by electronic and paper mail.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 You should also get your employer (if you work as a programmer) or your} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 school, if any, to sign a "copyright disclaimer" for the library, if} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 necessary. Here is a sample; alter the names:} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Yoyodyne, Inc., hereby disclaims all copyright interest in the} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 library `Frob' (a library for tweaking knobs) written by James Random Hacker.} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 , 1 April 1990} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch }{\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 Ty Coon, President of Vice} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 {\rtlch \ltrch\loch\f1\fs20\lang1033\i0\b0 That's all there is to it!} -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par \pard\plain \ltrpar\s1\cf0\qj{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af1\afs20\lang255\ltrch\dbch\af1\langfe255\hich\f1\fs20\lang1033\loch\f1\fs20\lang1033 -\par } \ No newline at end of file +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fprq2\fcharset0 Georgia;}} +{\colortbl ;\red51\green51\blue51;\red0\green0\blue255;\red88\green90\blue194;\red255\green255\blue255;} +{\*\generator Riched20 10.0.10586}{\*\mmathPr\mnaryLim0\mdispDef1\mwrapIndent1440 }\viewkind4\uc1 +\pard\cbpat4\widctlpar\sa150\sl300\slmult0\cf1\f0\fs28 Apache License\line Version 2.0, January 2004\line\fs21\line {\cf0{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/ }}{\fldrslt{http://www.apache.org/licenses/\ul0\cf0}}}}\f0\fs21\par +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\par +\cf3\b 1. Definitions\cf1\b0 .\par +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\par +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\par +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\par +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.\par +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\par +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\par +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\par +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\par +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."\par +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\par +\cf3\b 2. Grant of Copyright License\cf1\b0 . Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\par +\cf3\b 3. Grant of Patent License\cf1\b0 . Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\par +\cf3\b 4. Redistribution\cf1\b0 . You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\par + +\pard\cbpat4 +{\pntext\f0 1.\tab}{\*\pn\pnlvlbody\pnf0\pnindent360\pnstart1\pndec{\pntxta.}} +\widctlpar\fi-360\li720\sb100\sa100\sl300\slmult0 You must give any other recipients of the Work or Derivative Works a copy of this License; and\par +{\pntext\f0 2.\tab}You must cause any modified files to carry prominent notices stating that You changed the files; and\par +{\pntext\f0 3.\tab}You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\par +{\pntext\f0 4.\tab}If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.\~\line\line You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\par + +\pard\cbpat4\widctlpar\sa150\sl300\slmult0\cf3\b 5. Submission of Contributions\cf1\b0 . Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\par +\cf3\b 6. Trademarks\cf1\b0 . This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\par +\cf3\b 7. Disclaimer of Warranty\cf1\b0 . Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\par +\cf3\b 8. Limitation of Liability\cf1\b0 . In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\par +\cf3\b 9. Accepting Warranty or Additional Liability\cf1\b0 . While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\par +END OF TERMS AND CONDITIONS\par +} + \ No newline at end of file diff --git a/resources/install/doc/License.txt b/resources/install/doc/License.txt deleted file mode 100644 index 5ab7695..0000000 --- a/resources/install/doc/License.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/resources/install/generic/installer-generic.xml b/resources/install/generic/installer-generic.xml index b505ff3..26ee42f 100755 --- a/resources/install/generic/installer-generic.xml +++ b/resources/install/generic/installer-generic.xml @@ -52,7 +52,7 @@ - + diff --git a/resources/install/linux/installer-linux.xml b/resources/install/linux/installer-linux.xml index b24ab49..c4f9dcb 100755 --- a/resources/install/linux/installer-linux.xml +++ b/resources/install/linux/installer-linux.xml @@ -53,7 +53,7 @@ - + -- cgit v1.1 From 5911fa7cdbec990ba01f91bfcd1bcc8efa6eea4d Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 16 May 2016 13:17:11 +0200 Subject: Updates the license headers --- .../extensions/jitsimeet/SSRCInfoPacketExtension.java | 15 +++++++++++++-- .../protocol/event/CallPeerSecurityMessageEvent.java | 15 +++++++++++++-- .../protocol/event/CallPeerSecurityStatusEvent.java | 15 +++++++++++++-- 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java index 239c708..7384c9e 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java @@ -1,8 +1,19 @@ /* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet; diff --git a/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityMessageEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityMessageEvent.java index bcbb66a..92a3f31 100644 --- a/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityMessageEvent.java +++ b/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityMessageEvent.java @@ -1,8 +1,19 @@ /* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package net.java.sip.communicator.service.protocol.event; diff --git a/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityStatusEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityStatusEvent.java index 6720f4b..931998b 100644 --- a/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityStatusEvent.java +++ b/src/net/java/sip/communicator/service/protocol/event/CallPeerSecurityStatusEvent.java @@ -1,8 +1,19 @@ /* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * - * Distributable under LGPL license. - * See terms of license at gnu.org. + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package net.java.sip.communicator.service.protocol.event; -- cgit v1.1 From 7e392977124585eeabe7f732a7445e158c219176 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 16 May 2016 13:17:30 +0200 Subject: Rename SIP Communicator to Jitsi --- resources/install/doc/readme.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/install/doc/readme.txt b/resources/install/doc/readme.txt index 199d6aa..101ade0 100644 --- a/resources/install/doc/readme.txt +++ b/resources/install/doc/readme.txt @@ -1,5 +1,5 @@ -The SIP Communicator is currently under active development. -The version you are running is only experimental and WILL NOT +Jitsi is currently under active development. +The version you are running is only experimental and may not work as expected. Please refer to -http://jitsi.org/ +https://jitsi.org/ for more information. -- cgit v1.1 From 630b2902b2d4f5cbeed40299e58d37c92f8a4fb7 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 16 May 2016 13:17:55 +0200 Subject: Add Jitsi to Windows' default applications list Closes #252 --- resources/install/windows/SCRegistrySpec.wxi | 34 ++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/resources/install/windows/SCRegistrySpec.wxi b/resources/install/windows/SCRegistrySpec.wxi index 72479b2..f891002 100644 --- a/resources/install/windows/SCRegistrySpec.wxi +++ b/resources/install/windows/SCRegistrySpec.wxi @@ -23,11 +23,12 @@ - + Guid="5798BE9D-AEA5-4DA8-992E-EEAD03D7E4CB" + Win64="no"> + - + @@ -114,7 +115,7 @@ + Root="HKLM"> + + + + + + + + + + + + + + + + Root="HKLM"> Date: Thu, 16 Jan 2014 23:51:02 -0500 Subject: Add contact dialog: move group field to bottom The group field is the least import control in this dialog. It should therefore be last. Thanks to David Bolton for suggesting this change. --- .../impl/gui/main/contactlist/AddContactDialog.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index f92fbbe..4860f9d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -176,10 +176,6 @@ public class AddContactDialog this.accountCombo = new JComboBox(); - this.groupLabel = new JLabel( - GuiActivator.getResources().getI18NString( - "service.gui.SELECT_GROUP") + ": "); - this.contactAddressLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.CONTACT_NAME") + ": "); @@ -192,6 +188,10 @@ public class AddContactDialog this.displayNameField = new JTextField(); + this.groupLabel = new JLabel( + GuiActivator.getResources().getI18NString( + "service.gui.SELECT_GROUP") + ": "); + this.addButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.ADD")); @@ -228,15 +228,15 @@ public class AddContactDialog fieldsPanel.add(accountCombo); } - labelsPanel.add(groupLabel); - fieldsPanel.add(groupCombo); - labelsPanel.add(contactAddressLabel); fieldsPanel.add(contactAddressField); labelsPanel.add(displayNameLabel); fieldsPanel.add(displayNameField); + labelsPanel.add(groupLabel); + fieldsPanel.add(groupCombo); + contactAddressField.getDocument().addDocumentListener( new DocumentListener() { -- cgit v1.1 From 8e3ceecef06ab8b8f04946465353096efb954207 Mon Sep 17 00:00:00 2001 From: Tom Kazimiers Date: Wed, 11 Dec 2013 22:49:45 -0500 Subject: Add contact dialog: add tool tips To help users understand the purpose of the various fields of this dialog, tool tips are added by this commit. They provide basic explanation for the primary controls (name, address/number, account and group). Thanks to David Bolton for suggesting the used tool tips text. --- resources/languages/resources.properties | 4 ++++ .../gui/main/contactlist/AddContactDialog.java | 23 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 20b0691..39c5078 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -171,6 +171,7 @@ service.gui.CONNECTION=Connection service.gui.CONNECTION_FAILED_MSG=Connection failed for the following account: User name: {0}, Server name: {1}. Please check your network connection or contact your network administrator for more information. service.gui.CONNECTION_EXPIRED_MSG=You are currently disconnected from the {0} server. service.gui.CONTACT_NAME=ID or Number +service.gui.CONTACT_NAME_INFO=Add either an instant messaging address (such as jane.doe@example.com) or a VoIP number service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=The chosen {0} contact doesn''t support telephony. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=The chosen {0} contact doesn''t support chat conferencing. service.gui.CONTACT_PAUSED_TYPING={0} paused typing the message @@ -204,6 +205,7 @@ service.gui.DESKTOP_SHARING_WARNING=Are you sure you want to start screen sha service.gui.DESKTOP_SHARING_DIALOG_INDICATE=You are sharing your screen service.gui.DIALPAD=Dial Pad service.gui.DISPLAY_NAME=Display name +service.gui.DISPLAY_NAME_INFO=Add a name for this contact. If left blank the IM address or VoIP number will be used. (Optional) service.gui.DISCONNECTED_STATUS=Disconnected service.gui.DND_STATUS=Do not disturb service.gui.DO_NOT_ASK_AGAIN=Don't ask again @@ -509,8 +511,10 @@ service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Click the below button to show all chat ro service.gui.SEARCH_STRING_CONTACT_SOURCE=Searched contact service.gui.SECURITY=Security service.gui.SELECT_ACCOUNT=Select account +service.gui.SELECT_ACCOUNT_INFO=Which account do you want to use to communicate with this contact? service.gui.SELECT_COLOR=Select color service.gui.SELECT_GROUP=Select group +service.gui.SELECT_GROUP_INFO=Which group do you want to display this contact under? (Optional) service.gui.SELECT_GROUP_WIZARD_MSG=The list below contains all groups in your Contact List. Select the one, where you would like to add the new contact. service.gui.SELECT_NO_GROUP=No group service.gui.SELECT_GROUP_WIZARD=Specify group diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index 4860f9d..ffb93ea 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -170,27 +170,49 @@ public class AddContactDialog */ private void init() { + // Get tool tip text for primary controls + final String display_name_info = + GuiActivator.getResources().getI18NString( + "service.gui.DISPLAY_NAME_INFO"); + final String contact_info = + GuiActivator.getResources().getI18NString( + "service.gui.CONTACT_NAME_INFO"); + final String account_info = + GuiActivator.getResources().getI18NString( + "service.gui.SELECT_ACCOUNT_INFO"); + final String group_info = + GuiActivator.getResources().getI18NString( + "service.gui.SELECT_GROUP_INFO"); + + // Initialize controls this.accountLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.SELECT_ACCOUNT") + ": "); + this.accountLabel.setToolTipText(account_info); this.accountCombo = new JComboBox(); + this.accountCombo.setToolTipText(account_info); this.contactAddressLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.CONTACT_NAME") + ": "); + this.contactAddressLabel.setToolTipText(contact_info); this.displayNameLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.DISPLAY_NAME") + ": "); + this.displayNameLabel.setToolTipText(display_name_info); this.contactAddressField = new JTextField(); + this.contactAddressField.setToolTipText(contact_info); this.displayNameField = new JTextField(); + this.displayNameField.setToolTipText(display_name_info); this.groupLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.SELECT_GROUP") + ": "); + this.groupLabel.setToolTipText(group_info); this.addButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.ADD")); @@ -201,6 +223,7 @@ public class AddContactDialog this.imageLabel = new JLabel(); this.groupCombo = createGroupCombo(this); + this.groupCombo.setToolTipText(group_info); if(metaContact != null) { -- cgit v1.1 From 14a19e430d6c37bca2926ae3d1325a86e3d9d6f4 Mon Sep 17 00:00:00 2001 From: Tom Kazimiers Date: Wed, 11 Dec 2013 23:53:29 -0500 Subject: Add contact dialog: support prompts in text fields This commit adds a function which makes it possible to add faint gray prompt to a text field. The foreground color of the prompt's text is the one of the text field, but half transparent. As soon as text is added to the text field, the prompt will vanish and it will re-appear when the text field is emptied again. --- .../gui/main/contactlist/AddContactDialog.java | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index ffb93ea..950bb66 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -24,7 +24,9 @@ import java.util.*; import java.util.List; import javax.swing.*; +import javax.swing.border.*; import javax.swing.event.*; +import javax.swing.text.*; import org.jitsi.util.*; @@ -166,6 +168,47 @@ public class AddContactDialog } /** + * Adds a faint gray prompt to the provided text field that + * will vanish as soon as text is entered into the field. + */ + private void addPrompt(JTextField field, String text) + { + final JLabel prompt = new JLabel(text); + + // Give prompt a foreground color like the original + // text field, but with half transparency. + final Color fg = field.getForeground(); + final Color color = new Color( + fg.getRed(), fg.getGreen(), fg.getBlue(), 128); + + // Mimic properties of given text field + prompt.setFont(field.getFont()); + prompt.setForeground(color); + prompt.setBorder(new EmptyBorder(field.getInsets())); + prompt.setHorizontalAlignment(JLabel.LEADING); + + // Add handler to hide prompt when text is entered + final Document doc = field.getDocument(); + doc.addDocumentListener( new DocumentListener() { + public void insertUpdate(DocumentEvent e) + { + prompt.setVisible(doc.getLength() == 0); + } + + public void removeUpdate(DocumentEvent e) + { + prompt.setVisible(doc.getLength() == 0); + } + + public void changedUpdate(DocumentEvent e) {} + }); + + // Add prompt to text field + field.setLayout( new BorderLayout() ); + field.add(prompt); + } + + /** * Initializes the dialog. */ private void init() -- cgit v1.1 From 683f6c1ed1218fcf3c47328ce5d9ee21bbf6c85c Mon Sep 17 00:00:00 2001 From: Tom Kazimiers Date: Wed, 11 Dec 2013 23:56:54 -0500 Subject: Add contact dialog: have prompts in name and contact fields Having prompts in those two fields gives the user a hint of what (s)he is expected to put into them. This commit will use the example name 'Jane Doe' and the example contact 'jane.doe@example.com' for both fields. The text has a faint gray color and will vanish if the user adds text into the field. --- resources/languages/resources.properties | 2 ++ .../communicator/impl/gui/main/contactlist/AddContactDialog.java | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 39c5078..9eb8a78 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -171,6 +171,7 @@ service.gui.CONNECTION=Connection service.gui.CONNECTION_FAILED_MSG=Connection failed for the following account: User name: {0}, Server name: {1}. Please check your network connection or contact your network administrator for more information. service.gui.CONNECTION_EXPIRED_MSG=You are currently disconnected from the {0} server. service.gui.CONTACT_NAME=ID or Number +service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com service.gui.CONTACT_NAME_INFO=Add either an instant messaging address (such as jane.doe@example.com) or a VoIP number service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=The chosen {0} contact doesn''t support telephony. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=The chosen {0} contact doesn''t support chat conferencing. @@ -205,6 +206,7 @@ service.gui.DESKTOP_SHARING_WARNING=Are you sure you want to start screen sha service.gui.DESKTOP_SHARING_DIALOG_INDICATE=You are sharing your screen service.gui.DIALPAD=Dial Pad service.gui.DISPLAY_NAME=Display name +service.gui.DISPLAY_NAME_PROMPT=Jane Doe service.gui.DISPLAY_NAME_INFO=Add a name for this contact. If left blank the IM address or VoIP number will be used. (Optional) service.gui.DISCONNECTED_STATUS=Disconnected service.gui.DND_STATUS=Do not disturb diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index 950bb66..f8e8515 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -248,9 +248,15 @@ public class AddContactDialog this.contactAddressField = new JTextField(); this.contactAddressField.setToolTipText(contact_info); + addPrompt(this.contactAddressField, + GuiActivator.getResources().getI18NString( + "service.gui.CONTACT_NAME_PROMPT")); this.displayNameField = new JTextField(); this.displayNameField.setToolTipText(display_name_info); + addPrompt(this.displayNameField, + GuiActivator.getResources().getI18NString( + "service.gui.DISPLAY_NAME_PROMPT")); this.groupLabel = new JLabel( GuiActivator.getResources().getI18NString( -- cgit v1.1 From 4aa447582c885b4930c6ea5a8d21cde486f92319 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 17 May 2016 21:40:58 +0200 Subject: Rename tooltips to match codestyle --- .../gui/main/contactlist/AddContactDialog.java | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java index f8e8515..8d43c7f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/AddContactDialog.java @@ -214,16 +214,16 @@ public class AddContactDialog private void init() { // Get tool tip text for primary controls - final String display_name_info = + final String displayNameInfo = GuiActivator.getResources().getI18NString( "service.gui.DISPLAY_NAME_INFO"); - final String contact_info = + final String contactInfo = GuiActivator.getResources().getI18NString( "service.gui.CONTACT_NAME_INFO"); - final String account_info = + final String accountInfo = GuiActivator.getResources().getI18NString( "service.gui.SELECT_ACCOUNT_INFO"); - final String group_info = + final String groupInfo = GuiActivator.getResources().getI18NString( "service.gui.SELECT_GROUP_INFO"); @@ -231,29 +231,29 @@ public class AddContactDialog this.accountLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.SELECT_ACCOUNT") + ": "); - this.accountLabel.setToolTipText(account_info); + this.accountLabel.setToolTipText(accountInfo); this.accountCombo = new JComboBox(); - this.accountCombo.setToolTipText(account_info); + this.accountCombo.setToolTipText(accountInfo); this.contactAddressLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.CONTACT_NAME") + ": "); - this.contactAddressLabel.setToolTipText(contact_info); + this.contactAddressLabel.setToolTipText(contactInfo); this.displayNameLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.DISPLAY_NAME") + ": "); - this.displayNameLabel.setToolTipText(display_name_info); + this.displayNameLabel.setToolTipText(displayNameInfo); this.contactAddressField = new JTextField(); - this.contactAddressField.setToolTipText(contact_info); + this.contactAddressField.setToolTipText(contactInfo); addPrompt(this.contactAddressField, GuiActivator.getResources().getI18NString( "service.gui.CONTACT_NAME_PROMPT")); this.displayNameField = new JTextField(); - this.displayNameField.setToolTipText(display_name_info); + this.displayNameField.setToolTipText(displayNameInfo); addPrompt(this.displayNameField, GuiActivator.getResources().getI18NString( "service.gui.DISPLAY_NAME_PROMPT")); @@ -261,7 +261,7 @@ public class AddContactDialog this.groupLabel = new JLabel( GuiActivator.getResources().getI18NString( "service.gui.SELECT_GROUP") + ": "); - this.groupLabel.setToolTipText(group_info); + this.groupLabel.setToolTipText(groupInfo); this.addButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.ADD")); @@ -272,7 +272,7 @@ public class AddContactDialog this.imageLabel = new JLabel(); this.groupCombo = createGroupCombo(this); - this.groupCombo.setToolTipText(group_info); + this.groupCombo.setToolTipText(groupInfo); if(metaContact != null) { -- cgit v1.1 From 2550b4dc55b6ab3c606a92a07f00b4298f773772 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 17 May 2016 23:38:48 +0200 Subject: Prepare for the message MediaType --- .../sip/communicator/service/protocol/media/CallPeerMediaHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java index b0d62ed..e8d168b 100644 --- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java +++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java @@ -1046,7 +1046,7 @@ public abstract class CallPeerMediaHandler> case VIDEO: return videoStream; default: - throw new IllegalArgumentException("mediaType"); + return null; } } -- cgit v1.1 From 9d4835dca15ea471853165ccccf782b9d11f35db Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 17 May 2016 23:39:35 +0200 Subject: Fix an NPE when adding short SIP contacts --- .../sip/communicator/impl/protocol/sip/ContactSipImpl.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java index 3bd574e..7f30e4f 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java @@ -578,10 +578,15 @@ public class ContactSipImpl */ public static String stripScheme(String from) { - int i = from.substring(0, 5).indexOf(':'); + if (from.startsWith("sip:")) + { + return from.substring(4); + } + else if (from.startsWith("sips:")) + { + return from.substring(5); + } - if(from.startsWith("sip") && i > 0) - return from.substring(i + 1); return from; } -- cgit v1.1 From 9022e8e4f8239b7f1d3369ce7c9c89f5a1f64fcc Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 18 May 2016 00:05:39 +0200 Subject: Add support for Asterisk's based pidf presence Closes #222 --- .../protocol/sip/OperationSetPresenceSipImpl.java | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java index 2fce57e..ef0ec4c 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetPresenceSipImpl.java @@ -2240,6 +2240,40 @@ public class OperationSetPresenceSipImpl updateContactIcon((ContactSipImpl) contact, personStatusIcon); } + // search for a that can define a more precise + // status this is not recommended by RFC3863 but some im + // clients use this. + NodeList presNoteList = getPidfChilds(presence, NOTE_ELEMENT); + if (presNoteList.getLength() >= 1) + { + Node noteNode = presNoteList.item(presNoteList.getLength() - 1); + if (noteNode.getNodeType() == Node.ELEMENT_NODE) + { + String state = getTextContent((Element)noteNode); + if (state != null) + { + switch (state.toLowerCase()) + { + case "ready": + case "available": + personStatus = sipStatusEnum + .getStatus(SipStatusEnum.ONLINE); + break; + case "ringing": + case "on the phone": + case "on hold": + personStatus = sipStatusEnum + .getStatus(SipStatusEnum.ON_THE_PHONE); + break; + case "unavailable": + personStatus = sipStatusEnum + .getStatus(SipStatusEnum.OFFLINE); + break; + } + } + } + } + // Vector containing the list of status to set for each contact in // the presence document ordered by priority (highest first). // -- cgit v1.1 From 4c938c852e66dc22e84136656cadb44fdd31c2e4 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 18 May 2016 23:01:43 +0200 Subject: Update libjitsi jitsi/libjitsi@02e0e35dd2c0ff1644ed4519958fafc48100c2e9 --- lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar | Bin 7800273 -> 8072237 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar index 5f2c62b..fc4fff0 100644 Binary files a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar and b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar differ -- cgit v1.1 From ad61332a3e000d30fd3a2c24d2d3c6f1430f4c46 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 18 May 2016 23:02:33 +0200 Subject: Check for correct capability for showing desktop sharing Closes #186 --- .../impl/gui/main/contactlist/ContactListTreeCellRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java index bfe2fd3..ae0e3b0 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java @@ -1078,7 +1078,7 @@ public class ContactListTreeCellRenderer UIContactDetail desktopContact = uiContact.getDefaultContactDetail( - OperationSetDesktopStreaming.class); + OperationSetDesktopSharingServer.class); if (desktopContact != null || (contactPhoneUtil != null -- cgit v1.1 From 24297d644f5cda26393d0379b6ecd2801a40a198 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 18 May 2016 23:03:19 +0200 Subject: Don't claim features as supported if no info available --- .../protocol/jabber/ProtocolProviderServiceJabberImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 888c0aa..1d08250 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -2417,18 +2417,16 @@ public class ProtocolProviderServiceJabberImpl */ public boolean isFeatureListSupported(String jid, String... features) { - boolean isFeatureListSupported = true; - try { if(discoveryManager == null) - return isFeatureListSupported; + return false; DiscoverInfo featureInfo = discoveryManager.discoverInfoNonBlocking(jid); if(featureInfo == null) - return isFeatureListSupported; + return false; for (String feature : features) { @@ -2436,17 +2434,19 @@ public class ProtocolProviderServiceJabberImpl { // If one is not supported we return false and don't check // the others. - isFeatureListSupported = false; - break; + return false; } } + + return true; } catch (XMPPException e) { if (logger.isDebugEnabled()) logger.debug("Failed to retrive discovery info.", e); } - return isFeatureListSupported; + + return false; } /** -- cgit v1.1 From 3a3bf3158265bf1f8d06d7b30e8a143d499d6a72 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 19 May 2016 14:20:30 +0200 Subject: Rename Jibri "error" status to "failed" --- .../impl/protocol/jabber/extensions/jibri/JibriIq.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index c49774b..53c5c3f 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -83,7 +83,7 @@ public class JibriIq private Action action = Action.UNDEFINED; /** - * XMPPError stores error details for {@link Status#ERROR}. + * XMPPError stores error details for {@link Status#FAILED}. */ private XMPPError error; @@ -239,7 +239,7 @@ public class JibriIq /** * Sets the XMPPError which will provide details about Jibri * failure. It is expected to be set when this IQ's status value is - * {@link Status#ERROR}. + * {@link Status#FAILED}. * * @param error XMPPError to be set on this JibriIq * instance. @@ -251,7 +251,7 @@ public class JibriIq /** * Returns {@link XMPPError} with Jibri error details when the status is - * {@link Status#ERROR}. + * {@link Status#FAILED}. */ public XMPPError getError() { @@ -341,7 +341,7 @@ public class JibriIq /** * An error occurred any point during startup, recording or shutdown. */ - ERROR("error"), + FAILED("failed"), /** * There are Jibri instances connected to the system, but all of them -- cgit v1.1 From 1afb3d652955b469722a0c9ab960f8cd458e0321 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 18:11:09 +0200 Subject: Update dnsjava to stock 2.1.7 and make sure it is only loaded once --- .classpath | 3 +- build.xml | 2 +- lib/felix.client.run.properties | 55 +++++++++++---------- lib/installer-exclude/dnsjava-2.1.7.jar | Bin 0 -> 310044 bytes lib/installer-exclude/dnsjava.jar | Bin 308076 -> 0 bytes resources/install/debian/jitsi.sh.tmpl | 2 +- resources/install/linux/run.sh | 2 +- resources/install/rpm/SPECS/jitsi.spec | 1 + src/native/windows/run/run.c | 1 + .../java/sip/communicator/util/util.manifest.mf | 3 +- 10 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 lib/installer-exclude/dnsjava-2.1.7.jar delete mode 100644 lib/installer-exclude/dnsjava.jar diff --git a/.classpath b/.classpath index 194ed36..62e52bd 100755 --- a/.classpath +++ b/.classpath @@ -14,7 +14,7 @@ - + @@ -88,5 +88,6 @@ + diff --git a/build.xml b/build.xml index 94db76c..6594491 100644 --- a/build.xml +++ b/build.xml @@ -1127,6 +1127,7 @@ + @@ -1250,7 +1251,6 @@ - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 15e34f2..ffe19a4 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -2,32 +2,35 @@ # Framework config properties. # org.osgi.framework.system.packages.extra= \ - apple.awt; \ - com.apple.cocoa.application; \ - com.apple.cocoa.foundation; \ - com.apple.eawt; \ - com.apple.eio; \ - com.sun.awt; \ - net.java.sip.communicator.util.launchutils; \ - org.apache.xml.serialize; \ - org.growl4j; \ - org.xbill.DNS; \ - quicktime; \ - quicktime.qd; \ - quicktime.std.image; \ - quicktime.std.sg; \ - quicktime.util; \ - sun.awt.shell; \ - sun.lwawt; \ - sun.lwawt.macosx; \ - sun.misc; \ - sun.net.util; \ - sun.net.dns; \ - sun.security.action; \ - sun.security.pkcs11;\ - sun.audio;\ - sun.nio.ch;\ - com.sun.nio.sctp + apple.awt, \ + com.apple.cocoa.application, \ + com.apple.cocoa.foundation, \ + com.apple.eawt, \ + com.apple.eio, \ + com.sun.awt, \ + net.java.sip.communicator.util.launchutils, \ + org.apache.xml.serialize, \ + org.growl4j, \ + org.xbill.DNS;version="2.1.7", \ + org.xbill.DNS.utils;version="2.1.7", \ + quicktime, \ + quicktime.qd, \ + quicktime.std.image, \ + quicktime.std.sg, \ + quicktime.util, \ + sun.awt.shell, \ + sun.lwawt, \ + sun.lwawt.macosx, \ + sun.misc, \ + sun.net.util, \ + sun.net.dns, \ + sun.security.action, \ + sun.security.pkcs11,\ + sun.audio,\ + sun.nio.ch,\ + com.sun.nio.sctp, \ + android.os, \ + sun.net.spi.nameservice felix.auto.start.5=reference:file:sc-bundles/splash-screen.jar diff --git a/lib/installer-exclude/dnsjava-2.1.7.jar b/lib/installer-exclude/dnsjava-2.1.7.jar new file mode 100644 index 0000000..6e85e30 Binary files /dev/null and b/lib/installer-exclude/dnsjava-2.1.7.jar differ diff --git a/lib/installer-exclude/dnsjava.jar b/lib/installer-exclude/dnsjava.jar deleted file mode 100644 index 8158168..0000000 Binary files a/lib/installer-exclude/dnsjava.jar and /dev/null differ diff --git a/resources/install/debian/jitsi.sh.tmpl b/resources/install/debian/jitsi.sh.tmpl index de159db..7963135 100644 --- a/resources/install/debian/jitsi.sh.tmpl +++ b/resources/install/debian/jitsi.sh.tmpl @@ -30,7 +30,7 @@ javabin=`which java` SCDIR=/usr/share/_PACKAGE_NAME_ JITSI_COMMON_DIR=/usr/share/_PACKAGE_NAME_-common LIBPATH=$SCDIR/lib -CLASSPATH=/usr/share/java/org.apache.felix.framework.jar:/usr/share/java/org.apache.felix.main.jar:$SCDIR/sc-bundles/sc-launcher.jar:$JITSI_COMMON_DIR/util.jar/launchutils.jar:$LIBPATH +CLASSPATH=/usr/share/java/org.apache.felix.framework.jar:/usr/share/java/org.apache.felix.main.jar:/usr/share/java/dnsjava.jar:$SCDIR/sc-bundles/sc-launcher.jar:$JITSI_COMMON_DIR/util.jar/launchutils.jar:$LIBPATH FELIX_CONFIG=$LIBPATH/felix.client.run.properties LOG_CONFIG=$LIBPATH/logging.properties COMMAND="$javabin $CLIENTARGS -classpath $CLASSPATH -Djna.library.path=/usr/lib/jni -Dfelix.config.properties=file:$FELIX_CONFIG -Djava.util.logging.config.file=$LOG_CONFIG $SPLASH_ARG net.java.sip.communicator.launcher.SIPCommunicator" diff --git a/resources/install/linux/run.sh b/resources/install/linux/run.sh index ef3e9ff..bd74b1a 100755 --- a/resources/install/linux/run.sh +++ b/resources/install/linux/run.sh @@ -2,4 +2,4 @@ mkdir -p $HOME/.sip-communicator/log export PATH=$PATH:native export JAVA_HOME=jre -${JAVA_HOME}/bin/java -classpath "lib/felix.jar:sc-bundles/sc-launcher.jar:sc-bundles/util.jar:lib/" -Djna.library.path=native -Djava.library.path=native -Dfelix.config.properties=file:./lib/felix.client.run.properties -Djava.util.logging.config.file=lib/logging.properties net.java.sip.communicator.launcher.SIPCommunicator +${JAVA_HOME}/bin/java -classpath "lib/felix.jar:sc-bundles/sc-launcher.jar:sc-bundles/dnsjava.jar:sc-bundles/util.jar:lib/" -Djna.library.path=native -Djava.library.path=native -Dfelix.config.properties=file:./lib/felix.client.run.properties -Djava.util.logging.config.file=lib/logging.properties net.java.sip.communicator.launcher.SIPCommunicator diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index 0998303..32bc811 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -113,6 +113,7 @@ sed -i -e "s/\/usr\/lib\/jni/\$LIBPATH\/native/" $RPM_BUILD_ROOT/usr/bin/jitsi sed -i -e "s/\/usr\/share\/java\/jdic\.jar/\$LIBPATH\/jdic_stub\.jar:\$LIBPATH\/jdic-all\.jar/" $RPM_BUILD_ROOT/usr/bin/jitsi sed -i -e "s/\/usr\/share\/java\/org\.apache\.felix\.framework\.jar/\$LIBPATH\/felix\.jar/" $RPM_BUILD_ROOT/usr/bin/jitsi sed -i -e "s/\/usr\/share\/java\/org\.apache\.felix\.main\.jar://" $RPM_BUILD_ROOT/usr/bin/jitsi +sed -i -e "s/\/usr\/share\/java\/dnsjava\.jar://" $RPM_BUILD_ROOT/usr/bin/jitsi sed -i -e "s/\/launchutils.jar//" $RPM_BUILD_ROOT/usr/bin/jitsi %clean diff --git a/src/native/windows/run/run.c b/src/native/windows/run/run.c index 7f152e9..4bae363 100644 --- a/src/native/windows/run/run.c +++ b/src/native/windows/run/run.c @@ -525,6 +525,7 @@ Run_getJavaVMOptionStrings = { _T("lib\\felix.jar"), _T("sc-bundles\\sc-launcher.jar"), + _T("sc-bundles\\dnsjava.jar"), _T("sc-bundles\\util.jar"), _T("lib"), NULL diff --git a/src/net/java/sip/communicator/util/util.manifest.mf b/src/net/java/sip/communicator/util/util.manifest.mf index 7de9af7..a6e4db7 100644 --- a/src/net/java/sip/communicator/util/util.manifest.mf +++ b/src/net/java/sip/communicator/util/util.manifest.mf @@ -56,8 +56,7 @@ Import-Package: com.sun.awt, sun.awt.shell, sun.net.dns, sun.net.util -Export-Package: org.xbill.DNS, - net.java.sip.communicator.util, +Export-Package: net.java.sip.communicator.util, net.java.sip.communicator.util.launchutils, net.java.sip.communicator.util.skin, net.java.sip.communicator.util.xml, -- cgit v1.1 From 8402bc0643b3a137f676899ba35b5263041ea885 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 20:45:30 +0200 Subject: Use dnssecjava instead of unbound for dnssec validation --- build.xml | 1 + lib/felix.client.run.properties | 3 +- lib/installer-exclude/dnssecjava-1.1.jar | Bin 0 -> 53599 bytes .../impl/dns/ConfigurableDnssecResolver.java | 109 ++++++++++++++++++--- .../communicator/impl/dns/DnsUtilActivator.java | 2 +- .../sip/communicator/impl/dns/SecureMessage.java | 17 +++- .../java/sip/communicator/impl/dns/dns.manifest.mf | 2 + .../communicator/plugin/dnsconfig/DnssecPanel.java | 2 +- 8 files changed, 113 insertions(+), 23 deletions(-) create mode 100644 lib/installer-exclude/dnssecjava-1.1.jar diff --git a/build.xml b/build.xml index 6594491..7df3735 100644 --- a/build.xml +++ b/build.xml @@ -1128,6 +1128,7 @@ + diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index ffe19a4..c596e49 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -48,7 +48,8 @@ felix.auto.start.10= \ reference:file:sc-bundles/commons-lang.jar \ reference:file:sc-bundles/guava.jar \ reference:file:sc-bundles/slf4j-api.jar \ - reference:file:sc-bundles/weupnp.jar + reference:file:sc-bundles/weupnp.jar \ + reference:file:sc-bundles/dnssecjava.jar felix.auto.start.11= \ reference:file:sc-bundles/sip-api.jar \ diff --git a/lib/installer-exclude/dnssecjava-1.1.jar b/lib/installer-exclude/dnssecjava-1.1.jar new file mode 100644 index 0000000..57ad85a Binary files /dev/null and b/lib/installer-exclude/dnssecjava-1.1.jar differ diff --git a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java index 93bc71e..5668de2 100644 --- a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java +++ b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java @@ -19,7 +19,10 @@ package net.java.sip.communicator.impl.dns; import java.awt.*; import java.awt.event.*; +import java.io.*; +import java.net.*; import java.util.*; +import java.util.List; import javax.swing.*; @@ -28,6 +31,7 @@ import net.java.sip.communicator.service.notification.*; import net.java.sip.communicator.util.Logger; import net.java.sip.communicator.plugin.desktoputil.*; +import org.jitsi.dnssec.validator.ValidatingResolver; import org.jitsi.service.configuration.*; import org.jitsi.service.resources.*; import org.jitsi.util.*; @@ -40,7 +44,9 @@ import org.xbill.DNS.*; * @author Ingo Bauersachs */ public class ConfigurableDnssecResolver - extends UnboundResolver + //extends UnboundResolver + extends ValidatingResolver + implements CustomResolver { private final static Logger logger = Logger.getLogger(ConfigurableDnssecResolver.class); @@ -67,13 +73,38 @@ public class ConfigurableDnssecResolver private Map lastNotifications = new HashMap(); + private ExtendedResolver headResolver; + /** * Creates a new instance of this class. Tries to use the system's * default forwarders. */ - public ConfigurableDnssecResolver() + public ConfigurableDnssecResolver(ExtendedResolver headResolver) { - super(); + super(headResolver); + + List propNames + = config.getPropertyNamesByPrefix("org.jitsi.dnssec", false); + Properties config = new Properties(); + for (String propName : propNames) + { + String value = config.getProperty(propName); + if (!StringUtils.isNullOrEmpty(value)) + { + config.put(propName, value); + } + } + + try + { + super.init(config); + } + catch (IOException e) + { + logger.error("Extended dnssec properties contained an error", e); + } + + this.headResolver = headResolver; reset(); Lookup.setDefaultResolver(this); @@ -92,8 +123,8 @@ public class ConfigurableDnssecResolver * did not choose to ignore it. */ @Override - protected void validateMessage(SecureMessage msg) - throws DnssecRuntimeException + public Message send(Message query) + throws DnssecRuntimeException, IOException { //--------------------------------------------------------------------- // || 1 | 2 | 3 | 4 | 5 @@ -105,6 +136,7 @@ public class ConfigurableDnssecResolver //c) 0 | 0 || ok | nok | ok | ok | ask //--------------------------------------------------------------------- + SecureMessage msg = new SecureMessage(super.send(query)); String fqdn = msg.getQuestion().getName().toString(); String type = Type.string(msg.getQuestion().getType()); String propName = createPropNameUnsigned(fqdn, type); @@ -129,7 +161,7 @@ public class ConfigurableDnssecResolver //[abc]1, a[2-5] if(pinned == SecureResolveMode.IgnoreDnssec || msg.isSecure()) - return; + return msg; if( //b2, c2 @@ -152,16 +184,17 @@ public class ConfigurableDnssecResolver null); lastNotifications.put(text, new Date()); } + throw new DnssecRuntimeException(text); } //c3 if(pinned == SecureResolveMode.SecureOrUnsigned && !msg.isBogus()) - return; + return msg; //c4 if(pinned == SecureResolveMode.WarnIfBogus && !msg.isBogus()) - return; + return msg; //b4, b5, c5 String reason = msg.isBogus() @@ -190,6 +223,8 @@ public class ConfigurableDnssecResolver config.setProperty(propName, SecureResolveMode.SecureOnly); throw new DnssecRuntimeException(getExceptionMessage(msg)); } + + return msg; } /** @@ -372,22 +407,66 @@ public class ConfigurableDnssecResolver { if(logger.isTraceEnabled()) { - logger.trace("Setting DNSSEC forwarders to: " - + Arrays.toString(forwarders.split(","))); + logger.trace("Setting DNSSEC forwarders to: " + forwarders); + } + + synchronized (Lookup.class) + { + Lookup.refreshDefault(); + String[] fwds = forwarders.split(","); + Resolver[] rs = headResolver.getResolvers(); + for (Resolver r : rs) + { + headResolver.deleteResolver(r); + } + + for (String fwd : fwds) + { + try + { + SimpleResolver sr = new SimpleResolver(fwd); + + // these properties are normally set by the + // ValidatingResolver in the constructor + sr.setEDNS(0, 0, ExtendedFlags.DO, null); + sr.setIgnoreTruncation(false); + headResolver.addResolver(sr); + } + catch (UnknownHostException e) + { + logger.error("Invalid forwarder, ignoring", e); + } + } + + Lookup.setDefaultResolver(this); } - super.setForwarders(forwarders.split(",")); } + StringBuilder sb = new StringBuilder(); for(int i = 1;;i++) { String anchor = DnsUtilActivator.getResources().getSettingsString( "net.java.sip.communicator.util.dns.DS_ROOT." + i); if(anchor == null) + { break; - clearTrustAnchors(); - addTrustAnchor(anchor); - if(logger.isTraceEnabled()) - logger.trace("Loaded trust anchor " + anchor); + } + + sb.append(anchor); + sb.append('\n'); } + + try + { + super.loadTrustAnchors(new ByteArrayInputStream( + sb.toString().getBytes("ASCII"))); + } + catch (IOException e) + { + logger.error("Could not load the trust anchors", e); + } + + if(logger.isTraceEnabled()) + logger.trace("Loaded trust anchors " + sb.toString()); } } diff --git a/src/net/java/sip/communicator/impl/dns/DnsUtilActivator.java b/src/net/java/sip/communicator/impl/dns/DnsUtilActivator.java index e8b2e7d..4fc828c 100644 --- a/src/net/java/sip/communicator/impl/dns/DnsUtilActivator.java +++ b/src/net/java/sip/communicator/impl/dns/DnsUtilActivator.java @@ -150,7 +150,7 @@ public class DnsUtilActivator { bundleContext.registerService( CustomResolver.class.getName(), - new ConfigurableDnssecResolver(), + new ConfigurableDnssecResolver(new ExtendedResolver()), null); logger.info("DnssecResolver ... [REGISTERED]"); } diff --git a/src/net/java/sip/communicator/impl/dns/SecureMessage.java b/src/net/java/sip/communicator/impl/dns/SecureMessage.java index b2fa0d4..b03c340 100644 --- a/src/net/java/sip/communicator/impl/dns/SecureMessage.java +++ b/src/net/java/sip/communicator/impl/dns/SecureMessage.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.dns; import java.io.*; +import org.jitsi.dnssec.validator.*; import org.xbill.DNS.*; /** @@ -40,12 +41,18 @@ public class SecureMessage * @param msg The answer of the Unbound resolver. * @throws IOException */ - public SecureMessage(UnboundResult msg) throws IOException + public SecureMessage(Message msg) throws IOException { - super(msg.answerPacket); - secure = msg.secure; - bogus = msg.bogus; - bogusReason = msg.whyBogus; + super(msg.toWire()); + secure = msg.getHeader().getFlag(Flags.AD); + bogus = !secure && msg.getRcode() == Rcode.SERVFAIL; + for (RRset set : msg.getSectionRRsets(Section.ADDITIONAL)) { + if (set.getName().equals(Name.root) && set.getType() == Type.TXT + && set.getDClass() == ValidatingResolver.VALIDATION_REASON_QCLASS) + { + bogusReason = ((TXTRecord)set.first()).getStrings().get(0).toString(); + } + } } /** diff --git a/src/net/java/sip/communicator/impl/dns/dns.manifest.mf b/src/net/java/sip/communicator/impl/dns/dns.manifest.mf index 331eba1..33174b5 100644 --- a/src/net/java/sip/communicator/impl/dns/dns.manifest.mf +++ b/src/net/java/sip/communicator/impl/dns/dns.manifest.mf @@ -8,6 +8,8 @@ Import-Package: org.jitsi.util, org.osgi.framework, net.java.sip.communicator.util, net.java.sip.communicator.plugin.desktoputil, + org.jitsi.dnssec, + org.jitsi.dnssec.validator, org.jitsi.service.resources, org.jitsi.service.fileaccess, net.java.sip.communicator.service.resources, diff --git a/src/net/java/sip/communicator/plugin/dnsconfig/DnssecPanel.java b/src/net/java/sip/communicator/plugin/dnsconfig/DnssecPanel.java index 0500c07..27bf565 100644 --- a/src/net/java/sip/communicator/plugin/dnsconfig/DnssecPanel.java +++ b/src/net/java/sip/communicator/plugin/dnsconfig/DnssecPanel.java @@ -267,7 +267,7 @@ public class DnssecPanel if(chkEnabled.isSelected()) { if(!f.createNewFile() && !f.exists()) - chkEnabled.setSelected(UnboundApi.isAvailable()); + chkEnabled.setSelected(false); } else { -- cgit v1.1 From f9c01af00ba28550324b27769cb901e222b8c2cf Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 20:51:24 +0200 Subject: Catch lookup outside of NetworkUtils --- build.xml | 4 + .../sip/communicator/launcher/SIPCommunicator.java | 2 +- .../sip/communicator/util/JitsiDnsNameService.java | 151 +++++++++++++++++++++ .../util/JitsiDnsNameServiceDescriptor.java | 58 ++++++++ .../sun.net.spi.nameservice.NameServiceDescriptor | 1 + 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 src/net/java/sip/communicator/util/JitsiDnsNameService.java create mode 100644 src/net/java/sip/communicator/util/JitsiDnsNameServiceDescriptor.java create mode 100644 src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor diff --git a/build.xml b/build.xml index 7df3735..48a0aa5 100644 --- a/build.xml +++ b/build.xml @@ -1252,6 +1252,10 @@ + diff --git a/src/net/java/sip/communicator/launcher/SIPCommunicator.java b/src/net/java/sip/communicator/launcher/SIPCommunicator.java index 0fccc20..fee1e40 100644 --- a/src/net/java/sip/communicator/launcher/SIPCommunicator.java +++ b/src/net/java/sip/communicator/launcher/SIPCommunicator.java @@ -118,7 +118,7 @@ public class SIPCommunicator { System.setProperty( "sun.net.spi.nameservice.provider.1", - "dns,dnsjava"); + "dns,jitsi"); } if (version.startsWith("1.5") || vmVendor.startsWith("Gnu") || diff --git a/src/net/java/sip/communicator/util/JitsiDnsNameService.java b/src/net/java/sip/communicator/util/JitsiDnsNameService.java new file mode 100644 index 0000000..cf68ad5 --- /dev/null +++ b/src/net/java/sip/communicator/util/JitsiDnsNameService.java @@ -0,0 +1,151 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.util; + +import java.lang.reflect.Method; +import java.net.*; + +import org.xbill.DNS.*; + +import sun.net.spi.nameservice.*; + +/** + * JNDI DNS service to send DNS lookup through the dnsjava Lookup + * infrastructure. This is needed to catch lookups that are not made + * through the DNSSEC-aware NetworkUtils. + * + * @author Ingo Bauersachs + */ +public class JitsiDnsNameService + implements NameService +{ + private static boolean v6first; + private static Name localhostName = null; + private static InetAddress[] localhostAddresses = null; + private static InetAddress[] localhostNamedAddresses = null; + private static boolean addressesLoaded = false; + + static + { + v6first = Boolean.getBoolean("java.net.preferIPv6Addresses"); + try + { + // retrieve the name from the system that is used as localhost + Class inClass = Class.forName("java.net.InetAddressImplFactory"); + Method create = inClass.getDeclaredMethod("create"); + create.setAccessible(true); + + Object impl = create.invoke(null); + Class clazz = Class.forName("java.net.InetAddressImpl"); + Method hostname = clazz.getMethod("getLocalHostName"); + hostname.setAccessible(true); + localhostName = new Name((String) hostname.invoke(impl)); + Method lookup = clazz.getMethod("lookupAllHostAddr", String.class); + lookup.setAccessible(true); + + localhostNamedAddresses = (InetAddress[])lookup.invoke(impl, + localhostName.toString()); + localhostAddresses = (InetAddress[])lookup.invoke(impl, + "localhost"); + + addressesLoaded = true; + } + catch (Exception e) + { + System.err.println("Could not obtain localhost: " + e); + } + } + + @Override + public String getHostByAddr(final byte[] bytes) + throws UnknownHostException + { + InetAddress addr = InetAddress.getByAddress(bytes); + if (addr.isLoopbackAddress()) + { + return "localhost"; + } + + Name name = ReverseMap.fromAddress(addr); + Lookup l = new Lookup(name, Type.PTR); + Record[] records = l.run(); + if (records == null) + { + throw new UnknownHostException(); + } + + return ((PTRRecord) records[0]).getTarget().toString(); + } + + @Override + public InetAddress[] lookupAllHostAddr(final String host) + throws UnknownHostException + { + Name n; + try + { + n = new Name(host); + // Avoid sending queries to a nameserver for localhost + // and the machine's hostname. Unless in an enterprise environment + // the nameserver wouldn't know about that machine name anyway. + if (addressesLoaded) + { + if (n.equals(localhostName)) + { + return localhostNamedAddresses; + } + else if (host.equals("localhost")) + { + return localhostAddresses; + } + } + } + catch (TextParseException e) + { + throw new UnknownHostException(host); + } + + Lookup l = new Lookup(n, v6first ? Type.AAAA : Type.A); + Record[] r = l.run(); + if (r == null || r.length == 0) + { + l = new Lookup(n, v6first ? Type.A : Type.AAAA); + r = l.run(); + } + + if (r == null || r.length == 0) + { + throw new UnknownHostException(host); + } + + InetAddress[] results = new InetAddress[r.length]; + for (int i = 0; i < r.length; i++) + { + if (r[i] instanceof AAAARecord) + { + results[i] = ((AAAARecord) r[i]).getAddress(); + } + else if (r[i] instanceof ARecord) + { + results[i] = ((ARecord) r[i]).getAddress(); + } + } + + return results; + } +} diff --git a/src/net/java/sip/communicator/util/JitsiDnsNameServiceDescriptor.java b/src/net/java/sip/communicator/util/JitsiDnsNameServiceDescriptor.java new file mode 100644 index 0000000..559646a --- /dev/null +++ b/src/net/java/sip/communicator/util/JitsiDnsNameServiceDescriptor.java @@ -0,0 +1,58 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2016 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.util; + +import sun.net.spi.nameservice.*; + +/** + * A name service descriptor for Jitsi's DNS service. It is instantiated by the + * JRE when DNSSEC is enabled in Jitsi's options. + * + * @author Ingo Bauersachs + */ +public class JitsiDnsNameServiceDescriptor + implements NameServiceDescriptor +{ + /** + * Gets and creates an instance of the Jitsi's name service. + * + * @return an instance of the Jitsi's name service. + */ + public NameService createNameService() + { + return new JitsiDnsNameService(); + } + + /** + * Gets the type of this name service. + * @return the string dns + */ + public String getType() + { + return "dns"; + } + + /** + * Gets the name of this name service. + * @return the string jitsi + */ + public String getProviderName() + { + return "jitsi"; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor b/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor new file mode 100644 index 0000000..ecdbbf2 --- /dev/null +++ b/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor @@ -0,0 +1 @@ +net.java.sip.communicator.util.JitsiDnsNameServiceDescriptor -- cgit v1.1 From 91ce10758cd2ebbad5a2e041609dc46d48495964 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 21:04:09 +0200 Subject: Remove libunbound and related code --- lib/native/linux-64/libjunbound.so | Bin 794320 -> 0 bytes lib/native/linux/libjunbound.so | Bin 785008 -> 0 bytes lib/native/mac/libjunbound.jnilib | Bin 1827792 -> 0 bytes lib/native/windows-64/junbound.dll | Bin 1856000 -> 0 bytes lib/native/windows/junbound.dll | Bin 1850382 -> 0 bytes resources/install/build.xml | 3 +- resources/install/debian/control-src.tmpl | 1 - resources/install/debian/control.tmpl | 1 - src/native/build.xml | 28 -- src/native/libjunbound/Makefile.am | 2 - src/native/libjunbound/configure.ac | 69 --- src/native/libjunbound/make-linux.sh | 35 -- src/native/libjunbound/make-mac.sh | 76 --- src/native/libjunbound/makefile.linux | 16 - src/native/libjunbound/makefile.w32 | 25 - src/native/libjunbound/makefile.w64 | 26 - src/native/libjunbound/readme.txt | 40 -- src/native/libjunbound/src/Makefile.am | 3 - ...t_java_sip_communicator_impl_dns_UnboundApi.cpp | 284 ----------- ...net_java_sip_communicator_impl_dns_UnboundApi.h | 94 ---- ...municator_impl_dns_UnboundApi_UnboundCallback.h | 13 - src/native/libjunbound/unbound.patch | 54 --- src/native/libjunbound/windows32/libcrypto.a | Bin 2674964 -> 0 bytes src/native/libjunbound/windows32/libldns.a | Bin 1148054 -> 0 bytes src/native/libjunbound/windows32/libunbound.a | Bin 2184240 -> 0 bytes src/native/libjunbound/windows32/unbound.h | 534 --------------------- src/native/libjunbound/windows64/libcrypto.a | Bin 2891370 -> 0 bytes src/native/libjunbound/windows64/libldns.a | Bin 1470734 -> 0 bytes src/native/libjunbound/windows64/libunbound.a | Bin 6585198 -> 0 bytes src/native/libjunbound/windows64/unbound.h | 534 --------------------- .../impl/dns/ConfigurableDnssecResolver.java | 1 - .../sip/communicator/impl/dns/SecureMessage.java | 6 +- .../java/sip/communicator/impl/dns/UnboundApi.java | 239 --------- .../communicator/impl/dns/UnboundException.java | 42 -- .../sip/communicator/impl/dns/UnboundResolver.java | 410 ---------------- .../sip/communicator/impl/dns/UnboundResult.java | 128 ----- 36 files changed, 4 insertions(+), 2660 deletions(-) delete mode 100644 lib/native/linux-64/libjunbound.so delete mode 100644 lib/native/linux/libjunbound.so delete mode 100644 lib/native/mac/libjunbound.jnilib delete mode 100644 lib/native/windows-64/junbound.dll delete mode 100644 lib/native/windows/junbound.dll delete mode 100644 src/native/libjunbound/Makefile.am delete mode 100644 src/native/libjunbound/configure.ac delete mode 100644 src/native/libjunbound/make-linux.sh delete mode 100644 src/native/libjunbound/make-mac.sh delete mode 100644 src/native/libjunbound/makefile.linux delete mode 100644 src/native/libjunbound/makefile.w32 delete mode 100644 src/native/libjunbound/makefile.w64 delete mode 100644 src/native/libjunbound/readme.txt delete mode 100644 src/native/libjunbound/src/Makefile.am delete mode 100644 src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.cpp delete mode 100644 src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.h delete mode 100644 src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback.h delete mode 100644 src/native/libjunbound/unbound.patch delete mode 100644 src/native/libjunbound/windows32/libcrypto.a delete mode 100644 src/native/libjunbound/windows32/libldns.a delete mode 100644 src/native/libjunbound/windows32/libunbound.a delete mode 100644 src/native/libjunbound/windows32/unbound.h delete mode 100644 src/native/libjunbound/windows64/libcrypto.a delete mode 100644 src/native/libjunbound/windows64/libldns.a delete mode 100644 src/native/libjunbound/windows64/libunbound.a delete mode 100644 src/native/libjunbound/windows64/unbound.h delete mode 100644 src/net/java/sip/communicator/impl/dns/UnboundApi.java delete mode 100644 src/net/java/sip/communicator/impl/dns/UnboundException.java delete mode 100644 src/net/java/sip/communicator/impl/dns/UnboundResolver.java delete mode 100644 src/net/java/sip/communicator/impl/dns/UnboundResult.java diff --git a/lib/native/linux-64/libjunbound.so b/lib/native/linux-64/libjunbound.so deleted file mode 100644 index 323403b..0000000 Binary files a/lib/native/linux-64/libjunbound.so and /dev/null differ diff --git a/lib/native/linux/libjunbound.so b/lib/native/linux/libjunbound.so deleted file mode 100644 index 274d9dd..0000000 Binary files a/lib/native/linux/libjunbound.so and /dev/null differ diff --git a/lib/native/mac/libjunbound.jnilib b/lib/native/mac/libjunbound.jnilib deleted file mode 100644 index fcc1428..0000000 Binary files a/lib/native/mac/libjunbound.jnilib and /dev/null differ diff --git a/lib/native/windows-64/junbound.dll b/lib/native/windows-64/junbound.dll deleted file mode 100644 index 0a27298..0000000 Binary files a/lib/native/windows-64/junbound.dll and /dev/null differ diff --git a/lib/native/windows/junbound.dll b/lib/native/windows/junbound.dll deleted file mode 100644 index b1b8da8..0000000 Binary files a/lib/native/windows/junbound.dll and /dev/null differ diff --git a/resources/install/build.xml b/resources/install/build.xml index d00b397..c0b11d3 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -2407,7 +2407,7 @@ and libjdic.so to deb and i386 package fail to build --> + value="override_dh_shlibdeps: dh_shlibdeps -Xlibsysactivitynotifications.so get-orig-source:"/> - diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index fdf1456..cc5f976 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -42,7 +42,6 @@ Build-Depends: debhelper (>= 9), javahelper, libxtst-dev, libxv-dev, libdbus-1-dev, - libunbound-dev, libxss-dev, libgtk2.0-dev, libglib2.0-dev, diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index f717416..33afd3c 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -48,7 +48,6 @@ Build-Depends: debhelper (>= 9), javahelper, libasound2-dev, libspeexdsp-dev, libspeex-dev, - libunbound-dev, libxss-dev, libgtk2.0-dev, libglib2.0-dev, diff --git a/src/native/build.xml b/src/native/build.xml index 90c0704..8cdbc58 100644 --- a/src/native/build.xml +++ b/src/native/build.xml @@ -533,34 +533,6 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/src/native/libjunbound/Makefile.am b/src/native/libjunbound/Makefile.am deleted file mode 100644 index 0182df2..0000000 --- a/src/native/libjunbound/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -SUBDIRS = src -ACLOCAL_AMFLAGS = -I m4 diff --git a/src/native/libjunbound/configure.ac b/src/native/libjunbound/configure.ac deleted file mode 100644 index ddab6c3..0000000 --- a/src/native/libjunbound/configure.ac +++ /dev/null @@ -1,69 +0,0 @@ -# Prelude. -AC_INIT([junbound], [1.0], [dev@jitsi.java.net]) -AM_INIT_AUTOMAKE([foreign -Wall -Werror]) -AC_CONFIG_MACRO_DIR([m4]) -LT_INIT - -# Checks for programs. -AC_PROG_CXX -# Checks for libraries. - -AC_CHECK_LIB([unbound], [ub_ctx_create], [], [AC_MSG_ERROR([libunbound not found (is libunbound-dev installed?)])]) - -# Checks for header files. -AC_MSG_CHECKING(for java include file jni.h) -AC_ARG_WITH(javaincl, [ --with-javaincl=path Set location of Java include directory], [JAVAINCDIR="$withval"], [JAVAINCDIR=]) - -if test -z "$JAVAINCDIR" ; then - JAVAINCDIR="/usr/j2sdk*/include /usr/local/j2sdk*/include /usr/jdk*/include /usr/local/jdk*/include /opt/j2sdk*/include /opt/jdk*/include /usr/java/include /usr/java/j2sdk*/include /usr/java/jdk*/include /usr/local/java/include /opt/java/include /usr/include/java /usr/local/include/java /usr/lib/java/include /usr/lib/jvm/java*/include /usr/include/kaffe /usr/local/include/kaffe /usr/include" - - # Add in default installation directory on Windows for Cygwin - case $host in - *-*-cygwin* | *-*-mingw*) JAVAINCDIR="c:/Program*Files/Java/jdk*/include d:/Program*Files/Java/jdk*/include c:/j2sdk*/include d:/j2sdk*/include c:/jdk*/include d:/jdk*/include $JAVAINCDIR";; - *-*-darwin*) JAVAINCDIR="/System/Library/Frameworks/JavaVM.framework/Headers $JAVAINCDIR";; - *);; - esac -fi - -if test -z "$JAVA_HOME" ; then - JAVA_HOME=":" # Something completely invalid -fi -VS_JNI_INCLUDE="" -for d in "$JAVA_HOME/include" $JAVAINCDIR ; do - if test -r "$d/jni.h" ; then - AC_MSG_RESULT($d) - JAVAINCDIR=$d - VS_JNI_INCLUDE=-I\"$d\" #" quote here to fix nasty formatting bug in VIM - break - fi -done - -if test "$VS_JNI_INCLUDE" = "" ; then - AC_MSG_RESULT(not found) - AC_MSG_FAILURE([Could not find required Java header file jni.h. - Try defining JAVA_HOME to point to where you've - installed the JAVA JDK]) -else - # now look for /jni_md.h - AC_MSG_CHECKING(for java include file jni_md.h) - JAVAMDDIR=`find "$JAVAINCDIR" -follow -name jni_md.h -print` - if test "$JAVAMDDIR" = "" ; then - AC_MSG_RESULT(not found) - AC_MSG_FAILURE([Could not find required Java header file jni_md.h. - Try defining JAVA_HOME to point to where you've - installed the JAVA JDK]) - else - JAVAMDDIR=`dirname "$JAVAMDDIR" | tail -1` - VS_JNI_INCLUDE="${VS_JNI_INCLUDE} -I\"$JAVAMDDIR\"" - AC_MSG_RESULT($JAVAMDDIR) - fi -fi - -AC_SUBST([VS_JNI_INCLUDE]) -#AC_CHECK_HEADERS([jni.h], [], [AC_MSG_ERROR([JNI headers not found])]) -# Checks for typedefs, structures, and compiler characteristics. -# Checks for library functions. -# Output files. -# AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([Makefile src/Makefile]) -AC_OUTPUT \ No newline at end of file diff --git a/src/native/libjunbound/make-linux.sh b/src/native/libjunbound/make-linux.sh deleted file mode 100644 index 991eb17..0000000 --- a/src/native/libjunbound/make-linux.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -set -e - -out=`pwd`/build/linux -prefix=$out/libs -export JAVA_HOME=/usr/lib/jvm/default-java/ - -mkdir -p $out -mkdir -p $prefix - -cd $out - -expat=expat-2.1.0 -unbound=unbound-1.5.1 - -wget -nc http://downloads.sourceforge.net/project/expat/expat/2.1.0/$expat.tar.gz -wget -nc http://unbound.net/downloads/$unbound.tar.gz - -tar -xzvf $expat.tar.gz -tar -xzvf $unbound.tar.gz - -cd $out/$expat -./configure --with-pic --prefix=$prefix -make -make install - -cd $out/$unbound -patch -p 1 -i $out/../../unbound.patch -./configure --with-pic --prefix=$prefix --with-libexpat=$prefix -make -make install - -cd $out -gcc $out/../../src/net_java_sip_communicator_impl_dns_UnboundApi.cpp -fpic -shared -o libjunbound.so -I$JAVA_HOME/include -Wl,-Bstatic -L$prefix/lib -lunbound -I$prefix/include -Wl,-Bdynamic -lcrypto -lssl -strip libjunbound.so diff --git a/src/native/libjunbound/make-mac.sh b/src/native/libjunbound/make-mac.sh deleted file mode 100644 index 785adf8..0000000 --- a/src/native/libjunbound/make-mac.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash -#------------- -#Note: To compile the PPC support, you must have XCode 3.x installed! -# Remove the "-arch ppc" arguments to build only for 32/64 bit -#------------- - -set -e - -out=`pwd`/build/mac -prefix=$out/libs - -mkdir -p $out -mkdir -p $prefix/lib -#mkdir -p $prefix/include - -cd $out - -expat=expat-2.0.1 -ldns=ldns-1.6.11 -unbound=unbound-1.4.14 - -curl -L http://downloads.sourceforge.net/project/expat/expat/2.0.1/expat-2.0.1.tar.gz -o $expat.tar.gz -curl -L http://nlnetlabs.nl/downloads/ldns/$ldns.tar.gz -o $ldns.tar.gz -curl -L http://unbound.net/downloads/$unbound.tar.gz -o $unbound.tar.gz - -tar -xzvf $expat.tar.gz -tar -xzvf $ldns.tar.gz -tar -xzvf $unbound.tar.gz - -mv $expat expat -mv $ldns ldns -mv $unbound unbound - -export MACOSX_DEPLOYMENT_TARGET=10.5 -export CC="/usr/bin/gcc -arch i386 -arch x86_64 -mmacosx-version-min=10.5" -export CPP="/usr/bin/gcc -E" - -function build_arch { - prefixarch="${prefix}_$1" - mkdir -p $prefixarch - - cd $out/$2 - - ./configure --with-ssl=/usr --disable-gost --with-pic --with-ldns=$prefixarch --with-expat=$prefixarch --prefix=$prefixarch - - make clean - make - make install -} - -function build_lib { - build_arch all $1 -} - -build_lib expat -build_lib ldns -build_lib unbound - -cp -r ${prefix}_all/include $prefix/ -# remove all dynamic libs as we do not use them and compile is first searching -# for them -rm ${prefix}_all/lib/*.dylib -cd $out -g++ -mmacosx-version-min=10.4 -arch x86_64 -arch i386 \ - $out/../../src/net_java_sip_communicator_impl_dns_UnboundApi.cpp \ - -D_JNI_IMPLEMENTATION_ \ - -fPIC -shared -O2 -Wall \ - -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers \ - -I${prefix}_all/include \ - -L${prefix}_all/lib \ - -L/usr/lib \ - -dynamiclib \ - -lunbound -lldns -lcrypto \ - -dynamic \ - -lcrypto -lssl \ - -o libjunbound.jnilib diff --git a/src/native/libjunbound/makefile.linux b/src/native/libjunbound/makefile.linux deleted file mode 100644 index f4e2124..0000000 --- a/src/native/libjunbound/makefile.linux +++ /dev/null @@ -1,16 +0,0 @@ -CC = g++ -O2 -TARGET_BASENAME = libjunbound.so - -CPPFLAGS = \ - -Wall -Wreturn-type \ - -fpic \ - -DJNI_IMPLEMENTATION \ - -I/usr/lib/jvm/java-6-openjdk/include - -LDFLAGS = -shared -LIBS = -lunbound -TARGET = $(TARGET_BASENAME) - -$(TARGET): src/*.cpp - $(CC) $(CPPFLAGS) $^ $(LDFLAGS) -o $@ $(LIBS) - -strip $(TARGET) diff --git a/src/native/libjunbound/makefile.w32 b/src/native/libjunbound/makefile.w32 deleted file mode 100644 index e57c030..0000000 --- a/src/native/libjunbound/makefile.w32 +++ /dev/null @@ -1,25 +0,0 @@ -CC = g++ -O2 -TARGET_BASENAME = junbound.dll -TARGET_DIR ?= ../../../lib/native/windows - -ifeq ($(wildcard /bin/cygpath.*),/bin/cygpath.exe) - target.dir := $(shell cygpath --mixed "$(TARGET_DIR)") - cygwin.target.dir := $(shell cygpath --unix "$(TARGET_DIR)") -else - target.dir := "$(TARGET_DIR)" - cygwin.target.dir := "$(TARGET_DIR)" -endif - -CPPFLAGS = \ - -Wall -Wreturn-type \ - -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 \ - -DJNI_IMPLEMENTATION \ - -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" -Iwindows32 - -LDFLAGS = -shared -static -Wl,--kill-at -Wl,--subsystem,windows -LIBS = -Lwindows32 -lunbound -lldns -lcrypto -lws2_32 -lgdi32 -liphlpapi -TARGET = $(TARGET_DIR)/$(TARGET_BASENAME) - -$(TARGET): src/*.cpp - $(CC) $(CPPFLAGS) $^ $(LDFLAGS) -o $@ $(LIBS) - -strip $(TARGET) diff --git a/src/native/libjunbound/makefile.w64 b/src/native/libjunbound/makefile.w64 deleted file mode 100644 index c3865f4..0000000 --- a/src/native/libjunbound/makefile.w64 +++ /dev/null @@ -1,26 +0,0 @@ -CC = g++ -O2 -TARGET_BASENAME = junbound.dll -TARGET_DIR ?= ../../../lib/native/windows-64 -JAVA_HOME = C:/Program Files/Java/jdk6 - -ifeq ($(wildcard /bin/cygpath.*),/bin/cygpath.exe) - target.dir := $(shell cygpath --mixed "$(TARGET_DIR)") - cygwin.target.dir := $(shell cygpath --unix "$(TARGET_DIR)") -else - target.dir := "$(TARGET_DIR)" - cygwin.target.dir := "$(TARGET_DIR)" -endif - -CPPFLAGS = \ - -Wall -Wreturn-type \ - -DWINVER=0x0502 -D_WIN32_WINNT=0x0502 \ - -DJNI_IMPLEMENTATION \ - -I"$(JAVA_HOME)/include" -I"$(JAVA_HOME)/include/win32" -Iwindows64 - -LDFLAGS = -shared -static -Wl,--kill-at -Wl,--subsystem,windows -LIBS = -Lwindows64 -lunbound -lldns -lcrypto -lws2_32 -lgdi32 -liphlpapi -TARGET = $(TARGET_DIR)/$(TARGET_BASENAME) - -$(TARGET): src/*.cpp - $(CC) $(CPPFLAGS) $^ $(LDFLAGS) -o $@ $(LIBS) - -strip $(TARGET) diff --git a/src/native/libjunbound/readme.txt b/src/native/libjunbound/readme.txt deleted file mode 100644 index 4e7110a..0000000 --- a/src/native/libjunbound/readme.txt +++ /dev/null @@ -1,40 +0,0 @@ -To compile libjunbound - -Linux (libunbound, libldns and lcrypto shared): ----------------------------------------------- -a) With autoconf -autoreconf --install -./configure -make -cp ./libs/libjunbound.so ../../lib/native/linux - -b) With manual makefile -make -f makefile.linux - -Linux (libunbound statically linked, lcrypto shared): ----------------------------------------------------- -Use make-linux.sh - -Mac: ---- -Use make-mac.sh - -Windows: -------- -- Get ldns, libexpat, unbound and compile them -- make -f makefile.w32 - -Expat Win64: -./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 - -Unbound Win64: -The configure script wrongly detects getaddrinfo as Unix. Break the detection -script at line 16085 (1.4.12) - -OpenSSL Win64: -configure mingw64 -no-capieng -no-asm -make -make check (http://stackoverflow.com/questions/7256087/error-compiling-openssl-with-mingw-msys) -mkdir lib -cp libcrypto.a lib -cp libssl.a lib diff --git a/src/native/libjunbound/src/Makefile.am b/src/native/libjunbound/src/Makefile.am deleted file mode 100644 index 9cdbd7f..0000000 --- a/src/native/libjunbound/src/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -lib_LTLIBRARIES = libjunbound.la -libjunbound_la_SOURCES = net_java_sip_communicator_impl_dns_UnboundApi.cpp -AM_CPPFLAGS = ${includedirs} ${VS_JNI_INCLUDE} -DJNI_IMPLEMENTATION diff --git a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.cpp b/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.cpp deleted file mode 100644 index 05d6181..0000000 --- a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include -#include "net_java_sip_communicator_impl_dns_UnboundApi.h" - -void ub_async_cb(void* my_arg, int err, struct ub_result* result); -jobject createUnboundResult(JNIEnv* env, ub_result* resolveResult); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: setDebugLevel - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_setDebugLevel - (JNIEnv* env, jclass clazz, jlong context, jint level) -{ - int result = ub_ctx_debuglevel((ub_ctx*)context, level); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return; - } -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: createContext - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_createContext - (JNIEnv* env, jclass clazz) -{ - return (jlong)ub_ctx_create(); -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: deleteContext - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_deleteContext - (JNIEnv* env, jclass clazz, jlong context) -{ - ub_ctx_delete((ub_ctx*)context); -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: setForwarder - * Signature: (JLjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_setForwarder - (JNIEnv* env, jclass clazz, jlong context, jstring server) -{ - char* chars = (char*)env->GetStringUTFChars(server, NULL); - int result = ub_ctx_set_fwd((ub_ctx*)context, chars); - env->ReleaseStringUTFChars(server, chars); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return; - } -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: addTrustAnchor - * Signature: (JLjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_addTrustAnchor - (JNIEnv* env, jclass clazz, jlong context, jstring anchor) -{ - char* chars = (char*)env->GetStringUTFChars(anchor, NULL); - int result = ub_ctx_add_ta((ub_ctx*)context, chars); - env->ReleaseStringUTFChars(anchor, chars); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return; - } -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: resolve - * Signature: (JLjava/lang/String;II)Lnet/java/sip/communicator/impl/dns/UnboundResult; - */ -JNIEXPORT jobject JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_resolve - (JNIEnv* env, jclass clazz, jlong context, jstring name, jint rrtype, jint rrclass) -{ - char* chars = (char*)env->GetStringUTFChars(name, NULL); - ub_result* resolveResult; - int result = ub_resolve((ub_ctx*)context, chars, rrtype, rrclass, &resolveResult); - env->ReleaseStringUTFChars(name, chars); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return NULL; - } - return createUnboundResult(env, resolveResult); -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: resolveAsync - * Signature: (JLjava/lang/String;IILnet/java/sip/communicator/impl/dns/UnboundApi/UnboundCallback;)J - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_resolveAsync - (JNIEnv* env, jclass clazz, jlong context, jstring name, jint rrtype, jint rrclass, jobject data, jobject cb) -{ - JavaVM* jvm; - if(env->GetJavaVM(&jvm) != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), "Unable to obtain Java VM pointer"); - return 0; - } - - int result = ub_ctx_async((ub_ctx*)context, true); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return 0; - } - - //ensure the objects stay alive when this method leaves - void** cbData = new void*[3]; - cbData[0] = env->NewGlobalRef(data); - cbData[1] = env->NewGlobalRef(cb); - cbData[2] = jvm; - - int asyncId; - char* chars = (char*)env->GetStringUTFChars(name, NULL); - result = ub_resolve_async((ub_ctx*)context, chars, rrtype, rrclass, cbData, &ub_async_cb, &asyncId); - env->ReleaseStringUTFChars(name, chars); - if(result != 0) - { - delete[] cbData; - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return 0; - } - return asyncId; -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: cancelAsync - * Signature: (JJ)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_cancelAsync - (JNIEnv* env, jclass clazz, jlong context, jint asyncId) -{ - int result = ub_cancel((ub_ctx*)context, asyncId); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return; - } -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: errorCodeToString - * Signature: (I)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_errorCodeToString - (JNIEnv* env, jclass clazz, jint code) -{ - return env->NewStringUTF(ub_strerror(code)); -} - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: processAsync - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_processAsync - (JNIEnv* env, jclass clazz, jlong context) -{ - int result = ub_wait((ub_ctx*)context); - if(result != 0) - { - env->ThrowNew(env->FindClass("net/java/sip/communicator/impl/dns/UnboundException"), ub_strerror(result)); - return; - } -} - - - - - -void ub_async_cb(void* my_arg, int err, struct ub_result* result) -{ - void** cbData = (void**)my_arg; - JavaVM* jvm = ((JavaVM*)cbData[2]); - JNIEnv* env; - if(jvm->AttachCurrentThreadAsDaemon((void**)&env, NULL) == 0) - { - jobject data = (jobject)cbData[0]; - jobject cb = (jobject)cbData[1]; - delete[] cbData; - - jobject ubResult = NULL; - if(err == 0) - { - ubResult = createUnboundResult(env, result); - } - env->CallVoidMethod( - cb, env->GetMethodID( - env->FindClass("net/java/sip/communicator/impl/dns/UnboundApi$UnboundCallback"), - "UnboundResolveCallback", - "(Ljava/lang/Object;ILnet/java/sip/communicator/impl/dns/UnboundResult;)V" - ), data, (jint)err, ubResult - ); - - env->DeleteGlobalRef(data); - env->DeleteGlobalRef(cb); - env->DeleteLocalRef(ubResult); - } - jvm->DetachCurrentThread(); -} - - - - -jobject createUnboundResult(JNIEnv* env, ub_result* resolveResult) -{ - jclass ubResultClass = env->FindClass("net/java/sip/communicator/impl/dns/UnboundResult"); - jmethodID constructor = env->GetMethodID(ubResultClass, "", "()V"); - jobject ubResult = env->NewObject(ubResultClass, constructor); - - //copy data - //int numData = 0; - //char** data = resolveResult->data; - //while(*(data++) != NULL) - // numData++; - - //jobjectArray dataArray = env->NewObjectArray(numData, env->FindClass("[B"), NULL); - //for(int i = 0; i < numData; i++) - //{ - // jbyteArray dataEntry = env->NewByteArray(resolveResult->len[i]); - // env->SetByteArrayRegion(dataEntry, 0, resolveResult->len[i], (jbyte*)resolveResult->data[i]); - // env->SetObjectArrayElement(dataArray, i, dataEntry); - // env->DeleteLocalRef(dataEntry); - //} - - //copy answer packet - jbyteArray answerPacket = env->NewByteArray(resolveResult->answer_len); - env->SetByteArrayRegion(answerPacket, 0, resolveResult->answer_len, (jbyte*)resolveResult->answer_packet); - - //set fields - env->SetObjectField( ubResult, env->GetFieldID(ubResultClass, "qname", "Ljava/lang/String;"), env->NewStringUTF(resolveResult->qname)); - env->SetIntField( ubResult, env->GetFieldID(ubResultClass, "qtype", "I"), resolveResult->qtype); - env->SetIntField( ubResult, env->GetFieldID(ubResultClass, "qclass", "I"), resolveResult->qclass); - - //env->SetObjectField( ubResult, env->GetFieldID(ubResultClass, "data", "[[B"), dataArray); - //env->SetObjectField( ubResult, env->GetFieldID(ubResultClass, "canonname", "Ljava/lang/String;"), env->NewStringUTF(resolveResult->canonname)); - env->SetIntField( ubResult, env->GetFieldID(ubResultClass, "rcode", "I"), resolveResult->rcode); - env->SetObjectField( ubResult, env->GetFieldID(ubResultClass, "answerPacket", "[B"), answerPacket); - - env->SetBooleanField(ubResult, env->GetFieldID(ubResultClass, "haveData", "Z"), resolveResult->havedata); - env->SetBooleanField(ubResult, env->GetFieldID(ubResultClass, "nxDomain", "Z"), resolveResult->nxdomain); - env->SetBooleanField(ubResult, env->GetFieldID(ubResultClass, "secure", "Z"), resolveResult->secure); - env->SetBooleanField(ubResult, env->GetFieldID(ubResultClass, "bogus", "Z"), resolveResult->bogus); - env->SetObjectField( ubResult, env->GetFieldID(ubResultClass, "whyBogus", "Ljava/lang/String;"), env->NewStringUTF(resolveResult->why_bogus)); - - ub_resolve_free(resolveResult); - return ubResult; -} diff --git a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.h b/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.h deleted file mode 100644 index 71b59b9..0000000 --- a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi.h +++ /dev/null @@ -1,94 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class net_java_sip_communicator_impl_dns_UnboundApi */ - -#ifndef _Included_net_java_sip_communicator_impl_dns_UnboundApi -#define _Included_net_java_sip_communicator_impl_dns_UnboundApi -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: setDebugLevel - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_setDebugLevel - (JNIEnv *, jclass, jlong, jint); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: createContext - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_createContext - (JNIEnv *, jclass); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: deleteContext - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_deleteContext - (JNIEnv *, jclass, jlong); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: setForwarder - * Signature: (JLjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_setForwarder - (JNIEnv *, jclass, jlong, jstring); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: addTrustAnchor - * Signature: (JLjava/lang/String;)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_addTrustAnchor - (JNIEnv *, jclass, jlong, jstring); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: resolve - * Signature: (JLjava/lang/String;II)Lnet/java/sip/communicator/impl/dns/UnboundResult; - */ -JNIEXPORT jobject JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_resolve - (JNIEnv *, jclass, jlong, jstring, jint, jint); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: resolveAsync - * Signature: (JLjava/lang/String;IILjava/lang/Object;Lnet/java/sip/communicator/impl/dns/UnboundApi/UnboundCallback;)I - */ -JNIEXPORT jint JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_resolveAsync - (JNIEnv *, jclass, jlong, jstring, jint, jint, jobject, jobject); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: cancelAsync - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_cancelAsync - (JNIEnv *, jclass, jlong, jint); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: errorCodeToString - * Signature: (I)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_errorCodeToString - (JNIEnv *, jclass, jint); - -/* - * Class: net_java_sip_communicator_impl_dns_UnboundApi - * Method: processAsync - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_java_sip_communicator_impl_dns_UnboundApi_processAsync - (JNIEnv *, jclass, jlong); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback.h b/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback.h deleted file mode 100644 index f9b9de6..0000000 --- a/src/native/libjunbound/src/net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback.h +++ /dev/null @@ -1,13 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback */ - -#ifndef _Included_net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback -#define _Included_net_java_sip_communicator_impl_dns_UnboundApi_UnboundCallback -#ifdef __cplusplus -extern "C" { -#endif -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/native/libjunbound/unbound.patch b/src/native/libjunbound/unbound.patch deleted file mode 100644 index cc9aba6..0000000 --- a/src/native/libjunbound/unbound.patch +++ /dev/null @@ -1,54 +0,0 @@ -diff -u -r unbound-1.5.1-orig/libunbound/context.c unbound-1.5.1/libunbound/context.c ---- unbound-1.5.1-orig/libunbound/context.c 2014-02-07 14:28:39.000000000 +0100 -+++ unbound-1.5.1/libunbound/context.c 2015-02-09 11:55:02.000000000 +0100 -@@ -125,7 +125,7 @@ - } - - struct ctx_query* --context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, -+context_create(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, - ub_callback_t cb, void* cbarg) - { - struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); -diff -u -r unbound-1.5.1-orig/libunbound/context.h unbound-1.5.1/libunbound/context.h ---- unbound-1.5.1-orig/libunbound/context.h 2014-02-07 14:28:39.000000000 +0100 -+++ unbound-1.5.1/libunbound/context.h 2015-02-09 11:54:44.000000000 +0100 -@@ -241,7 +241,7 @@ - * @param cbarg: user arg for async queries. - * @return new ctx_query or NULL for malloc failure. - */ --struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype, -+struct ctx_query* context_create(struct ub_ctx* ctx, const char* name, int rrtype, - int rrclass, ub_callback_t cb, void* cbarg); - - /** -diff -u -r unbound-1.5.1-orig/libunbound/libunbound.c unbound-1.5.1/libunbound/libunbound.c ---- unbound-1.5.1-orig/libunbound/libunbound.c 2014-11-04 10:11:59.000000000 +0100 -+++ unbound-1.5.1/libunbound/libunbound.c 2015-02-09 11:55:20.000000000 +0100 -@@ -634,7 +634,7 @@ - } - /* create new ctx_query and attempt to add to the list */ - lock_basic_unlock(&ctx->cfglock); -- q = context_new(ctx, name, rrtype, rrclass, NULL, NULL); -+ q = context_create(ctx, name, rrtype, rrclass, NULL, NULL); - if(!q) - return UB_NOMEM; - /* become a resolver thread for a bit */ -@@ -687,7 +687,7 @@ - } - - /* create new ctx_query and attempt to add to the list */ -- q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback, -+ q = context_create(ctx, name, rrtype, rrclass, (ub_callback_t)callback, - mydata); - if(!q) - return UB_NOMEM; -@@ -733,7 +733,7 @@ - } - - /* create new ctx_query and attempt to add to the list */ -- q = context_new(ctx, name, rrtype, rrclass, callback, mydata); -+ q = context_create(ctx, name, rrtype, rrclass, callback, mydata); - if(!q) - return UB_NOMEM; - diff --git a/src/native/libjunbound/windows32/libcrypto.a b/src/native/libjunbound/windows32/libcrypto.a deleted file mode 100644 index 6c7863e..0000000 Binary files a/src/native/libjunbound/windows32/libcrypto.a and /dev/null differ diff --git a/src/native/libjunbound/windows32/libldns.a b/src/native/libjunbound/windows32/libldns.a deleted file mode 100644 index 55837de..0000000 Binary files a/src/native/libjunbound/windows32/libldns.a and /dev/null differ diff --git a/src/native/libjunbound/windows32/libunbound.a b/src/native/libjunbound/windows32/libunbound.a deleted file mode 100644 index 8b5b7d5..0000000 Binary files a/src/native/libjunbound/windows32/libunbound.a and /dev/null differ diff --git a/src/native/libjunbound/windows32/unbound.h b/src/native/libjunbound/windows32/unbound.h deleted file mode 100644 index 14f1fea..0000000 --- a/src/native/libjunbound/windows32/unbound.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file - * - * This file contains functions to resolve DNS queries and - * validate the answers. Synchonously and asynchronously. - * - * Several ways to use this interface from an application wishing - * to perform (validated) DNS lookups. - * - * All start with - * ctx = ub_ctx_create(); - * err = ub_ctx_add_ta(ctx, "..."); - * err = ub_ctx_add_ta(ctx, "..."); - * ... some lookups - * ... call ub_ctx_delete(ctx); when you want to stop. - * - * Application not threaded. Blocking. - * int err = ub_resolve(ctx, "www.example.com", ... - * if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err)); - * ... use the answer - * - * Application not threaded. Non-blocking ('asynchronous'). - * err = ub_resolve_async(ctx, "www.example.com", ... my_callback); - * ... application resumes processing ... - * ... and when either ub_poll(ctx) is true - * ... or when the file descriptor ub_fd(ctx) is readable, - * ... or whenever, the app calls ... - * ub_process(ctx); - * ... if no result is ready, the app resumes processing above, - * ... or process() calls my_callback() with results. - * - * ... if the application has nothing more to do, wait for answer - * ub_wait(ctx); - * - * Application threaded. Blocking. - * Blocking, same as above. The current thread does the work. - * Multiple threads can use the *same context*, each does work and uses - * shared cache data from the context. - * - * Application threaded. Non-blocking ('asynchronous'). - * ... setup threaded-asynchronous config option - * err = ub_ctx_async(ctx, 1); - * ... same as async for non-threaded - * ... the callbacks are called in the thread that calls process(ctx) - * - * If no threading is compiled in, the above async example uses fork(2) to - * create a process to perform the work. The forked process exits when the - * calling process exits, or ctx_delete() is called. - * Otherwise, for asynchronous with threading, a worker thread is created. - * - * The blocking calls use shared ctx-cache when threaded. Thus - * ub_resolve() and ub_resolve_async() && ub_wait() are - * not the same. The first makes the current thread do the work, setting - * up buffers, etc, to perform the work (but using shared cache data). - * The second calls another worker thread (or process) to perform the work. - * And no buffers need to be set up, but a context-switch happens. - */ -#ifndef _UB_UNBOUND_H -#define _UB_UNBOUND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The validation context is created to hold the resolver status, - * validation keys and a small cache (containing messages, rrsets, - * roundtrip times, trusted keys, lameness information). - * - * Its contents are internally defined. - */ -struct ub_ctx; - -/** - * The validation and resolution results. - * Allocated by the resolver, and need to be freed by the application - * with ub_resolve_free(). - */ -struct ub_result { - /** The original question, name text string. */ - char* qname; - /** the type asked for */ - int qtype; - /** the class asked for */ - int qclass; - - /** - * a list of network order DNS rdata items, terminated with a - * NULL pointer, so that data[0] is the first result entry, - * data[1] the second, and the last entry is NULL. - * If there was no data, data[0] is NULL. - */ - char** data; - - /** the length in bytes of the data items, len[i] for data[i] */ - int* len; - - /** - * canonical name for the result (the final cname). - * zero terminated string. - * May be NULL if no canonical name exists. - */ - char* canonname; - - /** - * DNS RCODE for the result. May contain additional error code if - * there was no data due to an error. 0 (NOERROR) if okay. - */ - int rcode; - - /** - * The DNS answer packet. Network formatted. Can contain DNSSEC types. - */ - void* answer_packet; - /** length of the answer packet in octets. */ - int answer_len; - - /** - * If there is any data, this is true. - * If false, there was no data (nxdomain may be true, rcode can be set). - */ - int havedata; - - /** - * If there was no data, and the domain did not exist, this is true. - * If it is false, and there was no data, then the domain name - * is purported to exist, but the requested data type is not available. - */ - int nxdomain; - - /** - * True, if the result is validated securely. - * False, if validation failed or domain queried has no security info. - * - * It is possible to get a result with no data (havedata is false), - * and secure is true. This means that the non-existance of the data - * was cryptographically proven (with signatures). - */ - int secure; - - /** - * If the result was not secure (secure==0), and this result is due - * to a security failure, bogus is true. - * This means the data has been actively tampered with, signatures - * failed, expected signatures were not present, timestamps on - * signatures were out of date and so on. - * - * If !secure and !bogus, this can happen if the data is not secure - * because security is disabled for that domain name. - * This means the data is from a domain where data is not signed. - */ - int bogus; - - /** - * If the result is bogus this contains a string (zero terminated) - * that describes the failure. There may be other errors as well - * as the one described, the description may not be perfectly accurate. - * Is NULL if the result is not bogus. - */ - char* why_bogus; -}; - -/** - * Callback for results of async queries. - * The readable function definition looks like: - * void my_callback(void* my_arg, int err, struct ub_result* result); - * It is called with - * void* my_arg: your pointer to a (struct of) data of your choice, - * or NULL. - * int err: if 0 all is OK, otherwise an error occured and no results - * are forthcoming. - * struct result: pointer to more detailed result structure. - * This structure is allocated on the heap and needs to be - * freed with ub_resolve_free(result); - */ -typedef void (*ub_callback_t)(void*, int, struct ub_result*); - -/** - * Create a resolving and validation context. - * The information from /etc/resolv.conf and /etc/hosts is not utilised by - * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - * @return a new context. default initialisation. - * returns NULL on error. - */ -struct ub_ctx* ub_ctx_create(void); - -/** - * Destroy a validation context and free all its resources. - * Outstanding async queries are killed and callbacks are not called for them. - * @param ctx: context to delete. - */ -void ub_ctx_delete(struct ub_ctx* ctx); - -/** - * Set an option for the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name includes the trailing ':' - * for example ub_ctx_set_option(ctx, "logfile:", "mylog.txt"); - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @param val: value of the option. - * @return: 0 if OK, else error. - */ -int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val); - -/** - * Get an option from the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name excludes the trailing ':' - * for example ub_ctx_get_option(ctx, "logfile", &result); - * This is a power-users interface that lets you specify all sorts - * of options. - * @param str: the string is malloced and returned here. NULL on error. - * The caller must free() the string. In cases with multiple - * entries (auto-trust-anchor-file), a newline delimited list is - * returned in the string. - * @return 0 if OK else an error code (malloc failure, syntax error). - */ -int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str); - -/** - * setup configuration for the given context. - * @param ctx: context. - * @param fname: unbound config file (not all settings applicable). - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @return: 0 if OK, else error. - */ -int ub_ctx_config(struct ub_ctx* ctx, char* fname); - -/** - * Set machine to forward DNS queries to, the caching resolver to use. - * IP4 or IP6 address. Forwards all DNS requests to that machine, which - * is expected to run a recursive resolver. If the proxy is not - * DNSSEC-capable, validation may fail. Can be called several times, in - * that case the addresses are used as backup servers. - * - * To read the list of nameservers from /etc/resolv.conf (from DHCP or so), - * use the call ub_ctx_resolvconf. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param addr: address, IP4 or IP6 in string format. - * If the addr is NULL, forwarding is disabled. - * @return 0 if OK, else error. - */ -int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr); - -/** - * Read list of nameservers to use from the filename given. - * Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. - * If they do not support DNSSEC, validation may fail. - * - * Only nameservers are picked up, the searchdomain, ndots and other - * settings from resolv.conf(5) are ignored. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/resolv.conf" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname); - -/** - * Read list of hosts from the filename given. - * Usually "/etc/hosts". - * These addresses are not flagged as DNSSEC secure when queried for. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/hosts" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_hosts(struct ub_ctx* ctx, char* fname); - -/** - * Add a trust anchor to the given context. - * The trust anchor is a string, on one line, that holds a valid DNSKEY or - * DS RR. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param ta: string, with zone-format RR on one line. - * [domainname] [TTL optional] [type] [class optional] [rdata contents] - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta); - -/** - * Add trust anchors to the given context. - * Pass name of a file with DS and DNSKEY records (like from dig or drill). - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with keyfile with trust anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname); - -/** - * Add trust anchors to the given context. - * Pass the name of a bind-style config file with trusted-keys{}. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with bind-style config entries with trust - * anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname); - -/** - * Set debug output (and error output) to the specified stream. - * Pass NULL to disable. Default is stderr. - * @param ctx: context. - * @param out: FILE* out file stream to log to. - * Type void* to avoid stdio dependency of this header file. - * @return 0 if OK, else error. - */ -int ub_ctx_debugout(struct ub_ctx* ctx, void* out); - -/** - * Set debug verbosity for the context - * Output is directed to stderr. - * @param ctx: context. - * @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed, - * and 3 is lots. - * @return 0 if OK, else error. - */ -int ub_ctx_debuglevel(struct ub_ctx* ctx, int d); - -/** - * Set a context behaviour for asynchronous action. - * @param ctx: context. - * @param dothread: if true, enables threading and a call to resolve_async() - * creates a thread to handle work in the background. - * If false, a process is forked to handle work in the background. - * Changes to this setting after async() calls have been made have - * no effect (delete and re-create the context to change). - * @return 0 if OK, else error. - */ -int ub_ctx_async(struct ub_ctx* ctx, int dothread); - -/** - * Poll a context to see if it has any new results - * Do not poll in a loop, instead extract the fd below to poll for readiness, - * and then check, or wait using the wait routine. - * @param ctx: context. - * @return: 0 if nothing to read, or nonzero if a result is available. - * If nonzero, call ctx_process() to do callbacks. - */ -int ub_poll(struct ub_ctx* ctx); - -/** - * Wait for a context to finish with results. Calls ub_process() after - * the wait for you. After the wait, there are no more outstanding - * asynchronous queries. - * @param ctx: context. - * @return: 0 if OK, else error. - */ -int ub_wait(struct ub_ctx* ctx); - -/** - * Get file descriptor. Wait for it to become readable, at this point - * answers are returned from the asynchronous validating resolver. - * Then call the ub_process to continue processing. - * This routine works immediately after context creation, the fd - * does not change. - * @param ctx: context. - * @return: -1 on error, or file descriptor to use select(2) with. - */ -int ub_fd(struct ub_ctx* ctx); - -/** - * Call this routine to continue processing results from the validating - * resolver (when the fd becomes readable). - * Will perform necessary callbacks. - * @param ctx: context - * @return: 0 if OK, else error. - */ -int ub_process(struct ub_ctx* ctx); - -/** - * Perform resolution and validation of the target name. - * @param ctx: context. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a zero terminated text string). - * @param rrtype: type of RR in host order, 1 is A (address). - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param result: the result data is returned in a newly allocated result - * structure. May be NULL on return, return value is set to an error - * in that case (out of memory). - * @return 0 if OK, else error. - */ -int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, - int rrclass, struct ub_result** result); - -/** - * Perform resolution and validation of the target name. - * Asynchronous, after a while, the callback will be called with your - * data and the result. - * @param ctx: context. - * If no thread or process has been created yet to perform the - * work in the background, it is created now. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a string). - * @param rrtype: type of RR in host order, 1 is A. - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param mydata: this data is your own data (you can pass NULL), - * and is passed on to the callback function. - * @param callback: this is called on completion of the resolution. - * It is called as: - * void callback(void* mydata, int err, struct ub_result* result) - * with mydata: the same as passed here, you may pass NULL, - * with err: is 0 when a result has been found. - * with result: a newly allocated result structure. - * The result may be NULL, in that case err is set. - * - * If an error happens during processing, your callback will be called - * with error set to a nonzero value (and result==NULL). - * @param async_id: if you pass a non-NULL value, an identifier number is - * returned for the query as it is in progress. It can be used to - * cancel the query. - * @return 0 if OK, else error. - */ -int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, - int rrclass, void* mydata, ub_callback_t callback, int* async_id); - -/** - * Cancel an async query in progress. - * Its callback will not be called. - * - * @param ctx: context. - * @param async_id: which query to cancel. - * @return 0 if OK, else error. - * This routine can return an error if the async_id passed does not exist - * or has already been delivered. If another thread is processing results - * at the same time, the result may be delivered at the same time and the - * cancel fails with an error. Also the cancel can fail due to a system - * error, no memory or socket failures. - */ -int ub_cancel(struct ub_ctx* ctx, int async_id); - -/** - * Free storage associated with a result structure. - * @param result: to free - */ -void ub_resolve_free(struct ub_result* result); - -/** - * Convert error value to a human readable string. - * @param err: error code from one of the ub_val* functions. - * @return pointer to constant text string, zero terminated. - */ -const char* ub_strerror(int err); - -/** - * Debug routine. Print the local zone information to debug output. - * @param ctx: context. Is finalized by the routine. - * @return 0 if OK, else error. - */ -int ub_ctx_print_local_zones(struct ub_ctx* ctx); - -/** - * Add a new zone with the zonetype to the local authority info of the - * library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it already exists, the type is updated. - * @param zone_type: type of the zone (like for unbound.conf) in text. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type); - -/** - * Remove zone from local authority info of the library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it does not exist, nothing happens. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name); - -/** - * Add localdata to the library local authority info. - * Similar to local-data config statement. - * @param ctx: context. Is finalized by the routine. - * @param data: the resource record in text format, for example - * "www.example.com IN A 127.0.0.1" - * @return 0 if OK, else error. - */ -int ub_ctx_data_add(struct ub_ctx* ctx, char *data); - -/** - * Remove localdata from the library local authority info. - * @param ctx: context. Is finalized by the routine. - * @param data: the name to delete all data from, like "www.example.com". - * @return 0 if OK, else error. - */ -int ub_ctx_data_remove(struct ub_ctx* ctx, char *data); - -#ifdef __cplusplus -} -#endif - -#endif /* _UB_UNBOUND_H */ diff --git a/src/native/libjunbound/windows64/libcrypto.a b/src/native/libjunbound/windows64/libcrypto.a deleted file mode 100644 index 71a8fde..0000000 Binary files a/src/native/libjunbound/windows64/libcrypto.a and /dev/null differ diff --git a/src/native/libjunbound/windows64/libldns.a b/src/native/libjunbound/windows64/libldns.a deleted file mode 100644 index 2a094a9..0000000 Binary files a/src/native/libjunbound/windows64/libldns.a and /dev/null differ diff --git a/src/native/libjunbound/windows64/libunbound.a b/src/native/libjunbound/windows64/libunbound.a deleted file mode 100644 index 47d1902..0000000 Binary files a/src/native/libjunbound/windows64/libunbound.a and /dev/null differ diff --git a/src/native/libjunbound/windows64/unbound.h b/src/native/libjunbound/windows64/unbound.h deleted file mode 100644 index 14f1fea..0000000 --- a/src/native/libjunbound/windows64/unbound.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file - * - * This file contains functions to resolve DNS queries and - * validate the answers. Synchonously and asynchronously. - * - * Several ways to use this interface from an application wishing - * to perform (validated) DNS lookups. - * - * All start with - * ctx = ub_ctx_create(); - * err = ub_ctx_add_ta(ctx, "..."); - * err = ub_ctx_add_ta(ctx, "..."); - * ... some lookups - * ... call ub_ctx_delete(ctx); when you want to stop. - * - * Application not threaded. Blocking. - * int err = ub_resolve(ctx, "www.example.com", ... - * if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err)); - * ... use the answer - * - * Application not threaded. Non-blocking ('asynchronous'). - * err = ub_resolve_async(ctx, "www.example.com", ... my_callback); - * ... application resumes processing ... - * ... and when either ub_poll(ctx) is true - * ... or when the file descriptor ub_fd(ctx) is readable, - * ... or whenever, the app calls ... - * ub_process(ctx); - * ... if no result is ready, the app resumes processing above, - * ... or process() calls my_callback() with results. - * - * ... if the application has nothing more to do, wait for answer - * ub_wait(ctx); - * - * Application threaded. Blocking. - * Blocking, same as above. The current thread does the work. - * Multiple threads can use the *same context*, each does work and uses - * shared cache data from the context. - * - * Application threaded. Non-blocking ('asynchronous'). - * ... setup threaded-asynchronous config option - * err = ub_ctx_async(ctx, 1); - * ... same as async for non-threaded - * ... the callbacks are called in the thread that calls process(ctx) - * - * If no threading is compiled in, the above async example uses fork(2) to - * create a process to perform the work. The forked process exits when the - * calling process exits, or ctx_delete() is called. - * Otherwise, for asynchronous with threading, a worker thread is created. - * - * The blocking calls use shared ctx-cache when threaded. Thus - * ub_resolve() and ub_resolve_async() && ub_wait() are - * not the same. The first makes the current thread do the work, setting - * up buffers, etc, to perform the work (but using shared cache data). - * The second calls another worker thread (or process) to perform the work. - * And no buffers need to be set up, but a context-switch happens. - */ -#ifndef _UB_UNBOUND_H -#define _UB_UNBOUND_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The validation context is created to hold the resolver status, - * validation keys and a small cache (containing messages, rrsets, - * roundtrip times, trusted keys, lameness information). - * - * Its contents are internally defined. - */ -struct ub_ctx; - -/** - * The validation and resolution results. - * Allocated by the resolver, and need to be freed by the application - * with ub_resolve_free(). - */ -struct ub_result { - /** The original question, name text string. */ - char* qname; - /** the type asked for */ - int qtype; - /** the class asked for */ - int qclass; - - /** - * a list of network order DNS rdata items, terminated with a - * NULL pointer, so that data[0] is the first result entry, - * data[1] the second, and the last entry is NULL. - * If there was no data, data[0] is NULL. - */ - char** data; - - /** the length in bytes of the data items, len[i] for data[i] */ - int* len; - - /** - * canonical name for the result (the final cname). - * zero terminated string. - * May be NULL if no canonical name exists. - */ - char* canonname; - - /** - * DNS RCODE for the result. May contain additional error code if - * there was no data due to an error. 0 (NOERROR) if okay. - */ - int rcode; - - /** - * The DNS answer packet. Network formatted. Can contain DNSSEC types. - */ - void* answer_packet; - /** length of the answer packet in octets. */ - int answer_len; - - /** - * If there is any data, this is true. - * If false, there was no data (nxdomain may be true, rcode can be set). - */ - int havedata; - - /** - * If there was no data, and the domain did not exist, this is true. - * If it is false, and there was no data, then the domain name - * is purported to exist, but the requested data type is not available. - */ - int nxdomain; - - /** - * True, if the result is validated securely. - * False, if validation failed or domain queried has no security info. - * - * It is possible to get a result with no data (havedata is false), - * and secure is true. This means that the non-existance of the data - * was cryptographically proven (with signatures). - */ - int secure; - - /** - * If the result was not secure (secure==0), and this result is due - * to a security failure, bogus is true. - * This means the data has been actively tampered with, signatures - * failed, expected signatures were not present, timestamps on - * signatures were out of date and so on. - * - * If !secure and !bogus, this can happen if the data is not secure - * because security is disabled for that domain name. - * This means the data is from a domain where data is not signed. - */ - int bogus; - - /** - * If the result is bogus this contains a string (zero terminated) - * that describes the failure. There may be other errors as well - * as the one described, the description may not be perfectly accurate. - * Is NULL if the result is not bogus. - */ - char* why_bogus; -}; - -/** - * Callback for results of async queries. - * The readable function definition looks like: - * void my_callback(void* my_arg, int err, struct ub_result* result); - * It is called with - * void* my_arg: your pointer to a (struct of) data of your choice, - * or NULL. - * int err: if 0 all is OK, otherwise an error occured and no results - * are forthcoming. - * struct result: pointer to more detailed result structure. - * This structure is allocated on the heap and needs to be - * freed with ub_resolve_free(result); - */ -typedef void (*ub_callback_t)(void*, int, struct ub_result*); - -/** - * Create a resolving and validation context. - * The information from /etc/resolv.conf and /etc/hosts is not utilised by - * default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them. - * @return a new context. default initialisation. - * returns NULL on error. - */ -struct ub_ctx* ub_ctx_create(void); - -/** - * Destroy a validation context and free all its resources. - * Outstanding async queries are killed and callbacks are not called for them. - * @param ctx: context to delete. - */ -void ub_ctx_delete(struct ub_ctx* ctx); - -/** - * Set an option for the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name includes the trailing ':' - * for example ub_ctx_set_option(ctx, "logfile:", "mylog.txt"); - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @param val: value of the option. - * @return: 0 if OK, else error. - */ -int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val); - -/** - * Get an option from the context. - * @param ctx: context. - * @param opt: option name from the unbound.conf config file format. - * (not all settings applicable). The name excludes the trailing ':' - * for example ub_ctx_get_option(ctx, "logfile", &result); - * This is a power-users interface that lets you specify all sorts - * of options. - * @param str: the string is malloced and returned here. NULL on error. - * The caller must free() the string. In cases with multiple - * entries (auto-trust-anchor-file), a newline delimited list is - * returned in the string. - * @return 0 if OK else an error code (malloc failure, syntax error). - */ -int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str); - -/** - * setup configuration for the given context. - * @param ctx: context. - * @param fname: unbound config file (not all settings applicable). - * This is a power-users interface that lets you specify all sorts - * of options. - * For some specific options, such as adding trust anchors, special - * routines exist. - * @return: 0 if OK, else error. - */ -int ub_ctx_config(struct ub_ctx* ctx, char* fname); - -/** - * Set machine to forward DNS queries to, the caching resolver to use. - * IP4 or IP6 address. Forwards all DNS requests to that machine, which - * is expected to run a recursive resolver. If the proxy is not - * DNSSEC-capable, validation may fail. Can be called several times, in - * that case the addresses are used as backup servers. - * - * To read the list of nameservers from /etc/resolv.conf (from DHCP or so), - * use the call ub_ctx_resolvconf. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param addr: address, IP4 or IP6 in string format. - * If the addr is NULL, forwarding is disabled. - * @return 0 if OK, else error. - */ -int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr); - -/** - * Read list of nameservers to use from the filename given. - * Usually "/etc/resolv.conf". Uses those nameservers as caching proxies. - * If they do not support DNSSEC, validation may fail. - * - * Only nameservers are picked up, the searchdomain, ndots and other - * settings from resolv.conf(5) are ignored. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/resolv.conf" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname); - -/** - * Read list of hosts from the filename given. - * Usually "/etc/hosts". - * These addresses are not flagged as DNSSEC secure when queried for. - * - * @param ctx: context. - * At this time it is only possible to set configuration before the - * first resolve is done. - * @param fname: file name string. If NULL "/etc/hosts" is used. - * @return 0 if OK, else error. - */ -int ub_ctx_hosts(struct ub_ctx* ctx, char* fname); - -/** - * Add a trust anchor to the given context. - * The trust anchor is a string, on one line, that holds a valid DNSKEY or - * DS RR. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param ta: string, with zone-format RR on one line. - * [domainname] [TTL optional] [type] [class optional] [rdata contents] - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta); - -/** - * Add trust anchors to the given context. - * Pass name of a file with DS and DNSKEY records (like from dig or drill). - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with keyfile with trust anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname); - -/** - * Add trust anchors to the given context. - * Pass the name of a bind-style config file with trusted-keys{}. - * @param ctx: context. - * At this time it is only possible to add trusted keys before the - * first resolve is done. - * @param fname: filename of file with bind-style config entries with trust - * anchors. - * @return 0 if OK, else error. - */ -int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname); - -/** - * Set debug output (and error output) to the specified stream. - * Pass NULL to disable. Default is stderr. - * @param ctx: context. - * @param out: FILE* out file stream to log to. - * Type void* to avoid stdio dependency of this header file. - * @return 0 if OK, else error. - */ -int ub_ctx_debugout(struct ub_ctx* ctx, void* out); - -/** - * Set debug verbosity for the context - * Output is directed to stderr. - * @param ctx: context. - * @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed, - * and 3 is lots. - * @return 0 if OK, else error. - */ -int ub_ctx_debuglevel(struct ub_ctx* ctx, int d); - -/** - * Set a context behaviour for asynchronous action. - * @param ctx: context. - * @param dothread: if true, enables threading and a call to resolve_async() - * creates a thread to handle work in the background. - * If false, a process is forked to handle work in the background. - * Changes to this setting after async() calls have been made have - * no effect (delete and re-create the context to change). - * @return 0 if OK, else error. - */ -int ub_ctx_async(struct ub_ctx* ctx, int dothread); - -/** - * Poll a context to see if it has any new results - * Do not poll in a loop, instead extract the fd below to poll for readiness, - * and then check, or wait using the wait routine. - * @param ctx: context. - * @return: 0 if nothing to read, or nonzero if a result is available. - * If nonzero, call ctx_process() to do callbacks. - */ -int ub_poll(struct ub_ctx* ctx); - -/** - * Wait for a context to finish with results. Calls ub_process() after - * the wait for you. After the wait, there are no more outstanding - * asynchronous queries. - * @param ctx: context. - * @return: 0 if OK, else error. - */ -int ub_wait(struct ub_ctx* ctx); - -/** - * Get file descriptor. Wait for it to become readable, at this point - * answers are returned from the asynchronous validating resolver. - * Then call the ub_process to continue processing. - * This routine works immediately after context creation, the fd - * does not change. - * @param ctx: context. - * @return: -1 on error, or file descriptor to use select(2) with. - */ -int ub_fd(struct ub_ctx* ctx); - -/** - * Call this routine to continue processing results from the validating - * resolver (when the fd becomes readable). - * Will perform necessary callbacks. - * @param ctx: context - * @return: 0 if OK, else error. - */ -int ub_process(struct ub_ctx* ctx); - -/** - * Perform resolution and validation of the target name. - * @param ctx: context. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a zero terminated text string). - * @param rrtype: type of RR in host order, 1 is A (address). - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param result: the result data is returned in a newly allocated result - * structure. May be NULL on return, return value is set to an error - * in that case (out of memory). - * @return 0 if OK, else error. - */ -int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, - int rrclass, struct ub_result** result); - -/** - * Perform resolution and validation of the target name. - * Asynchronous, after a while, the callback will be called with your - * data and the result. - * @param ctx: context. - * If no thread or process has been created yet to perform the - * work in the background, it is created now. - * The context is finalized, and can no longer accept config changes. - * @param name: domain name in text format (a string). - * @param rrtype: type of RR in host order, 1 is A. - * @param rrclass: class of RR in host order, 1 is IN (for internet). - * @param mydata: this data is your own data (you can pass NULL), - * and is passed on to the callback function. - * @param callback: this is called on completion of the resolution. - * It is called as: - * void callback(void* mydata, int err, struct ub_result* result) - * with mydata: the same as passed here, you may pass NULL, - * with err: is 0 when a result has been found. - * with result: a newly allocated result structure. - * The result may be NULL, in that case err is set. - * - * If an error happens during processing, your callback will be called - * with error set to a nonzero value (and result==NULL). - * @param async_id: if you pass a non-NULL value, an identifier number is - * returned for the query as it is in progress. It can be used to - * cancel the query. - * @return 0 if OK, else error. - */ -int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype, - int rrclass, void* mydata, ub_callback_t callback, int* async_id); - -/** - * Cancel an async query in progress. - * Its callback will not be called. - * - * @param ctx: context. - * @param async_id: which query to cancel. - * @return 0 if OK, else error. - * This routine can return an error if the async_id passed does not exist - * or has already been delivered. If another thread is processing results - * at the same time, the result may be delivered at the same time and the - * cancel fails with an error. Also the cancel can fail due to a system - * error, no memory or socket failures. - */ -int ub_cancel(struct ub_ctx* ctx, int async_id); - -/** - * Free storage associated with a result structure. - * @param result: to free - */ -void ub_resolve_free(struct ub_result* result); - -/** - * Convert error value to a human readable string. - * @param err: error code from one of the ub_val* functions. - * @return pointer to constant text string, zero terminated. - */ -const char* ub_strerror(int err); - -/** - * Debug routine. Print the local zone information to debug output. - * @param ctx: context. Is finalized by the routine. - * @return 0 if OK, else error. - */ -int ub_ctx_print_local_zones(struct ub_ctx* ctx); - -/** - * Add a new zone with the zonetype to the local authority info of the - * library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it already exists, the type is updated. - * @param zone_type: type of the zone (like for unbound.conf) in text. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_add(struct ub_ctx* ctx, char *zone_name, char *zone_type); - -/** - * Remove zone from local authority info of the library. - * @param ctx: context. Is finalized by the routine. - * @param zone_name: name of the zone in text, "example.com" - * If it does not exist, nothing happens. - * @return 0 if OK, else error. - */ -int ub_ctx_zone_remove(struct ub_ctx* ctx, char *zone_name); - -/** - * Add localdata to the library local authority info. - * Similar to local-data config statement. - * @param ctx: context. Is finalized by the routine. - * @param data: the resource record in text format, for example - * "www.example.com IN A 127.0.0.1" - * @return 0 if OK, else error. - */ -int ub_ctx_data_add(struct ub_ctx* ctx, char *data); - -/** - * Remove localdata from the library local authority info. - * @param ctx: context. Is finalized by the routine. - * @param data: the name to delete all data from, like "www.example.com". - * @return 0 if OK, else error. - */ -int ub_ctx_data_remove(struct ub_ctx* ctx, char *data); - -#ifdef __cplusplus -} -#endif - -#endif /* _UB_UNBOUND_H */ diff --git a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java index 5668de2..1b23af4 100644 --- a/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java +++ b/src/net/java/sip/communicator/impl/dns/ConfigurableDnssecResolver.java @@ -44,7 +44,6 @@ import org.xbill.DNS.*; * @author Ingo Bauersachs */ public class ConfigurableDnssecResolver - //extends UnboundResolver extends ValidatingResolver implements CustomResolver { diff --git a/src/net/java/sip/communicator/impl/dns/SecureMessage.java b/src/net/java/sip/communicator/impl/dns/SecureMessage.java index b03c340..15f77b0 100644 --- a/src/net/java/sip/communicator/impl/dns/SecureMessage.java +++ b/src/net/java/sip/communicator/impl/dns/SecureMessage.java @@ -35,10 +35,10 @@ public class SecureMessage private String bogusReason; /** - * Creates a new instance of this class based on data received from an - * Unbound resolve. + * Creates a new instance of this class based on data received from a + * dnssecjava resolve. * - * @param msg The answer of the Unbound resolver. + * @param msg The answer of the dnssecjava resolver. * @throws IOException */ public SecureMessage(Message msg) throws IOException diff --git a/src/net/java/sip/communicator/impl/dns/UnboundApi.java b/src/net/java/sip/communicator/impl/dns/UnboundApi.java deleted file mode 100644 index 9a628c0..0000000 --- a/src/net/java/sip/communicator/impl/dns/UnboundApi.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.dns; - -/** - * Wrapper for the JUnbound JNI wrapper. - *

    - * The JavaDoc of these methods is directly copied from libunbound, licensed as - * follows: - *

    - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @author Ingo Bauersachs - */ -public class UnboundApi -{ - private static boolean isAvailable; - private static final Object syncRoot = new Object(); - - static - { - tryLoadUnbound(); - } - - /** - * Attempts to load the Unbound native library. When successful, - * {@link #isAvailable()} returns true. - */ - public static void tryLoadUnbound() - { - synchronized(syncRoot) - { - try - { - System.loadLibrary("junbound"); - isAvailable = true; - } - catch(UnsatisfiedLinkError e) - { - isAvailable = false; - } - } - } - - /** - * Indicates whether the Unbound library is loaded. - * @return True when the JNI wrapper could be loaded, false otherwise. - */ - public static boolean isAvailable() - { - return isAvailable; - } - - /** - * Set debug verbosity for the context. Output is directed to stderr. Higher - * debug level gives more output. - * - * @param context context. - * @param level The debug level. - */ - public static native void setDebugLevel(long context, int level); - - /** - * Create a resolving and validation context. - * @return a new context. default initialization. returns NULL on error. - */ - public static native long createContext(); - - /** - * Destroy a validation context and free all its resources. Outstanding - * async queries are killed and callbacks are not called for them. - * - * @param context context to delete - */ - public static native void deleteContext(long context); - - /** - * Set machine to forward DNS queries to, the caching resolver to use. - *

    - * IP4 or IP6 address. Forwards all DNS requests to that machine, which is - * expected to run a recursive resolver. If the proxy is not DNSSEC-capable, - * validation may fail. Can be called several times, in that case the - * addresses are used as backup servers. - * - * @param context context. At this time it is only possible to set - * configuration before the first resolve is done. - * @param server address, IP4 or IP6 in string format. If the server is - * NULL, forwarding is disabled. - */ - public static native void setForwarder(long context, String server); - - /** - * Add a trust anchor to the given context. - *

    - * The trust anchor is a string, on one line, that holds a valid DNSKEY or - * DS RR. - * - * @param context context. At this time it is only possible to add trusted - * keys before the first resolve is done. - * @param anchor string, with zone-format RR on one line. [domainname] [TTL - * optional] [type] [class optional] [rdata contents] - */ - public static native void addTrustAnchor(long context, String anchor); - - /** - * Perform resolution and validation of the target name. - * - * @param context context. The context is finalized, and can no longer - * accept config changes. - * @param name domain name in text format (a zero terminated text string). - * @param rrtype type of RR in host order, 1 is A (address). - * @param rrclass class of RR in host order, 1 is IN (for internet). - * @return the result data is returned in a newly allocated result - * structure. May be NULL on return, return value is set to an error - * in that case (out of memory). - * @throws UnboundException when an error occurred. - */ - public static native UnboundResult resolve(long context, String name, - int rrtype, int rrclass) throws UnboundException; - - /** - * Perform resolution and validation of the target name. - *

    - * Asynchronous, after a while, the callback will be called with your data - * and the result. - * - * @param context context. If no thread or process has been created yet to - * perform the work in the background, it is created now. The - * context is finalized, and can no longer accept config changes. - * @param name domain name in text format (a string). - * @param rrtype type of RR in host order, 1 is A. - * @param rrclass class of RR in host order, 1 is IN (for internet). - * @param data this data is your own data (you can pass null), and is passed - * on to the callback function. - * @param cb this is called on completion of the resolution. - * @return an identifier number is returned for the query as it is in - * progress. It can be used to cancel the query. - * @throws UnboundException when an error occurred. - */ - public static native int resolveAsync(long context, String name, - int rrtype, int rrclass, Object data, UnboundCallback cb) - throws UnboundException; - - /** - * Cancel an async query in progress. Its callback will not be called. - * - * @param context context. - * @param asyncId which query to cancel. - * @throws UnboundException This routine can error if the async_id passed - * does not exist or has already been delivered. If another - * thread is processing results at the same time, the result may - * be delivered at the same time and the cancel fails with an - * error. Also the cancel can fail due to a system error, no - * memory or socket failures. - */ - public static native void cancelAsync(long context, int asyncId) - throws UnboundException; - - /** - * Convert error value to a human readable string. - * - * @param code error code from one of the Unbound functions. - * @return text string of the error code. - */ - public static native String errorCodeToString(int code); - - /** - * Wait for a context to finish with results. Call this routine to continue - * processing results from the validating resolver. After the wait, there - * are no more outstanding asynchronous queries. - * - * @param context context. - * @throws UnboundException when an error occurred. - */ - public static native void processAsync(long context) - throws UnboundException; - - /** - * Interface for the async resolve callback. - */ - public interface UnboundCallback - { - /** - * Called on completion of the async resolution. - * - * @param data the same object as passed to - * {@link UnboundApi#resolveAsync(long, String, int, int, - * Object, UnboundCallback)} - * @param err 0 when a result has been found, an Unbound error code - * otherwise - * @param result a newly allocated result structure. The result may be - * null, in that case err is set. - */ - public void UnboundResolveCallback(Object data, int err, - UnboundResult result); - } -} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundException.java b/src/net/java/sip/communicator/impl/dns/UnboundException.java deleted file mode 100644 index a27a607..0000000 --- a/src/net/java/sip/communicator/impl/dns/UnboundException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.dns; - -/** - * Exception that is being thrown when native Unbound code resulted in an error. - * - * @author Ingo Bauersachs - */ -public class UnboundException - extends Exception -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates a new instance of this class. - * - * @param message the detail message. - */ - public UnboundException(String message) - { - super(message); - } -} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundResolver.java b/src/net/java/sip/communicator/impl/dns/UnboundResolver.java deleted file mode 100644 index 3f3d8c9..0000000 --- a/src/net/java/sip/communicator/impl/dns/UnboundResolver.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.dns; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.concurrent.*; - -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.util.*; - -import org.xbill.DNS.*; - -/** - * Implementation of the {@link Resolver} interface, wrapping the native NLnet - * Labs Unbound resolver. Only the basic methods for queries are supported. - * - * @author Ingo Bauersachs - */ -public class UnboundResolver - implements CustomResolver -{ - private final static Logger logger = - Logger.getLogger(UnboundResolver.class); - - /** - * Helper class to synchronize on asynchronous queries. - */ - private static class CallbackData - { - /** - * The resolver consumer that wishes to be informed when the request - * completed. - */ - ResolverListener listener; - - /** - * The unbound session context. - */ - long context; - - /** - * The ID of the unbound async query. - */ - int asyncId; - - /** - * Java synchronization on top of unbound. - */ - CountDownLatch sync = new CountDownLatch(1); - } - - /** - * Timeout for DNS queries. - */ - private int timeout = 10000; - - /** - * The recursive DNS servers answering our queries. - */ - private String[] forwarders; - - /** - * DNSSEC trust anchors for signed zones (usually for the root zone). - */ - private List trustAnchors = new LinkedList(); - - /** - * Pool that executes our queries. - */ - private ExecutorService threadPool; - - /** - * Creates a new instance of this class. - */ - public UnboundResolver() - { - threadPool = Executors.newCachedThreadPool(); - } - - /** - * Sets a list of forwarders to use instead of the system default. - * - * @param forwarders list of servers to use for our queries. - */ - public void setForwarders(String[] forwarders) - { - this.forwarders = forwarders; - } - - /** - * Clears any existing trust anchors previously added. - */ - public void clearTrustAnchors() - { - trustAnchors.clear(); - } - - /** - * Adds a DNSSEC trust anchor validation of the DNSKEYs. - * - * @param anchor trust anchor in the form of - * "'zone' IN DS 'key tag' 'algorithm' 'digest type' 'digest'" - */ - public void addTrustAnchor(String anchor) - { - trustAnchors.add(anchor); - } - - /** - * {@inheritDoc} - */ - public SecureMessage send(final Message query) throws IOException - { - Future future = threadPool.submit( - new Callable() - { - public SecureMessage call() throws Exception - { - if(logger.isDebugEnabled()) - logger.debug(query); - - SecureMessage secureMessage = null; - final long context = prepareContext(); - try - { - UnboundResult result = UnboundApi.resolve( - context, - query.getQuestion().getName().toString(), - query.getQuestion().getType(), - query.getQuestion().getDClass() - ); - secureMessage = new SecureMessage(result); - validateMessage(secureMessage); - } - finally - { - UnboundApi.deleteContext(context); - if(logger.isDebugEnabled() && secureMessage != null) - logger.debug(secureMessage); - } - - return secureMessage; - } - }); - try - { - return future.get(timeout, TimeUnit.SECONDS); - } - catch (InterruptedException e) - { - logger.error(e); - throw new IOException(e.getMessage()); - } - catch (ExecutionException e) - { - if(e.getCause() instanceof DnssecRuntimeException) - throw new DnssecRuntimeException(e.getCause().getMessage()); - logger.error(e); - throw new IOException(e.getMessage()); - } - catch (TimeoutException e) - { - throw new SocketTimeoutException(e.getMessage()); - } - } - - /** - * Method to allow overriders to inspect the message. This class' - * implementation does nothing. - * - * @param msg The message to inspect. - * @throws DnssecRuntimeException if the inspector does not want the code to - * continue normal processing of the answer. - */ - protected void validateMessage(SecureMessage msg) - throws DnssecRuntimeException - { - } - - /** - * Prepares a unbound session context initialized with forwarders and trust - * anchors. - * - * @return The context id - */ - private long prepareContext() - { - final long context = UnboundApi.createContext(); - if(logger.isTraceEnabled()) - UnboundApi.setDebugLevel(context, 100); - for(String fwd : forwarders == null - ? ResolverConfig.getCurrentConfig().servers() - : forwarders) - { - fwd = fwd.trim(); - if(NetworkUtils.isValidIPAddress(fwd)) - { - if(fwd.startsWith("[")) - fwd = fwd.substring(1, fwd.length() - 1); - UnboundApi.setForwarder(context, fwd); - } - } - for(String anchor : trustAnchors) - { - UnboundApi.addTrustAnchor(context, anchor); - } - return context; - } - - /** - * Cleans up an Unbound session context. - * - * @param cbData The helper object of the asynchronous call. - * @param cancelAsync Whether an outstanding asynchronous unbound query - * should be canceled. - */ - private static synchronized void deleteContext(CallbackData cbData, - boolean cancelAsync) - { - if(cbData.context == 0) - return; - - if(cancelAsync) - { - try - { - UnboundApi.cancelAsync(cbData.context, cbData.asyncId); - } - catch (UnboundException ignore) - {} - } - UnboundApi.deleteContext(cbData.context); - cbData.context = 0; - } - - /* - * (non-Javadoc) - * - * @see org.xbill.DNS.Resolver#sendAsync(org.xbill.DNS.Message, - * org.xbill.DNS.ResolverListener) - */ - public CallbackData sendAsync(Message query, ResolverListener listener) - { - if(listener == null) - throw new IllegalArgumentException("listener cannot be null"); - - final long context = prepareContext(); - final CallbackData cbData = new CallbackData(); - cbData.listener = listener; - cbData.context = context; - int asyncId; - try - { - asyncId = UnboundApi.resolveAsync( - context, - query.getQuestion().getName().toString(), - query.getQuestion().getType(), - query.getQuestion().getDClass(), - cbData, - new UnboundApi.UnboundCallback() - { - public void UnboundResolveCallback(Object data, int err, - UnboundResult result) - { - CallbackData cbData = (CallbackData)data; - deleteContext(cbData, false); - - ResolverListener l = cbData.listener; - if(err == 0) - { - try - { - l.receiveMessage(data, - new SecureMessage(result)); - } - catch (IOException e) - { - l.handleException(data, e); - } - } - else - l.handleException(data, - new Exception( - UnboundApi.errorCodeToString(err))); - - cbData.sync.countDown(); - } - } - ); - } - catch (UnboundException e) - { - listener.handleException(null, e); - return null; - } - cbData.asyncId = asyncId; - threadPool.execute(new Runnable() - { - public void run() - { - try - { - UnboundApi.processAsync(context); - } - catch(UnboundException ex) - { - cbData.listener.handleException(this, ex); - deleteContext(cbData, false); - cbData.sync.countDown(); - } - } - }); - return cbData; - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setEDNS(int level) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - @SuppressWarnings("rawtypes") - public void setEDNS(int level, int payloadSize, int flags, List options) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setIgnoreTruncation(boolean flag) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setPort(int port) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setTCP(boolean flag) - { - throw new UnsupportedOperationException(); - } - - /** - * Not supported. - * @throws UnsupportedOperationException - */ - public void setTSIGKey(TSIG key) - { - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see org.xbill.DNS.Resolver#setTimeout(int) - */ - public void setTimeout(int secs) - { - timeout = secs * 1000; - } - - /* (non-Javadoc) - * @see org.xbill.DNS.Resolver#setTimeout(int, int) - */ - public void setTimeout(int secs, int msecs) - { - timeout = secs * 1000 + msecs; - } - - /** - * Does nothing. - */ - public void reset() - { - } -} diff --git a/src/net/java/sip/communicator/impl/dns/UnboundResult.java b/src/net/java/sip/communicator/impl/dns/UnboundResult.java deleted file mode 100644 index ef5d1ec..0000000 --- a/src/net/java/sip/communicator/impl/dns/UnboundResult.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.dns; - -/** - * Class that contains the answer to query processed by the native Unbound - * resolver. Corresponds to the ub_result data structure. - * - * The fields {@link #data} and {@link #canonname} are not filled. - *

    - * The JavaDoc of these fields is directly copied from libunbound, licensed as - * follows: - *

    - * Copyright (c) 2007, NLnet Labs. All rights reserved. - * - * This software is open source. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * Neither the name of the NLNET LABS nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * @author Ingo Bauersachs - */ -public class UnboundResult -{ - /** - * The original question, name text string. - */ - String qname; - - /** - * the type asked for - */ - int qtype; - - /** - * the type asked for - */ - int qclass; - - - /** - * a list of network order DNS rdata items, terminated with a NULL pointer, - * so that data[0] is the first result entry, data[1] the second, and the - * last entry is NULL. - */ - byte[][] data; - - /** - * canonical name for the result (the final cname). - */ - String canonname; - - /** - * DNS RCODE for the result. - */ - int rcode; - - /** - * The DNS answer packet. - */ - byte[] answerPacket; - - - /** - * If there is any data, this is true. - */ - boolean haveData; - - /** - * If there was no data, and the domain did not exist, this is true. - */ - boolean nxDomain; - - /** - * True, if the result is validated securely. - */ - boolean secure; - - /** - * If the result was not secure ({@link #secure} == false), and this result - * is due to a security failure, bogus is true. - */ - boolean bogus; - - /** - * If the result is bogus this contains a string (zero terminated) that - * describes the failure. - */ - String whyBogus; -} -- cgit v1.1 From 1fcac7e80a3e131013b712a1c381cea85de5595e Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 21:49:50 +0200 Subject: Autogenerate the SPI service descriptor --- build.xml | 7 +++---- m2/jitsi-dns/pom.xml | 5 +++++ m2/jitsi-util/pom.xml | 18 ++++++++++++++++++ .../sun.net.spi.nameservice.NameServiceDescriptor | 1 - 4 files changed, 26 insertions(+), 5 deletions(-) delete mode 100644 src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor diff --git a/build.xml b/build.xml index 48a0aa5..75bea81 100644 --- a/build.xml +++ b/build.xml @@ -1252,10 +1252,9 @@ - + diff --git a/m2/jitsi-dns/pom.xml b/m2/jitsi-dns/pom.xml index c8fc438..bbedef9 100644 --- a/m2/jitsi-dns/pom.xml +++ b/m2/jitsi-dns/pom.xml @@ -24,6 +24,11 @@ ${project.groupId} + dnssecjava + 1.1 + + + ${project.groupId} jitsi-protocol diff --git a/m2/jitsi-util/pom.xml b/m2/jitsi-util/pom.xml index a17620f..1a01006 100644 --- a/m2/jitsi-util/pom.xml +++ b/m2/jitsi-util/pom.xml @@ -60,9 +60,27 @@ net/java/sip/communicator/util/** + META-INF/services/** + + eu.somatik.serviceloader-maven-plugin + serviceloader-maven-plugin + 1.0.7 + + + sun.net.spi.nameservice.NameServiceDescriptor + + + + + + generate + + + + diff --git a/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor b/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor deleted file mode 100644 index ecdbbf2..0000000 --- a/src/net/java/sip/communicator/util/services/sun.net.spi.nameservice.NameServiceDescriptor +++ /dev/null @@ -1 +0,0 @@ -net.java.sip.communicator.util.JitsiDnsNameServiceDescriptor -- cgit v1.1 From 58c33e299688b3fda07b18af3aa52056bb34ae93 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 21:51:27 +0200 Subject: Fix OSGi test configuration --- lib/felix.unit.test.properties | 64 ++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 044f24e..1adc197 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -4,36 +4,37 @@ # and Service Implementation Compatibility Kits # org.osgi.framework.system.packages.extra= \ - apple.awt; \ - com.apple.cocoa.application; \ - com.apple.cocoa.foundation; \ - com.apple.eawt; \ - com.apple.eio; \ - gnu.java.zrtp; \ - gnu.java.zrtp.packets; \ - gnu.java.zrtp.utils; \ - gnu.java.zrtp.zidfile; \ - net.java.stun4j;\ - net.java.stun4j.client;\ - org.apache.xml.serialize;\ - quicktime; \ - quicktime.qd; \ - quicktime.std.image; \ - quicktime.std.sg; \ - quicktime.util; \ - com.sun.awt; \ - sun.lwawt; \ - sun.lwawt.macosx; \ - sun.awt.shell; \ - sun.misc; \ - sun.net.util; \ - sun.net.dns; \ - sun.security.action; \ - sun.security.pkcs11; \ - sun.reflect; \ - org.xbill.DNS;\ - sun.audio;\ - sun.nio.ch;\ + apple.awt, \ + com.apple.cocoa.application, \ + com.apple.cocoa.foundation, \ + com.apple.eawt, \ + com.apple.eio, \ + gnu.java.zrtp, \ + gnu.java.zrtp.packets, \ + gnu.java.zrtp.utils, \ + gnu.java.zrtp.zidfile, \ + net.java.stun4j,\ + net.java.stun4j.client,\ + org.apache.xml.serialize,\ + quicktime, \ + quicktime.qd, \ + quicktime.std.image, \ + quicktime.std.sg, \ + quicktime.util, \ + com.sun.awt, \ + sun.lwawt, \ + sun.lwawt.macosx, \ + sun.awt.shell, \ + sun.misc, \ + sun.net.util, \ + sun.net.dns, \ + sun.security.action, \ + sun.security.pkcs11, \ + sun.reflect, \ + org.xbill.DNS;version="2.1.7",\ + org.xbill.DNS.util;version="2.1.7",\ + sun.audio,\ + sun.nio.ch,\ com.sun.nio.sctp @@ -61,7 +62,8 @@ felix.auto.start.10= \ reference:file:sc-bundles/hsqldb.jar \ reference:file:sc-bundles/commons-lang.jar \ reference:file:sc-bundles/guava.jar \ - reference:file:sc-bundles/weupnp.jar + reference:file:sc-bundles/weupnp.jar \ + reference:file:sc-bundles/dnssecjava.jar felix.auto.start.11= \ reference:file:sc-bundles/sip-api.jar \ -- cgit v1.1 From cb24dd6985d3a100879c5db8b085cc234b6c5c6e Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 21:52:55 +0200 Subject: Fix protocols in RPM description --- resources/install/rpm/SPECS/jitsi.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index 32bc811..0d60ff7 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -21,7 +21,7 @@ Requires: java >= 0:1.6 %description Jitsi (formerly SIP Communicator) is an audio/video and chat communicator -that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, Windows Live, +that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC, Yahoo! and many other useful features. %define debug_package %{nil} -- cgit v1.1 From 7aea53d7f9f0225408edaa0e11990519898b01f5 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 21:53:15 +0200 Subject: Add support for tel: and callto: URI on Mac --- resources/install/build.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/install/build.xml b/resources/install/build.xml index c0b11d3..00add08 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -1286,6 +1286,8 @@ CFBundleURLSchemes sip + tel + callto -- cgit v1.1 From b93a459a93f1ebc6279c9ac1e2fd66b9babc5ddb Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 28 May 2016 22:34:14 +0200 Subject: Add slf4j to unit tests, fix typo --- lib/felix.unit.test.properties | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 1adc197..b4f1a7f 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -31,8 +31,8 @@ org.osgi.framework.system.packages.extra= \ sun.security.action, \ sun.security.pkcs11, \ sun.reflect, \ - org.xbill.DNS;version="2.1.7",\ - org.xbill.DNS.util;version="2.1.7",\ + org.xbill.DNS;version="2.1.7", \ + org.xbill.DNS.utils;version="2.1.7", \ sun.audio,\ sun.nio.ch,\ com.sun.nio.sctp @@ -50,6 +50,7 @@ org.osgi.framework.system.packages.extra= \ #install (but don't start) OSGi fragments felix.auto.install.10= \ reference:file:sc-bundles/fmj.jar \ + reference:file:sc-bundles/slf4j-jdk14.jar \ reference:file:sc-bundles/jitsi-lgpl-dependencies.jar felix.auto.start.10= \ @@ -63,6 +64,7 @@ felix.auto.start.10= \ reference:file:sc-bundles/commons-lang.jar \ reference:file:sc-bundles/guava.jar \ reference:file:sc-bundles/weupnp.jar \ + reference:file:sc-bundles/slf4j-api.jar \ reference:file:sc-bundles/dnssecjava.jar felix.auto.start.11= \ -- cgit v1.1 From d258eaf5fdf8cff44675b690f5586f8abf13e878 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 13:34:34 +0200 Subject: Exclude native libs of foreign platforms I.e. no Windows DLLs for Mac OS, etc. --- resources/install/build.xml | 60 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/resources/install/build.xml b/resources/install/build.xml index 00add08..6693513 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -131,6 +131,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -539,6 +575,18 @@ + + + + + + + + + + + + Date: Sun, 29 May 2016 13:57:56 +0200 Subject: Check if the systray is initialized before hiding the main frame --- src/net/java/sip/communicator/impl/gui/main/MainFrame.java | 3 ++- .../communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java | 3 ++- src/net/java/sip/communicator/service/systray/SystrayService.java | 6 ++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java index a8ee80a..fb7e01c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java @@ -1920,7 +1920,8 @@ public class MainFrame // On Mac systems the application is not quited on window close, so we // don't need to warn the user. if (!GuiActivator.getUIService().getExitOnMainWindowClose() - && !OSUtils.IS_MAC) + && !OSUtils.IS_MAC + && GuiActivator.getSystrayService().checkInitialized()) { SwingUtilities.invokeLater(new Runnable() { diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index f774b23..94e6307 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -469,7 +469,8 @@ public class SystrayServiceJdicImpl } } - private boolean checkInitialized() + @Override + public boolean checkInitialized() { if (!initialized) logger.error("Systray not init"); diff --git a/src/net/java/sip/communicator/service/systray/SystrayService.java b/src/net/java/sip/communicator/service/systray/SystrayService.java index b9ada84..751abc6 100644 --- a/src/net/java/sip/communicator/service/systray/SystrayService.java +++ b/src/net/java/sip/communicator/service/systray/SystrayService.java @@ -129,4 +129,10 @@ public interface SystrayService * Selects the best available popup message handler */ public void selectBestPopupMessageHandler(); + + /** + * Checks if the systray icon has been initialized. + * @return True if the systray is initialized, false otherwise. + */ + public boolean checkInitialized(); } -- cgit v1.1 From 7126030f9835f3c932e28b2f391794af411f3c82 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 18:12:52 +0200 Subject: Simplify SystemTray/TrayIcon access Removes all the reflection to access the AWT implementation as it is included with Java 1.6 anyway. Instead of *Peer and double-wrapping, define a Jitsi-specific base class and implement it by wrapping the AWT system tray. Potential new implementations simply need to extend SystemTray and TrayIcon. --- .../sip/communicator/impl/osdependent/Desktop.java | 1 + .../PopupMessageHandlerTrayIconImpl.java | 1 + .../communicator/impl/osdependent/SystemTray.java | 215 ----------- .../communicator/impl/osdependent/TrayIcon.java | 412 --------------------- .../osdependent/jdic/SystrayServiceJdicImpl.java | 12 +- .../impl/osdependent/jdic/TrayMenuFactory.java | 4 - .../impl/osdependent/systemtray/SystemTray.java | 78 ++++ .../impl/osdependent/systemtray/TrayIcon.java | 42 +++ .../systemtray/awt/AWTMouseAdapter.java | 124 +++++++ .../osdependent/systemtray/awt/AWTSystemTray.java | 72 ++++ .../osdependent/systemtray/awt/AWTTrayIcon.java | 97 +++++ 11 files changed, 421 insertions(+), 637 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/osdependent/SystemTray.java delete mode 100644 src/net/java/sip/communicator/impl/osdependent/TrayIcon.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTMouseAdapter.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java diff --git a/src/net/java/sip/communicator/impl/osdependent/Desktop.java b/src/net/java/sip/communicator/impl/osdependent/Desktop.java index 885dd02..53728e8 100644 --- a/src/net/java/sip/communicator/impl/osdependent/Desktop.java +++ b/src/net/java/sip/communicator/impl/osdependent/Desktop.java @@ -22,6 +22,7 @@ import java.io.*; import java.lang.reflect.*; import java.net.*; +import net.java.sip.communicator.impl.osdependent.systemtray.SystemTray; import net.java.sip.communicator.util.Logger; /** diff --git a/src/net/java/sip/communicator/impl/osdependent/PopupMessageHandlerTrayIconImpl.java b/src/net/java/sip/communicator/impl/osdependent/PopupMessageHandlerTrayIconImpl.java index 7416b75..592e5af 100644 --- a/src/net/java/sip/communicator/impl/osdependent/PopupMessageHandlerTrayIconImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/PopupMessageHandlerTrayIconImpl.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.osdependent; import java.awt.event.*; +import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.service.systray.event.*; diff --git a/src/net/java/sip/communicator/impl/osdependent/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/SystemTray.java deleted file mode 100644 index b9d4d45..0000000 --- a/src/net/java/sip/communicator/impl/osdependent/SystemTray.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.osdependent; - -import java.awt.*; -import java.lang.reflect.*; - -import javax.swing.*; - -import net.java.sip.communicator.impl.osdependent.TrayIcon.AWTTrayIconPeer; -import net.java.sip.communicator.impl.osdependent.TrayIcon.TrayIconPeer; -import net.java.sip.communicator.util.*; - -/** - * @author Lubomir Marinov - */ -public class SystemTray -{ - /** - * The Logger used by the SystemTray class and its - * instances for logging output. - */ - private static final Logger logger = Logger.getLogger(SystemTray.class); - - private static SystemTray defaultSystemTray; - - public static SystemTray getDefaultSystemTray() - throws UnsupportedOperationException, - HeadlessException, - SecurityException - { - if (defaultSystemTray != null) - return defaultSystemTray; - - Class awtSystemTrayClass = null; - try - { - awtSystemTrayClass = Class.forName("java.awt.SystemTray"); - } - catch (ClassNotFoundException ex) - { - // We'll try org.jdesktop.jdic.tray then. - } - SystemTrayPeer peer = null; - if (awtSystemTrayClass != null) - try - { - peer = new AWTSystemTrayPeer(awtSystemTrayClass); - } - catch (Exception ex) - { - if(!GraphicsEnvironment.isHeadless()) - logger.error("Failed to initialize java.awt.SystemTray", - ex); - - // We'll try org.jdesktop.jdic.tray then. - } - if (peer == null) - { - logger.error( - "Failed to initialize the desktop.tray implementation."); - throw new UnsupportedOperationException( - "Failed to initialize the desktop.tray implementation."); - } - return (defaultSystemTray = new SystemTray(peer)); - } - - private final SystemTrayPeer peer; - - private SystemTray(SystemTrayPeer peer) - { - this.peer = peer; - } - - public void addTrayIcon(TrayIcon trayIcon) - throws NullPointerException, - IllegalArgumentException - { - if (peer != null) - peer.addTrayIcon(trayIcon.getPeer()); - } - - SystemTrayPeer getPeer() - { - return peer; - } - - public boolean isSwing() - { - if (peer != null) - return getPeer().isSwing(); - return false; - } - - static interface SystemTrayPeer - { - void addTrayIcon(TrayIconPeer trayIconPeer) - throws NullPointerException, - IllegalArgumentException; - - TrayIconPeer createTrayIcon(ImageIcon icon, - String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException; - - boolean isSwing(); - } - - private static class AWTSystemTrayPeer - implements SystemTrayPeer - { - private final Method addTrayIcon; - - private final Object impl; - - private final Class trayIconClass; - - public AWTSystemTrayPeer(Class clazz) - throws UnsupportedOperationException, - HeadlessException, - SecurityException - { - Method getDefaultSystemTray; - try - { - getDefaultSystemTray = - clazz.getMethod("getSystemTray", (Class[]) null); - trayIconClass = Class.forName("java.awt.TrayIcon"); - addTrayIcon = clazz.getMethod("add", new Class[] - { trayIconClass }); - } - catch (ClassNotFoundException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (NoSuchMethodException ex) - { - throw new UnsupportedOperationException(ex); - } - - try - { - impl = getDefaultSystemTray.invoke(null, (Object[]) null); - } - catch (IllegalAccessException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InvocationTargetException ex) - { - throw new UnsupportedOperationException(ex); - } - } - - public void addTrayIcon(TrayIconPeer trayIconPeer) - throws NullPointerException, - IllegalArgumentException - { - try - { - addTrayIcon.invoke(impl, new Object[] - { ((AWTTrayIconPeer) trayIconPeer).getImpl() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause == null) - throw new UndeclaredThrowableException(ex); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - if (cause instanceof IllegalArgumentException) - throw (IllegalArgumentException) cause; - throw new UndeclaredThrowableException(cause); - } - } - - public TrayIconPeer createTrayIcon(ImageIcon icon, String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - return new AWTTrayIconPeer(trayIconClass, (icon == null) ? null - : icon.getImage(), tooltip, popup); - } - - public boolean isSwing() - { - return false; - } - } -} diff --git a/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java deleted file mode 100644 index d338dc4..0000000 --- a/src/net/java/sip/communicator/impl/osdependent/TrayIcon.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.osdependent; - -import java.awt.*; -import java.awt.event.*; -import java.lang.reflect.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.impl.osdependent.SystemTray.SystemTrayPeer; - -import org.jitsi.util.*; - -/** - * @author Lubomir Marinov - */ -public class TrayIcon -{ - private final TrayIconPeer peer; - - public TrayIcon(ImageIcon icon, String tooltip, Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - SystemTrayPeer systemTrayPeer = - SystemTray.getDefaultSystemTray().getPeer(); - if (systemTrayPeer != null) - peer = systemTrayPeer.createTrayIcon(icon, tooltip, popup); - else - peer = null; - } - - public void addActionListener(ActionListener listener) - { - if (peer != null) - peer.addActionListener(listener); - } - - public void addBalloonActionListener(ActionListener listener) - { - if (peer != null) - peer.addBalloonActionListener(listener); - } - - public void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException - { - if (peer != null) - peer.displayMessage(caption, text, messageType); - } - - TrayIconPeer getPeer() - { - return peer; - } - - public void setIcon(ImageIcon icon) throws NullPointerException - { - if (peer != null) - peer.setIcon(icon); - } - - public void setIconAutoSize(boolean autoSize) - { - if (peer != null) - peer.setIconAutoSize(autoSize); - } - - static interface TrayIconPeer - { - void addActionListener(ActionListener listener); - - void addBalloonActionListener(ActionListener listener); - - void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException; - - void setIcon(ImageIcon icon) throws NullPointerException; - - void setIconAutoSize(boolean autoSize); - } - - static class AWTTrayIconPeer - implements TrayIconPeer - { - private final Method addActionListener; - - private final Method addMouseListener; - - private final Method displayMessage; - - private final Object impl; - - private final Class messageTypeClass; - - private final Method setIcon; - - private final Method setIconAutoSize; - - public AWTTrayIconPeer(Class clazz, Image image, String tooltip, - Object popup) - throws IllegalArgumentException, - UnsupportedOperationException, - HeadlessException, - SecurityException - { - Constructor constructor; - try - { - if (popup instanceof JPopupMenu) - { - constructor = clazz.getConstructor(new Class[] - { Image.class, String.class }); - } - else - { - constructor = clazz.getConstructor(new Class[] - { Image.class, String.class, PopupMenu.class }); - } - addActionListener = - clazz.getMethod("addActionListener", new Class[] - { ActionListener.class }); - addMouseListener = - clazz.getMethod("addMouseListener", new Class[] - { MouseListener.class }); - messageTypeClass = - Class.forName("java.awt.TrayIcon$MessageType"); - displayMessage = - clazz.getMethod("displayMessage", new Class[] - { String.class, String.class, messageTypeClass }); - setIcon = clazz.getMethod("setImage", new Class[] - { Image.class }); - setIconAutoSize = - clazz.getMethod("setImageAutoSize", new Class[] - { boolean.class }); - } - catch (ClassNotFoundException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (NoSuchMethodException ex) - { - throw new UnsupportedOperationException(ex); - } - - try - { - if (popup instanceof JPopupMenu) - { - impl = constructor.newInstance( - new Object[] { image, tooltip }); - addMouseListener(new AWTMouseAdapter((JPopupMenu) popup)); - } - else - { - impl = constructor.newInstance( - new Object[] { image, tooltip, popup }); - } - } - catch (IllegalAccessException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InstantiationException ex) - { - throw new UnsupportedOperationException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause == null) - throw new UnsupportedOperationException(ex); - if (cause instanceof IllegalArgumentException) - throw (IllegalArgumentException) cause; - if (cause instanceof UnsupportedOperationException) - throw (UnsupportedOperationException) cause; - if (cause instanceof HeadlessException) - throw (HeadlessException) cause; - if (cause instanceof SecurityException) - throw (SecurityException) cause; - throw new UnsupportedOperationException(cause); - } - } - - public void addActionListener(ActionListener listener) - { - try - { - addActionListener.invoke(getImpl(), new Object[] - { listener }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void addMouseListener(MouseListener listener) - { - try - { - addMouseListener.invoke(getImpl(), new Object[] { listener }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void addBalloonActionListener(ActionListener listener) - { - // java.awt.TrayIcon doesn't support addBalloonActionListener() - } - - public void displayMessage(String caption, String text, - java.awt.TrayIcon.MessageType messageType) - throws NullPointerException - { - try - { - displayMessage.invoke(getImpl(), new Object[] - { caption, text, messageType.name() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public Object getImpl() - { - return impl; - } - - public void setIcon(ImageIcon icon) throws NullPointerException - { - try - { - setIcon.invoke(getImpl(), new Object[] - { (icon == null) ? null : icon.getImage() }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - if (cause instanceof NullPointerException) - throw (NullPointerException) cause; - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - - public void setIconAutoSize(boolean autoSize) - { - try - { - setIconAutoSize.invoke(getImpl(), new Object[] - { autoSize }); - } - catch (IllegalAccessException ex) - { - throw new UndeclaredThrowableException(ex); - } - catch (InvocationTargetException ex) - { - Throwable cause = ex.getCause(); - throw new UndeclaredThrowableException((cause == null) ? ex - : cause); - } - } - } - - /** - * Extended mouse adapter to show the JPopupMenu in Java 6 - * Based on : http://weblogs.java.net/blog/ixmal/archive/2006/05/using_jpopupmen.html - * And : http://weblogs.java.net/blog/alexfromsun/archive/2008/02/jtrayicon_updat.html - * - * Use a hidden JWindow (JDialog for Windows) to manage the JPopupMenu. - * - * @author Damien Roth - */ - private static class AWTMouseAdapter - extends MouseAdapter - { - private JPopupMenu popup = null; - private Window hiddenWindow = null; - - public AWTMouseAdapter(JPopupMenu p) - { - this.popup = p; - this.popup.addPopupMenuListener(new PopupMenuListener() - { - public void popupMenuWillBecomeVisible(PopupMenuEvent e) - {} - - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) - { - if (hiddenWindow != null) - { - hiddenWindow.dispose(); - hiddenWindow = null; - } - } - - public void popupMenuCanceled(PopupMenuEvent e) - { - if (hiddenWindow != null) - { - hiddenWindow.dispose(); - hiddenWindow = null; - } - } - }); - } - - @Override - public void mouseReleased(MouseEvent e) - { - showPopupMenu(e); - } - - @Override - public void mousePressed(MouseEvent e) - { - showPopupMenu(e); - } - - private void showPopupMenu(MouseEvent e) - { - if (e.isPopupTrigger() && popup != null) - { - if (hiddenWindow == null) - { - if (OSUtils.IS_WINDOWS) - { - hiddenWindow = new JDialog((Frame) null); - ((JDialog) hiddenWindow).setUndecorated(true); - } - else - hiddenWindow = new JWindow((Frame) null); - - hiddenWindow.setAlwaysOnTop(true); - Dimension size = popup.getPreferredSize(); - - Point centerPoint = GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getCenterPoint(); - - if(e.getY() > centerPoint.getY()) - hiddenWindow - .setLocation(e.getX(), e.getY() - size.height); - else - hiddenWindow - .setLocation(e.getX(), e.getY()); - - hiddenWindow.setVisible(true); - - popup.show( - ((RootPaneContainer)hiddenWindow).getContentPane(), - 0, 0); - - // popup works only for focused windows - hiddenWindow.toFront(); - } - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index 94e6307..f1a744d 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -25,8 +25,8 @@ import javax.swing.*; import javax.swing.event.*; import net.java.sip.communicator.impl.osdependent.*; -import net.java.sip.communicator.impl.osdependent.SystemTray; -import net.java.sip.communicator.impl.osdependent.TrayIcon; +import net.java.sip.communicator.impl.osdependent.systemtray.SystemTray; +import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.systray.*; @@ -134,7 +134,7 @@ public class SystrayServiceJdicImpl try { - systray = SystemTray.getDefaultSystemTray(); + systray = SystemTray.getSystemTray(); } catch (Throwable t) { @@ -187,7 +187,7 @@ public class SystrayServiceJdicImpl return; } - menu = TrayMenuFactory.createTrayMenu(this, systray.isSwing()); + menu = TrayMenuFactory.createTrayMenu(this, systray.useSwingPopupMenu()); boolean isMac = OSUtils.IS_MAC; @@ -243,7 +243,7 @@ public class SystrayServiceJdicImpl currentIcon = isMac ? logoIcon : logoIconOffline; trayIcon - = new TrayIcon( + = systray.createTrayIcon( currentIcon, Resources.getApplicationString( "service.gui.APPLICATION_NAME"), @@ -552,7 +552,7 @@ public class SystrayServiceJdicImpl OsDependentActivator.bundleContext.removeServiceListener( this); - if (!initialized) + if (!initialized && systray != null) initSystray(); } } diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java index 2b5df19..c13a505 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java @@ -144,10 +144,6 @@ public final class TrayMenuFactory public static Object createTrayMenu(SystrayServiceJdicImpl tray, boolean swing) { - // Enable swing for java 1.6 except for the mac version - if (!swing && !OSUtils.IS_MAC) - swing = true; - Object trayMenu = swing ? new JPopupMenu() : new PopupMenu(); ActionListener listener = new ActionListener() { diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java new file mode 100644 index 0000000..125a190 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java @@ -0,0 +1,78 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray; + +import javax.swing.*; + +import net.java.sip.communicator.impl.osdependent.systemtray.awt.*; + +/** + * Base class for all wrappers of SystemTray implementations. + */ +public abstract class SystemTray +{ + private static SystemTray systemTray; + + /** + * Gets or creates the supported SystemTray implementations. + * @return a SystemTray implementation for the current platform. + */ + public final static SystemTray getSystemTray() + { + if (systemTray == null) + { + if (java.awt.SystemTray.isSupported()) + { + systemTray = new AWTSystemTray(); + } + } + + return systemTray; + } + + /** + * Adds a TrayIcon to this system tray implementation. + * + * @param trayIcon the TrayIcon to add + */ + public abstract void addTrayIcon(TrayIcon trayIcon); + + /** + * Creates an implementation specific TrayIcon that can later be + * added with {@link #addTrayIcon(TrayIcon)}. + * + * @param image the Image to be used + * @param tooltip the string to be used as tooltip text; if the value is + * null no tooltip is shown + * @param popup the menu to be used for the tray icon's popup menu; if the + * value is null no popup menu is shown + * @return a TrayIcon instance for this SystemTray + * implementation. + */ + public abstract TrayIcon createTrayIcon(ImageIcon icon, String tooltip, + Object popup); + + /** + * Determines if the popup menu for the icon is to be a Swing + * JPopupMenu or an AWT PopupMenu + * + * @return true for a JPopupMenu, false for a + * PopupMenu + */ + public abstract boolean useSwingPopupMenu(); +} diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java new file mode 100644 index 0000000..39fa6bd --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java @@ -0,0 +1,42 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray; + +import java.awt.event.*; + +import javax.swing.*; + +/** + * Interface for all platform specific TrayIcon implementations. See + * {@link java.awt.TrayIcon} for a description of the methods. + * + * @author Lubomir Marinov + */ +public interface TrayIcon +{ + public void addActionListener(ActionListener listener); + + public void addBalloonActionListener(ActionListener listener); + + public void displayMessage(String caption, String text, + java.awt.TrayIcon.MessageType messageType); + + public void setIcon(ImageIcon icon) throws NullPointerException; + + public void setIconAutoSize(boolean autoSize); +} diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTMouseAdapter.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTMouseAdapter.java new file mode 100644 index 0000000..eb4a773 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTMouseAdapter.java @@ -0,0 +1,124 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.awt; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.event.*; + +import org.jitsi.util.*; + +/** + * Extended mouse adapter to show the JPopupMenu in Java 6. Based on: + * Using JPopupMenu in TrayIcon Blog and + * JTrayIcon update Blog. + * + * Use a hidden JWindow (JDialog for Windows) to manage the JPopupMenu. + * + * @author Damien Roth + */ +class AWTMouseAdapter + extends MouseAdapter +{ + private JPopupMenu popup = null; + private Window hiddenWindow = null; + + public AWTMouseAdapter(JPopupMenu p) + { + this.popup = p; + this.popup.addPopupMenuListener(new PopupMenuListener() + { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) + {} + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) + { + if (hiddenWindow != null) + { + hiddenWindow.dispose(); + hiddenWindow = null; + } + } + + public void popupMenuCanceled(PopupMenuEvent e) + { + if (hiddenWindow != null) + { + hiddenWindow.dispose(); + hiddenWindow = null; + } + } + }); + } + + @Override + public void mouseReleased(MouseEvent e) + { + showPopupMenu(e); + } + + @Override + public void mousePressed(MouseEvent e) + { + showPopupMenu(e); + } + + private void showPopupMenu(MouseEvent e) + { + if (e.isPopupTrigger() && popup != null) + { + if (hiddenWindow == null) + { + if (OSUtils.IS_WINDOWS) + { + hiddenWindow = new JDialog((Frame) null); + ((JDialog) hiddenWindow).setUndecorated(true); + } + else + hiddenWindow = new JWindow((Frame) null); + + hiddenWindow.setAlwaysOnTop(true); + Dimension size = popup.getPreferredSize(); + + Point centerPoint = GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getCenterPoint(); + + if(e.getY() > centerPoint.getY()) + hiddenWindow + .setLocation(e.getX(), e.getY() - size.height); + else + hiddenWindow + .setLocation(e.getX(), e.getY()); + + hiddenWindow.setVisible(true); + + popup.show( + ((RootPaneContainer)hiddenWindow).getContentPane(), + 0, 0); + + // popup works only for focused windows + hiddenWindow.toFront(); + } + } + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java new file mode 100644 index 0000000..2fa25b3 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java @@ -0,0 +1,72 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.awt; + +import java.awt.*; + +import javax.swing.*; + +import org.jitsi.util.*; + +import net.java.sip.communicator.impl.osdependent.systemtray.SystemTray; +import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; + +/** + * Wrapper of the AWT SystemTray class. + */ +public class AWTSystemTray + extends SystemTray +{ + private final java.awt.SystemTray impl; + + /** + * Creates a new instance of this class. + */ + public AWTSystemTray() + { + impl = java.awt.SystemTray.getSystemTray(); + } + + @Override + public void addTrayIcon(TrayIcon trayIcon) + throws IllegalArgumentException + { + try + { + impl.add(((AWTTrayIcon) trayIcon).getImpl()); + } + catch (AWTException e) + { + throw new IllegalArgumentException(e); + } + } + + @Override + public TrayIcon createTrayIcon(ImageIcon icon, String tooltip, + Object popup) + { + return new AWTTrayIcon(icon.getImage(), tooltip, popup); + } + + @Override + public boolean useSwingPopupMenu() + { + // enable swing for Java 1.6 except for the mac version + return !OSUtils.IS_MAC; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java new file mode 100644 index 0000000..54d97ec --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java @@ -0,0 +1,97 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.awt; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; + +/** + * Wrapper of the AWT TrayIcon class. + */ +public class AWTTrayIcon + implements TrayIcon +{ + private final java.awt.TrayIcon impl; + + /** + * Creates a new instance of this class. + * + * @param image the Image to be used + * @param tooltip the string to be used as tooltip text; if the value is + * null no tooltip is shown + * @param popup the menu to be used for the tray icon's popup menu; if the + * value is null no popup menu is shown + */ + public AWTTrayIcon(Image image, String tooltip, + Object popup) + { + if (popup instanceof JPopupMenu) + { + impl = new java.awt.TrayIcon(image, tooltip); + impl.addMouseListener(new AWTMouseAdapter((JPopupMenu)popup)); + } + else if (popup instanceof PopupMenu) + { + impl = new java.awt.TrayIcon(image, tooltip, (PopupMenu)popup); + } + else if (popup == null) + { + impl = new java.awt.TrayIcon(image, tooltip); + } + else + { + throw new IllegalArgumentException("Invalid popup menu type"); + } + } + + public void addActionListener(ActionListener listener) + { + impl.addActionListener(listener); + } + + public void addBalloonActionListener(ActionListener listener) + { + // java.awt.TrayIcon doesn't support addBalloonActionListener() + } + + public void displayMessage(String caption, String text, + java.awt.TrayIcon.MessageType messageType) + throws NullPointerException + { + impl.displayMessage(caption, text, messageType); + } + + public void setIcon(ImageIcon icon) throws NullPointerException + { + impl.setImage(icon.getImage()); + } + + public void setIconAutoSize(boolean autoSize) + { + impl.setImageAutoSize(autoSize); + } + + java.awt.TrayIcon getImpl() + { + return impl; + } +} \ No newline at end of file -- cgit v1.1 From 98dc2c732e2ae6891d35cd0c024cc6975931fb32 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 18:45:58 +0200 Subject: Remove unused envelope icon --- resources/images/images.properties | 4 --- resources/images/impl/systray/envelope.png | Bin 756 -> 0 bytes resources/images/impl/systray/envelopeMacOSX.png | Bin 565 -> 0 bytes .../images/impl/systray/envelopeMacOSXWhite.png | Bin 554 -> 0 bytes resources/images/impl/systray/envelopeWindows.png | Bin 1431 -> 0 bytes .../impl/gui/main/contactlist/TreeContactList.java | 4 --- .../osdependent/jdic/SystrayServiceJdicImpl.java | 29 ++------------------- .../service/systray/SystrayService.java | 5 ---- 8 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 resources/images/impl/systray/envelope.png delete mode 100644 resources/images/impl/systray/envelopeMacOSX.png delete mode 100644 resources/images/impl/systray/envelopeMacOSXWhite.png delete mode 100644 resources/images/impl/systray/envelopeWindows.png diff --git a/resources/images/images.properties b/resources/images/images.properties index 482dc85..736cb54 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -408,10 +408,6 @@ service.systray.DOCK_ICON_EXTENDED_AWAY=resources/images/impl/systray/dock-exten service.systray.DOCK_ICON_FFC=resources/images/impl/systray/dock-chatty.png service.systray.DOCK_ICON_DND=resources/images/impl/systray/dock-dnd.png service.systray.STATUS_MENU_ICON=resources/images/impl/systray/statusIcon.png -service.systray.MESSAGE_ICON=resources/images/impl/systray/envelope.png -service.systray.MESSAGE_ICON_WINDOWS=resources/images/impl/systray/envelopeWindows.png -service.systray.MESSAGE_ICON_MACOSX=resources/images/impl/systray/envelopeMacOSX.png -service.systray.MESSAGE_ICON_MACOSX_WHITE=resources/images/impl/systray/envelopeMacOSXWhite.png service.systray.QUIT_MENU_ICON=resources/images/impl/gui/common/quit16x16.png service.systray.CONFIGURE_ICON=resources/images/impl/gui/common/configureIcon.png diff --git a/resources/images/impl/systray/envelope.png b/resources/images/impl/systray/envelope.png deleted file mode 100644 index 1d6b70a..0000000 Binary files a/resources/images/impl/systray/envelope.png and /dev/null differ diff --git a/resources/images/impl/systray/envelopeMacOSX.png b/resources/images/impl/systray/envelopeMacOSX.png deleted file mode 100644 index a19704b..0000000 Binary files a/resources/images/impl/systray/envelopeMacOSX.png and /dev/null differ diff --git a/resources/images/impl/systray/envelopeMacOSXWhite.png b/resources/images/impl/systray/envelopeMacOSXWhite.png deleted file mode 100644 index 2a11957..0000000 Binary files a/resources/images/impl/systray/envelopeMacOSXWhite.png and /dev/null differ diff --git a/resources/images/impl/systray/envelopeWindows.png b/resources/images/impl/systray/envelopeWindows.png deleted file mode 100644 index c0886c2..0000000 Binary files a/resources/images/impl/systray/envelopeWindows.png and /dev/null differ diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java index a916b2b..119e000 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java @@ -565,10 +565,6 @@ public class TreeContactList if (isActive) { activeContacts.add(contactNode); -// SystrayService stray = GuiActivator.getSystrayService(); -// -// if (stray != null) -// stray.setSystrayIcon(SystrayService.ENVELOPE_IMG_TYPE); } else activeContacts.remove(contactNode); diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index f1a744d..48d0f8c 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -93,10 +93,6 @@ public class SystrayServiceJdicImpl private ImageIcon logoIconWhite; - private ImageIcon envelopeIcon; - - private ImageIcon envelopeIconWhite; - /** * The dock Icons used only in Mac version */ @@ -206,8 +202,6 @@ public class SystrayServiceJdicImpl "service.systray.TRAY_ICON_WINDOWS_FFC"); logoIconDND = Resources.getImage( "service.systray.TRAY_ICON_WINDOWS_DND"); - envelopeIcon = Resources.getImage( - "service.systray.MESSAGE_ICON_WINDOWS"); } /* * If we're running under Mac OS X, we use special black and white icons @@ -218,10 +212,6 @@ public class SystrayServiceJdicImpl logoIcon = Resources.getImage("service.systray.TRAY_ICON_MACOSX"); logoIconWhite = Resources.getImage( "service.systray.TRAY_ICON_MACOSX_WHITE"); - envelopeIcon = Resources.getImage( - "service.systray.MESSAGE_ICON_MACOSX"); - envelopeIconWhite = Resources.getImage( - "service.systray.MESSAGE_ICON_MACOSX_WHITE"); } else { @@ -233,7 +223,6 @@ public class SystrayServiceJdicImpl "service.systray.TRAY_ICON_EXTENDED_AWAY"); logoIconFFC = Resources.getImage("service.systray.TRAY_ICON_FFC"); logoIconDND = Resources.getImage("service.systray.TRAY_ICON_DND"); - envelopeIcon = Resources.getImage("service.systray.MESSAGE_ICON"); } /* @@ -296,11 +285,7 @@ public class SystrayServiceJdicImpl { public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - ImageIcon newIcon - = (currentIcon == envelopeIcon) - ? envelopeIconWhite - : logoIconWhite; - + ImageIcon newIcon = logoIconWhite; trayIcon.setIcon(newIcon); currentIcon = newIcon; } @@ -308,11 +293,7 @@ public class SystrayServiceJdicImpl public void popupMenuWillBecomeInvisible( PopupMenuEvent e) { - ImageIcon newIcon - = (currentIcon == envelopeIconWhite) - ? envelopeIcon - : logoIcon; - + ImageIcon newIcon = logoIcon; getTrayIcon().setIcon(newIcon); currentIcon = newIcon; } @@ -402,12 +383,6 @@ public class SystrayServiceJdicImpl if (!isMac) systrayIconToSet = logoIconDND; break; - case SystrayService.ENVELOPE_IMG_TYPE: - systrayIconToSet - = (isMac && TrayMenuFactory.isVisible(menu)) - ? envelopeIconWhite - : envelopeIcon; - break; } if (systrayIconToSet != null) diff --git a/src/net/java/sip/communicator/service/systray/SystrayService.java b/src/net/java/sip/communicator/service/systray/SystrayService.java index 751abc6..4cabe2d 100644 --- a/src/net/java/sip/communicator/service/systray/SystrayService.java +++ b/src/net/java/sip/communicator/service/systray/SystrayService.java @@ -78,11 +78,6 @@ public interface SystrayService public static final int SC_IMG_EXTENDED_AWAY_TYPE = 6; /** - * Image type corresponding to the envelope icon - */ - public static final int ENVELOPE_IMG_TYPE = 1; - - /** * Shows the given PopupMessage * * @param popupMessage the message to show -- cgit v1.1 From 8bee4d318ea5a5bf29a83e02a5ec8d68e74434df Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 23:10:01 +0200 Subject: Stop messing with the JNA manifest and libraries --- build.xml | 15 +++------------ lib/felix.client.run.properties | 3 ++- lib/felix.unit.test.properties | 3 ++- lib/installer-exclude/jna.manifest.mf | 12 ------------ resources/install/build.xml | 4 ++-- 5 files changed, 9 insertions(+), 28 deletions(-) delete mode 100644 lib/installer-exclude/jna.manifest.mf diff --git a/build.xml b/build.xml index 75bea81..6bc941c 100644 --- a/build.xml +++ b/build.xml @@ -1053,7 +1053,7 @@ bundle-protocol,bundle-protocol-media,bundle-icq, bundle-icq-slick,bundle-mock,bundle-smacklib,bundle-jmdnslib, bundle-jabber,bundle-jabber-slick,bundle-swing-ui,bundle-ui-service, - bundle-jnalib,bundle-phonenumbers, + bundle-phonenumbers, bundle-irc,bundle-irc-commands,bundle-plugin-ircaccregwizz, bundle-yahoo,bundle-yahoo-slick, bundle-contactlist,meta-contactlist,meta-contactlist-slick, @@ -1129,6 +1129,8 @@ + + @@ -1596,17 +1598,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index c596e49..e36bf54 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -105,7 +105,8 @@ felix.auto.start.35= \ felix.auto.start.40= \ reference:file:sc-bundles/jmdnslib.jar \ - reference:file:sc-bundles/jnalib.jar \ + reference:file:sc-bundles/jna.jar \ + reference:file:sc-bundles/jna-platform.jar \ reference:file:sc-bundles/provdisc.jar \ reference:file:sc-bundles/jfontchooserlib.jar \ reference:file:sc-bundles/netaddr.jar \ diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index b4f1a7f..5db3a83 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -112,7 +112,8 @@ felix.auto.start.40= \ reference:file:sc-bundles/jfontchooserlib.jar \ reference:file:sc-bundles/version-impl.jar \ reference:file:sc-bundles/keybindings.jar \ - reference:file:sc-bundles/jnalib.jar \ + reference:file:sc-bundles/jna.jar \ + reference:file:sc-bundles/jna-platform.jar \ reference:file:sc-bundles/netaddr.jar \ reference:file:sc-bundles/sysactivitynotifications.jar \ reference:file:sc-bundles/browserlauncher.jar \ diff --git a/lib/installer-exclude/jna.manifest.mf b/lib/installer-exclude/jna.manifest.mf deleted file mode 100644 index 0c32920..0000000 --- a/lib/installer-exclude/jna.manifest.mf +++ /dev/null @@ -1,12 +0,0 @@ -Bundle-Name: JNA Lib Provider -Bundle-Description: JNA Lib Provider -Bundle-Vendor: sip-communicator.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: com.sun.jna -Export-Package: com.sun.jna.win32, - com.sun.jna, - com.sun.jna.ptr, - com.sun.jna.platform, - com.sun.jna.platform.win32 - - diff --git a/resources/install/build.xml b/resources/install/build.xml index 6693513..88ec725 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -584,7 +584,7 @@ - + @@ -1204,7 +1204,7 @@ - + -- cgit v1.1 From 8c1b1b17cde4acdf75220f18b559b4ca616601d4 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 23:11:41 +0200 Subject: Add a notification cleared event --- .../impl/gui/main/UINotificationGroup.java | 5 +++++ .../impl/gui/main/UINotificationListener.java | 7 +++++++ .../impl/gui/main/UINotificationManager.java | 19 +++++++++++++++++++ .../impl/gui/main/call/CallHistoryButton.java | 8 ++++++++ 4 files changed, 39 insertions(+) diff --git a/src/net/java/sip/communicator/impl/gui/main/UINotificationGroup.java b/src/net/java/sip/communicator/impl/gui/main/UINotificationGroup.java index a2e3673..fb14645 100644 --- a/src/net/java/sip/communicator/impl/gui/main/UINotificationGroup.java +++ b/src/net/java/sip/communicator/impl/gui/main/UINotificationGroup.java @@ -99,7 +99,12 @@ public class UINotificationGroup { synchronized (unreadNotifications) { + List copy = new ArrayList<>(unreadNotifications); unreadNotifications.clear(); + for (UINotification n : copy) + { + UINotificationManager.fireClearedEvent(n); + } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/UINotificationListener.java b/src/net/java/sip/communicator/impl/gui/main/UINotificationListener.java index fc5568d..932d96c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/UINotificationListener.java +++ b/src/net/java/sip/communicator/impl/gui/main/UINotificationListener.java @@ -32,4 +32,11 @@ public interface UINotificationListener * @param notification the notification that was received */ public void notificationReceived(UINotification notification); + + /** + * Indicates that a notification has been cleared. + * + * @param notification the notification that was cleared. + */ + public void notificationCleared(UINotification notification); } diff --git a/src/net/java/sip/communicator/impl/gui/main/UINotificationManager.java b/src/net/java/sip/communicator/impl/gui/main/UINotificationManager.java index b6001f7..2d42233 100644 --- a/src/net/java/sip/communicator/impl/gui/main/UINotificationManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/UINotificationManager.java @@ -150,4 +150,23 @@ public class UINotificationManager listeners.next().notificationReceived(notification); } } + + + /** + * Notifies interested UINotificationListener that a + * notification has been cleared. + * + * @param notification the cleared notification + */ + static void fireClearedEvent(UINotification notification) + { + synchronized (notificationListeners) + { + Iterator listeners + = notificationListeners.iterator(); + + while (listeners.hasNext()) + listeners.next().notificationCleared(notification); + } + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java b/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java index 095b3dd..d1c0a42 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallHistoryButton.java @@ -130,6 +130,14 @@ public class CallHistoryButton } /** + * Does nothing because this class causes the clearing. + */ + @Override + public void notificationCleared(UINotification notification) + { + } + + /** * Sets the history view. */ private void setHistoryView() -- cgit v1.1 From 7f08c0d239e1c63ebb44dc025d7507017d5d1add Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 23:12:37 +0200 Subject: Forward pending notification count to the systray service --- .../sip/communicator/impl/gui/UIServiceImpl.java | 41 +++++++++++++++++++++- .../service/systray/AbstractSystrayService.java | 9 +++++ .../service/systray/SystrayService.java | 6 ++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java index 2e8735f..838e86e 100644 --- a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java +++ b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java @@ -74,7 +74,8 @@ public class UIServiceImpl implements UIService, ShutdownService, ServiceListener, - PropertyChangeListener + PropertyChangeListener, + UINotificationListener { /** * The Logger used by the UIServiceImpl class and its @@ -140,6 +141,7 @@ public class UIServiceImpl */ public UIServiceImpl() { + UINotificationManager.addNotificationListener(this); } /** @@ -1642,4 +1644,41 @@ public class UIServiceImpl ChatRoomAutoOpenConfigDialog.showChatRoomAutoOpenConfigDialog( pps, chatRoomId); } + + /** + * Counts the number of unread notifications and forwards the sum to the + * systray service. + */ + @Override + public void notificationReceived(UINotification notification) + { + forwardNotificationCount(); + } + + /** + * Counts the number of unread notifications and forwards the sum to the + * systray service. + */ + @Override + public void notificationCleared(UINotification notification) + { + forwardNotificationCount(); + } + + private void forwardNotificationCount() + { + int count = 0; + for (UINotificationGroup g : UINotificationManager + .getNotificationGroups()) + { + Iterator it = + UINotificationManager.getUnreadNotifications(g); + while (it.hasNext()) + { + count += it.next().getUnreadObjects(); + } + } + + GuiActivator.getSystrayService().setNotificationCount(count); + } } diff --git a/src/net/java/sip/communicator/service/systray/AbstractSystrayService.java b/src/net/java/sip/communicator/service/systray/AbstractSystrayService.java index 6b4c430..60114f9 100644 --- a/src/net/java/sip/communicator/service/systray/AbstractSystrayService.java +++ b/src/net/java/sip/communicator/service/systray/AbstractSystrayService.java @@ -128,6 +128,15 @@ public abstract class AbstractSystrayService } /** + * Stub method that does nothing. + * @param count ignored + */ + @Override + public void setNotificationCount(int count) + { + } + + /** * Implements the SystrayService.addPopupMessageListener method. * If activePopupHandler is still not available record the listener * so we can add him later. diff --git a/src/net/java/sip/communicator/service/systray/SystrayService.java b/src/net/java/sip/communicator/service/systray/SystrayService.java index 4cabe2d..bcde841 100644 --- a/src/net/java/sip/communicator/service/systray/SystrayService.java +++ b/src/net/java/sip/communicator/service/systray/SystrayService.java @@ -130,4 +130,10 @@ public interface SystrayService * @return True if the systray is initialized, false otherwise. */ public boolean checkInitialized(); + + /** + * Set the number that should be shown as an overlay on the try icon. + * @param count The number of pending notifications. + */ + public void setNotificationCount(int count); } -- cgit v1.1 From 5c24dad320f355f721fc4562fbed7ecf72b66d50 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 29 May 2016 23:13:19 +0200 Subject: Show pending notifications on OSX and Windows --- .../osdependent/jdic/SystrayServiceJdicImpl.java | 79 ++++++++++ .../impl/osdependent/osdependent.manifest.mf | 18 ++- .../impl/osdependent/windows/ImageConverter.java | 172 +++++++++++++++++++++ .../impl/osdependent/windows/TaskBarList3.java | 150 ++++++++++++++++++ .../impl/osdependent/windows/User32Ex.java | 47 ++++++ 5 files changed, 460 insertions(+), 6 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/osdependent/windows/ImageConverter.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/windows/TaskBarList3.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/windows/User32Ex.java diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index 48d0f8c..6fd9d8c 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.osdependent.jdic; import java.awt.*; import java.awt.event.*; +import java.awt.image.*; import java.net.*; import javax.swing.*; @@ -27,6 +28,7 @@ import javax.swing.event.*; import net.java.sip.communicator.impl.osdependent.*; import net.java.sip.communicator.impl.osdependent.systemtray.SystemTray; import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; +import net.java.sip.communicator.impl.osdependent.windows.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.systray.*; @@ -453,6 +455,83 @@ public class SystrayServiceJdicImpl } /** + * Set the number of pending notifications to the the application icon + * (Dock on OSX, TaskBar on Windows, nothing on Linux currently). + */ + @Override + public void setNotificationCount(int count) + { + if (OSUtils.IS_MAC) + { + Application application = Application.getApplication(); + application.setDockIconBadge(new Integer(count).toString()); + } + else if (OSUtils.IS_WINDOWS) + { + UIService uiService = OsDependentActivator.getUIService(); + if (uiService == null) + { + return; + } + + ExportedWindow mainWindow = + uiService.getExportedWindow(ExportedWindow.MAIN_WINDOW); + if (mainWindow == null + || !(mainWindow.getSource() instanceof Component)) + { + return; + } + + BufferedImage img = null; + if (count > 0) + { + img = createOverlayImage(new Integer(count).toString()); + } + + try + { + TaskBarList3.getInstance().SetOverlayIcon( + (Component) mainWindow.getSource(), img, null); + } + catch (Exception ex) + { + logger.error("Could not set the notification count.", ex); + } + } + } + + private BufferedImage createOverlayImage(String text) + { + int size = 16; + BufferedImage image = + new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + //background + g.setPaint(new Color(0, 0, 0, 102)); + g.fillRoundRect(0, 0, size, size, size, size); + + //filling + int mainRadius = 14; + g.setPaint(new Color(255, 98, 89)); + g.fillRoundRect(size / 2 - mainRadius / 2, size / 2 - mainRadius / 2, + mainRadius, mainRadius, size, size); + + //text + Font font = g.getFont(); + g.setFont(new Font(font.getName(), Font.BOLD, 9)); + FontMetrics fontMetrics = g.getFontMetrics(); + int textWidth = fontMetrics.stringWidth(text); + g.setColor(Color.white); + g.drawString(text, size / 2 - textWidth / 2, + size / 2 - fontMetrics.getHeight() / 2 + fontMetrics.getAscent()); + + return image; + } + + /** * @return the trayIcon */ public TrayIcon getTrayIcon() diff --git a/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf b/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf index 0db99ad..bc56371 100644 --- a/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf +++ b/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf @@ -5,21 +5,23 @@ Bundle-Vendor: jitsi.org Bundle-Version: 0.0.1 Bundle-SymbolicName: net.java.sip.communicator.osdependent Export-Package: net.java.sip.communicator.service.desktop -Import-Package: org.osgi.framework, - com.apple.cocoa.application, +Import-Package: com.apple.cocoa.application, com.apple.cocoa.foundation, com.apple.eawt, - org.jitsi.service.configuration, + com.sun.jna, + com.sun.jna.platform.win32, + com.sun.jna.platform.win32.COM, + com.sun.jna.ptr, + com.sun.jna.win32, net.java.sip.communicator.service.gui, net.java.sip.communicator.service.gui.event, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.globalstatus, net.java.sip.communicator.service.protocol.event, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.resources, net.java.sip.communicator.service.shutdown, net.java.sip.communicator.service.systray, net.java.sip.communicator.service.systray.event, - org.jitsi.util, net.java.sip.communicator.util, net.java.sip.communicator.plugin.desktoputil, net.java.sip.communicator.plugin.desktoputil.presence, @@ -36,4 +38,8 @@ Import-Package: org.osgi.framework, javax.swing.text, javax.swing.text.html, javax.swing.tree, - javax.swing.undo + javax.swing.undo, + org.jitsi.service.configuration, + org.jitsi.service.resources, + org.jitsi.util, + org.osgi.framework diff --git a/src/net/java/sip/communicator/impl/osdependent/windows/ImageConverter.java b/src/net/java/sip/communicator/impl/osdependent/windows/ImageConverter.java new file mode 100644 index 0000000..99754d3 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/windows/ImageConverter.java @@ -0,0 +1,172 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright 2000-2016 JetBrains s.r.o. + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */package net.java.sip.communicator.impl.osdependent.windows; + +import java.awt.image.*; +import java.nio.*; + +import com.sun.jna.*; +import com.sun.jna.platform.win32.*; +import com.sun.jna.platform.win32.WinDef.*; + +/** + * Image conversion utilities. + * + * Parts of this code are based on AppIcon.java from IntelliJ community. + * Licensed under Apache 2.0, Copyright 2000-2016 JetBrains s.r.o. + */ +public class ImageConverter +{ + /** + * Converts the BufferedImage to an ICONDIR structure. + * @param src The source image to convert + * @return an ICONDIR structure with the data of the passed source image + */ + public static byte[] writeTransparentIcoImage(BufferedImage src) + { + int bitCount = 32; + + int scanline_size = (bitCount * src.getWidth() + 7) / 8; + if ((scanline_size % 4) != 0) + scanline_size += 4 - (scanline_size % 4); // pad scanline to 4 byte + // size. + int t_scanline_size = (src.getWidth() + 7) / 8; + if ((t_scanline_size % 4) != 0) + t_scanline_size += 4 - (t_scanline_size % 4); // pad scanline to 4 + // byte size. + int imageSize = 40 + src.getHeight() * scanline_size + + src.getHeight() * t_scanline_size; + + // sizeof(ICONDIR) + // + sizeof(ICONDIRENTRY) + // + (sizeof(BITMAPINFOHEADER)+data) + ByteBuffer bos = ByteBuffer.allocate(6 + 16 + imageSize); + bos.order(ByteOrder.LITTLE_ENDIAN); + + // ICONDIR + bos.putShort((short) 0); // reserved + bos.putShort((short) 1); // 1=ICO, 2=CUR + bos.putShort((short) 1); // count + + // ICONDIRENTRY + int iconDirEntryWidth = src.getWidth(); + int iconDirEntryHeight = src.getHeight(); + if (iconDirEntryWidth > 255 || iconDirEntryHeight > 255) + { + iconDirEntryWidth = 0; + iconDirEntryHeight = 0; + } + bos.put((byte) iconDirEntryWidth); + bos.put((byte) iconDirEntryHeight); + bos.put((byte) 0); + bos.put((byte) 0); // reserved + bos.putShort((short) 1); // color planes + bos.putShort((short) bitCount); + bos.putInt(imageSize); + bos.putInt(22); // image offset + + // BITMAPINFOHEADER + bos.putInt(40); // size + bos.putInt(src.getWidth()); + bos.putInt(2 * src.getHeight()); + bos.putShort((short) 1); // planes + bos.putShort((short) bitCount); + bos.putInt(0); // compression + bos.putInt(0); // image size + bos.putInt(0); // x pixels per meter + bos.putInt(0); // y pixels per meter + bos.putInt(0); // colors used, 0 = (1 << bitCount) (ignored) + bos.putInt(0); // colors important + + int bit_cache = 0; + int bits_in_cache = 0; + int row_padding = scanline_size - (bitCount * src.getWidth() + 7) / 8; + for (int y = src.getHeight() - 1; y >= 0; y--) + { + for (int x = 0; x < src.getWidth(); x++) + { + int argb = src.getRGB(x, y); + + bos.put((byte) (0xff & argb)); + bos.put((byte) (0xff & (argb >> 8))); + bos.put((byte) (0xff & (argb >> 16))); + bos.put((byte) (0xff & (argb >> 24))); + } + + for (int x = 0; x < row_padding; x++) + bos.put((byte) 0); + } + + int t_row_padding = t_scanline_size - (src.getWidth() + 7) / 8; + for (int y = src.getHeight() - 1; y >= 0; y--) + { + for (int x = 0; x < src.getWidth(); x++) + { + int argb = src.getRGB(x, y); + int alpha = 0xff & (argb >> 24); + bit_cache <<= 1; + if (alpha == 0) + bit_cache |= 1; + bits_in_cache++; + if (bits_in_cache >= 8) + { + bos.put((byte) (0xff & bit_cache)); + bit_cache = 0; + bits_in_cache = 0; + } + } + + if (bits_in_cache > 0) + { + bit_cache <<= (8 - bits_in_cache); + bos.put((byte) (0xff & bit_cache)); + bit_cache = 0; + bits_in_cache = 0; + } + + for (int x = 0; x < t_row_padding; x++) + bos.put((byte) 0); + } + + byte[] result = new byte[bos.position()]; + System.arraycopy(bos.array(), 0, result, 0, bos.position()); + return result; + } + + /** + * Converts an ICONDIR ico to an HICON handle + * @param ico the image data + * @return A Windows HICON handle + */ + public static HICON createIcon(byte[] ico) + { + Memory buffer = new Memory(ico.length); + buffer.write(0, ico, 0, ico.length); + int nSize = 100; + int offset = User32Ex.INSTANCE.LookupIconIdFromDirectoryEx(buffer, true, + nSize, nSize, 0); + if (offset != 0) + { + return User32Ex.INSTANCE.CreateIconFromResourceEx( + buffer.share(offset), new WinDef.DWORD(0), true, + new WinDef.DWORD(0x00030000), nSize, nSize, 0); + } + + return null; + } +} diff --git a/src/net/java/sip/communicator/impl/osdependent/windows/TaskBarList3.java b/src/net/java/sip/communicator/impl/osdependent/windows/TaskBarList3.java new file mode 100644 index 0000000..a21cd8f --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/windows/TaskBarList3.java @@ -0,0 +1,150 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.windows; + +import java.awt.*; +import java.awt.image.*; + +import org.jitsi.util.*; + +import com.sun.jna.*; +import com.sun.jna.platform.win32.*; +import com.sun.jna.platform.win32.COM.*; +import com.sun.jna.platform.win32.Guid.*; +import com.sun.jna.platform.win32.WinDef.*; +import com.sun.jna.platform.win32.WinNT.*; +import com.sun.jna.ptr.*; + +/** + * JNA wrapper for the ITaskBarList3 COM interface. + * https://msdn.microsoft.com/en-us/library/dd391696(v=vs.85).aspx + * + * @author Ingo Bauersachs + */ +public class TaskBarList3 + extends Unknown +{ + private static final GUID CLSID_TaskbarList = + new GUID("{56FDF344-FD6D-11d0-958A-006097C9A090}"); + + private static final GUID IID_ITaskbarList3 = + new GUID("{ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf}"); + + private static TaskBarList3 instance; + + /** + * Gets the ITaskBarList3 interface and initializes it with HrInit + * @return A ready to use TaskBarList3 object. + * @throws COMException when the interface could not be accessed + */ + public static TaskBarList3 getInstance() + { + if (instance == null && OSUtils.IS_WINDOWS) + { + Ole32.INSTANCE.CoInitializeEx(Pointer.NULL, 0); + PointerByReference p = new PointerByReference(); + WinNT.HRESULT hr = + Ole32.INSTANCE.CoCreateInstance(CLSID_TaskbarList, Pointer.NULL, + ObjBase.CLSCTX_ALL, IID_ITaskbarList3, p); + COMUtils.checkRC(hr); + instance = new TaskBarList3(p.getValue()); + } + + return instance; + } + + private TaskBarList3(Pointer p) + { + super(p); + HrInit(); + } + + // VTable + // ------ + // IUnknown: + // 0: AddRef + // 1: QueryInterface + // 2: Release + // + // ITaskBarList: + // 3: HrInit + // 4: AddTab + // 5: DeleteTab + // 6: ActivateTab + // 7: SetActiveAlt + // + // ITaskBarList2 + // 8: MarkFullscreenWindow + // + // ITaskBarList3: + // 9: SetProgressValue + // 10: SetProgressState + // 11: RegisterTab + // 12: UnregisterTab + // 13: SetTabOrder + // 14: SetTabActive + // 15: ThumbBarAddButtons + // 16: ThumbBarAddButtons + // 17: ThumbBarSetImageList + // 18: SetOverlayIcon + // 19: SetThumbnailTooltip + // 20: SetThumbnailClip + // + // ITaskbarList4: + // 21: SetTabProperties + + /** + * https://msdn.microsoft.com/en-us/library/bb774650(v=vs.85).aspx + */ + private void HrInit() + { + int hr = this._invokeNativeInt(3, new Object[] + { this.getPointer() }); + COMUtils.checkRC(new HRESULT(hr)); + } + + /** + * https://msdn.microsoft.com/en-us/library/dd391696(v=vs.85).aspx + */ + private void SetOverlayIcon(HWND hwnd, HICON hIcon, String pszDescription) + { + int hr = this._invokeNativeInt(18, new Object[] + { this.getPointer(), hwnd, hIcon, pszDescription }); + COMUtils.checkRC(new HRESULT(hr)); + } + + /** + * Sets an overlay image to the taskbar icon. + * @param frame The window that should receive the overlay + * @param image The overlay image, can be null to clear the overlay + * @param description An optional tooltip text, can be null + */ + public void SetOverlayIcon(Component frame, BufferedImage image, + String description) + { + HICON ico = null; + if (image != null) + { + byte[] iconBytes = ImageConverter.writeTransparentIcoImage(image); + ico = ImageConverter.createIcon(iconBytes); + } + + HWND hwnd = new HWND(Native.getComponentPointer(frame)); + SetOverlayIcon(hwnd, ico, description); + } +} diff --git a/src/net/java/sip/communicator/impl/osdependent/windows/User32Ex.java b/src/net/java/sip/communicator/impl/osdependent/windows/User32Ex.java new file mode 100644 index 0000000..59f3a7a --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/windows/User32Ex.java @@ -0,0 +1,47 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.windows; + +import com.sun.jna.*; +import com.sun.jna.platform.win32.*; +import com.sun.jna.win32.*; + +/** + * Extension to missing user32 Windows APIs + * + * @author Ingo Bauersachs + */ +interface User32Ex + extends StdCallLibrary +{ + User32Ex INSTANCE = (User32Ex) Native.loadLibrary("user32", User32Ex.class, + W32APIOptions.DEFAULT_OPTIONS); + + /** + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms648074(v=vs.85).aspx + */ + int LookupIconIdFromDirectoryEx(Memory presbits, boolean fIcon, + int cxDesired, int cyDesired, int Flags); + + /** + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms648061(v=vs.85).aspx + */ + WinDef.HICON CreateIconFromResourceEx(Pointer pbIconBits, + WinDef.DWORD cbIconBits, boolean fIcon, WinDef.DWORD dwVersion, + int cxDesired, int cyDesired, int uFlags); +} \ No newline at end of file -- cgit v1.1 From fb339a3e67af942c0f1a81e66a3573cadf59fef3 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 30 May 2016 00:55:12 +0200 Subject: Add option to minimize the main frame on closing instead of hiding Defaults to true on Windows if the application is pinned to the taskbar. Determined by searching for a shortcut with the application's name in the pin-folder. --- resources/languages/resources.properties | 1 + .../sip/communicator/impl/gui/UIServiceImpl.java | 13 +++-- .../sip/communicator/impl/gui/main/MainFrame.java | 4 ++ .../generalconfig/GeneralConfigurationPanel.java | 36 ++++++++++-- .../sip/communicator/util/ConfigurationUtils.java | 64 ++++++++++++++++++++++ .../java/sip/communicator/util/UtilActivator.java | 18 ++++++ .../java/sip/communicator/util/util.manifest.mf | 1 + 7 files changed, 128 insertions(+), 9 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 9eb8a78..45da14a 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1089,6 +1089,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Always assume packet loss: plugin.generalconfig.SILK_SAT=Speech activity threshold (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Advertise FEC support in SDP: plugin.generalconfig.RESTORE=Restore defaults +plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimize the main window instead of hiding it # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish diff --git a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java index 838e86e..b7e1d9c 100644 --- a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java +++ b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java @@ -199,8 +199,11 @@ public class UIServiceImpl } } - if(ConfigurationUtils.isApplicationVisible()) + if(ConfigurationUtils.isApplicationVisible() + || ConfigurationUtils.isMinimizeInsteadOfHide()) + { mainFrame.setFrameVisible(true); + } SwingUtilities.invokeLater(new RunLoginGui()); @@ -440,9 +443,11 @@ public class UIServiceImpl */ public void setExitOnMainWindowClose(boolean exitOnMainWindowClose) { - mainFrame.setDefaultCloseOperation( - exitOnMainWindowClose - ? JFrame.DISPOSE_ON_CLOSE + mainFrame.setDefaultCloseOperation( + exitOnMainWindowClose + ? JFrame.DISPOSE_ON_CLOSE + : ConfigurationUtils.isMinimizeInsteadOfHide() + ? JFrame.DO_NOTHING_ON_CLOSE : JFrame.HIDE_ON_CLOSE); } diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java index fb7e01c..4762df8 100644 --- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java @@ -1943,6 +1943,10 @@ public class MainFrame }); ConfigurationUtils.setApplicationVisible(false); + if (ConfigurationUtils.isMinimizeInsteadOfHide()) + { + this.minimize(); + } } } diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java index f5e482a..6319455 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java @@ -237,6 +237,30 @@ public class GeneralConfigurationPanel } /** + * Initializes the minimize instead of hide checkbox. + */ + public Component createMinimzeInsteadOfHideCheckBox() + { + JCheckBox chk = new SIPCommCheckBox(); + + chk.setText( + Resources.getString("plugin.generalconfig.MINIMIZE_NOT_HIDE")); + chk.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + boolean value = ((JCheckBox) e.getSource()).isSelected(); + ConfigurationUtils.setIsMinimizeInsteadOfHide(value); + UtilActivator.getUIService().setExitOnMainWindowClose( + !UtilActivator.getSystrayService().checkInitialized()); + } + }); + + chk.setSelected(ConfigurationUtils.isMinimizeInsteadOfHide()); + return chk; + } + + /** * Creates the message configuration panel. * @return the created panel */ @@ -959,15 +983,17 @@ public class GeneralConfigurationPanel */ public Component createStartupConfigPanel() { - if (!OSUtils.IS_WINDOWS) - return null; - JPanel updateConfigPanel = GeneralConfigPluginActivator. createConfigSectionComponent( Resources.getString("plugin.generalconfig.STARTUP_CONFIG")); - updateConfigPanel.add(createAutoStartCheckBox()); - updateConfigPanel.add(createUpdateCheckBox()); + updateConfigPanel.add(createMinimzeInsteadOfHideCheckBox()); + if (OSUtils.IS_WINDOWS) + { + updateConfigPanel.add(createAutoStartCheckBox()); + updateConfigPanel.add(createUpdateCheckBox()); + } + return updateConfigPanel; } diff --git a/src/net/java/sip/communicator/util/ConfigurationUtils.java b/src/net/java/sip/communicator/util/ConfigurationUtils.java index 05e4f09..db9fa3b 100644 --- a/src/net/java/sip/communicator/util/ConfigurationUtils.java +++ b/src/net/java/sip/communicator/util/ConfigurationUtils.java @@ -92,6 +92,11 @@ public class ConfigurationUtils private static boolean isQuitWarningShown = true; /** + * Indicates if the main frame should be minimized instead of hidden. + */ + private static boolean minimizeInsteadOfHide = false; + + /** * Indicates if typing notifications should be sent. */ private static boolean isSendTypingNotifications; @@ -479,6 +484,10 @@ public class ConfigurationUtils = Boolean.parseBoolean(quitWarningShown); } + minimizeInsteadOfHide = configService.getBoolean( + "net.java.sip.communicator.impl.gui.minimizeInsteadOfHide", + isPinnedToTaskBar()); + // Load the "sendTypingNotifications" property. String isSendTypingNotifProperty = "service.gui.SEND_TYPING_NOTIFICATIONS_ENABLED"; @@ -964,6 +973,37 @@ public class ConfigurationUtils ); } + private static boolean isPinnedToTaskBar() + { + if (!OSUtils.IS_WINDOWS) + { + return false; + } + + File taskbar = new File(System.getenv("appdata"), + "Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar"); + File[] pins = taskbar.listFiles(new FileFilter() + { + @Override + public boolean accept(File f) + { + return f.getName().endsWith(".lnk"); + } + }); + + String title = UtilActivator.getResources() + .getSettingsString("service.gui.APPLICATION_NAME"); + for (File pin : pins) + { + if (pin.getName().contains(title)) + { + return true; + } + } + + return false; + } + /** * Checks whether font support is disabled, checking in default * settings for the default value. @@ -1055,6 +1095,30 @@ public class ConfigurationUtils } /** + * Gets whether the application should be minimized and not hidden when + * clicking close on the main frame. + * @return true when the main frame should be minimized, + * false otherwise + */ + public static boolean isMinimizeInsteadOfHide() + { + return minimizeInsteadOfHide; + } + + /** + * Sets whether the application should be minimized and not hidden when + * clicking close on the main frame. + * @param value true when the main frame should be minimized, + * false otherwise + */ + public static void setIsMinimizeInsteadOfHide(boolean value) + { + minimizeInsteadOfHide = value; + configService.setProperty( + "net.java.sip.communicator.impl.gui.minimizeInsteadOfHide", value); + } + + /** * Return TRUE if "quitWarningShown" property is true, otherwise - * return FALSE. Indicates to the user interface whether the quit warning * dialog should be shown when user clicks on the X button. diff --git a/src/net/java/sip/communicator/util/UtilActivator.java b/src/net/java/sip/communicator/util/UtilActivator.java index c2ee299..6dff186 100644 --- a/src/net/java/sip/communicator/util/UtilActivator.java +++ b/src/net/java/sip/communicator/util/UtilActivator.java @@ -22,6 +22,7 @@ import java.util.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.service.systray.*; import org.jitsi.service.configuration.*; import org.jitsi.service.fileaccess.*; @@ -65,6 +66,8 @@ public class UtilActivator private static AlertUIService alertUIService; + private static SystrayService systrayService; + /** * Calls Thread.setUncaughtExceptionHandler() * @@ -184,6 +187,21 @@ public class UtilActivator } /** + * Gets the SystrayService instance registered in the + * BundleContext of the UtilActivator. + * + * @return the SystrayService instance registered in the + * BundleContext of the UtilActivator + */ + public static SystrayService getSystrayService() + { + if (systrayService == null) + systrayService = + ServiceUtils.getService(bundleContext, SystrayService.class); + return systrayService; + } + + /** * Returns the FileAccessService obtained from the bundle context. * * @return the FileAccessService obtained from the bundle context diff --git a/src/net/java/sip/communicator/util/util.manifest.mf b/src/net/java/sip/communicator/util/util.manifest.mf index a6e4db7..b50df6b 100644 --- a/src/net/java/sip/communicator/util/util.manifest.mf +++ b/src/net/java/sip/communicator/util/util.manifest.mf @@ -32,6 +32,7 @@ Import-Package: com.sun.awt, net.java.sip.communicator.service.gui, net.java.sip.communicator.service.gui.call, net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.systray, net.java.sip.communicator.service.keybindings, net.java.sip.communicator.service.msghistory, net.java.sip.communicator.service.contactlist, -- cgit v1.1 From 23968481aa2a4fbd6f2e6405e1188b770550ef99 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 30 May 2016 22:09:15 +0200 Subject: Prevent removal of manifest in stripped jars --- resources/install/build.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/install/build.xml b/resources/install/build.xml index 6693513..876df99 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -147,7 +147,7 @@ - + @@ -163,7 +163,7 @@ - + -- cgit v1.1 From 0a6acc19ce25a4dab892bca94a45e2c4ceb50796 Mon Sep 17 00:00:00 2001 From: damencho Date: Mon, 30 May 2016 22:11:57 -0500 Subject: Fixes debian build after 5c24dad320f355f721fc4562fbed7ecf72b66d50. --- resources/install/build.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/install/build.xml b/resources/install/build.xml index 3cd0c6b..52ff7b5 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -2611,7 +2611,6 @@ - -- cgit v1.1 From 1a9fec52218d8c1b1f1feb1706d6c06efa8a56a0 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 31 May 2016 22:08:03 +0200 Subject: Fix Debian based launcher dnsjava is an available package, but too old on e.g. Ubuntu 14.04. Put the embedded library on the classpath. Needs to be changed to /usr/share/java/dnsjava.jar for the Debian src upload. --- resources/install/debian/jitsi.sh.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/debian/jitsi.sh.tmpl b/resources/install/debian/jitsi.sh.tmpl index 7963135..5e8677d 100644 --- a/resources/install/debian/jitsi.sh.tmpl +++ b/resources/install/debian/jitsi.sh.tmpl @@ -30,7 +30,7 @@ javabin=`which java` SCDIR=/usr/share/_PACKAGE_NAME_ JITSI_COMMON_DIR=/usr/share/_PACKAGE_NAME_-common LIBPATH=$SCDIR/lib -CLASSPATH=/usr/share/java/org.apache.felix.framework.jar:/usr/share/java/org.apache.felix.main.jar:/usr/share/java/dnsjava.jar:$SCDIR/sc-bundles/sc-launcher.jar:$JITSI_COMMON_DIR/util.jar/launchutils.jar:$LIBPATH +CLASSPATH=/usr/share/java/org.apache.felix.framework.jar:/usr/share/java/org.apache.felix.main.jar:$SCDIR/sc-bundles/dnsjava.jar:$SCDIR/sc-bundles/sc-launcher.jar:$JITSI_COMMON_DIR/util.jar/launchutils.jar:$LIBPATH FELIX_CONFIG=$LIBPATH/felix.client.run.properties LOG_CONFIG=$LIBPATH/logging.properties COMMAND="$javabin $CLIENTARGS -classpath $CLASSPATH -Djna.library.path=/usr/lib/jni -Dfelix.config.properties=file:$FELIX_CONFIG -Djava.util.logging.config.file=$LOG_CONFIG $SPLASH_ARG net.java.sip.communicator.launcher.SIPCommunicator" -- cgit v1.1 From 8711c2829244d8baef1610715d2a68f7a2b7bdbf Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:23:40 +0200 Subject: Remove dict protocol It has been abandoned since Oct. 2010 --- .classpath | 1 - build.xml | 21 - lib/installer-exclude/dict4j.jar | Bin 10805 -> 0 bytes lib/installer-exclude/hexdump-0.2.jar | Bin 1633 -> 0 bytes .../impl/protocol/dict/ContactDictImpl.java | 343 ------- .../impl/protocol/dict/ContactGroupDictImpl.java | 588 ------------ .../impl/protocol/dict/DictAccountID.java | 70 -- .../impl/protocol/dict/DictActivator.java | 146 --- .../impl/protocol/dict/DictStatusEnum.java | 88 -- .../impl/protocol/dict/MessageDictImpl.java | 46 - .../OperationSetBasicInstantMessagingDictImpl.java | 412 --------- .../OperationSetPersistentPresenceDictImpl.java | 988 --------------------- .../impl/protocol/dict/ProtocolIconDictImpl.java | 133 --- .../dict/ProtocolProviderFactoryDictImpl.java | 200 ----- .../dict/ProtocolProviderServiceDictImpl.java | 364 -------- .../impl/protocol/dict/dict.provider.manifest.mf | 15 - .../dictaccregwizz/DictAccRegWizzActivator.java | 151 ---- .../dictaccregwizz/DictAccountRegistration.java | 104 --- .../DictAccountRegistrationWizard.java | 429 --------- .../plugin/dictaccregwizz/FirstWizardPage.java | 637 ------------- .../plugin/dictaccregwizz/ProgressPanel.java | 156 ---- .../plugin/dictaccregwizz/Resources.java | 75 -- .../plugin/dictaccregwizz/StrategiesList.java | 240 ----- .../plugin/dictaccregwizz/ThreadManager.java | 199 ----- .../dictaccregwizz/dictaccregwizz.manifest.mf | 34 - 25 files changed, 5440 deletions(-) delete mode 100755 lib/installer-exclude/dict4j.jar delete mode 100644 lib/installer-exclude/hexdump-0.2.jar delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/ContactDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/ContactGroupDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/DictAccountID.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/DictActivator.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/DictStatusEnum.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/MessageDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/OperationSetBasicInstantMessagingDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/OperationSetPersistentPresenceDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/ProtocolIconDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderFactoryDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderServiceDictImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/dict/dict.provider.manifest.mf delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistration.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/FirstWizardPage.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/ProgressPanel.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/Resources.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/StrategiesList.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/ThreadManager.java delete mode 100644 src/net/java/sip/communicator/plugin/dictaccregwizz/dictaccregwizz.manifest.mf diff --git a/.classpath b/.classpath index 62e52bd..ee1728a 100755 --- a/.classpath +++ b/.classpath @@ -13,7 +13,6 @@ - diff --git a/build.xml b/build.xml index 6bc941c..b80d638 100644 --- a/build.xml +++ b/build.xml @@ -2202,27 +2202,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - - - - - diff --git a/lib/installer-exclude/dict4j.jar b/lib/installer-exclude/dict4j.jar deleted file mode 100755 index 7eb9813..0000000 Binary files a/lib/installer-exclude/dict4j.jar and /dev/null differ diff --git a/lib/installer-exclude/hexdump-0.2.jar b/lib/installer-exclude/hexdump-0.2.jar deleted file mode 100644 index 4fb5ee1..0000000 Binary files a/lib/installer-exclude/hexdump-0.2.jar and /dev/null differ diff --git a/src/net/java/sip/communicator/impl/protocol/dict/ContactDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/ContactDictImpl.java deleted file mode 100644 index 924c0f7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/ContactDictImpl.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import net.java.dict4j.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * An implementation of a Dict contact - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class ContactDictImpl - extends AbstractContact -{ - private Logger logger = Logger.getLogger(ContactDictImpl.class); - - /** - * Icon - */ - private static byte[] icon = DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_64x64"); - - /** - * The id of the contact. - */ - private String contactID = null; - - /** - * The provider that created us. - */ - private ProtocolProviderServiceDictImpl parentProvider = null; - - /** - * The group that belong to. - */ - private ContactGroupDictImpl parentGroup = null; - - /** - * The presence status of the contact. - */ - private PresenceStatus presenceStatus = DictStatusEnum.ONLINE; - - /** - * Determines whether this contact is persistent, i.e. member of the contact - * list or whether it is here only temporarily. - */ - private boolean isPersistent = true; - - /** - * Determines whether the contact has been resolved (i.e. we have a - * confirmation that it is still on the server contact list). - */ - private boolean isResolved = true; - - /** - * The string in a "humain readable and understandable representation" of - * the dictionnaire. In brief this is a short description of the dictionary. - */ - private String dictName = null; - - /** - * Creates an instance of a meta contact with the specified string used - * as a name and identifier. - * - * @param databaseCode The identifier of this contact (also used as a name). - * @param parentProvider The provider that created us. - */ - public ContactDictImpl( - String databaseCode, - ProtocolProviderServiceDictImpl parentProvider) - { - this.contactID = databaseCode; - this.parentProvider = parentProvider; - } - - /** - * This method is only called when the contact is added to a new - * ContactGroupDictImpl by the - * ContactGroupDictImpl itself. - * - * @param newParentGroup the ContactGroupDictImpl that is now - * parent of this ContactDictImpl - */ - void setParentGroup(ContactGroupDictImpl newParentGroup) - { - this.parentGroup = newParentGroup; - } - - /** - * Returns a String that can be used for identifying the contact. - * - * @return a String id representing and uniquely identifying the contact. - */ - public String getContactID() - { - return contactID; - } - - /** - * Returns a String that can be used for identifying the contact. - * - * @return a String id representing and uniquely identifying the contact. - */ - public String getAddress() - { - return contactID; - } - - /** - * Returns a String that could be used by any user interacting modules - * for referring to this contact. - * - * @return a String that can be used for referring to this contact when - * interacting with the user. - */ - public String getDisplayName() - { - if (dictName == null) - { - if (this.contactID.equals("*")) - { - this.dictName = DictActivator.getResources() - .getI18NString("plugin.dictaccregwizz.ANY_DICTIONARY"); - } - else if (this.contactID.equals("!")) - { - this.dictName = DictActivator.getResources() - .getI18NString("plugin.dictaccregwizz.FIRST_MATCH"); - } - else - { - try - { - this.dictName = this.parentProvider.getConnection() - .getDictionaryName(this.contactID); - } - catch (DictException dx) - { - logger.error("Error while getting dictionary long name", dx); - } - - if (this.dictName == null) - this.dictName = this.contactID; - } - } - - return dictName; - } - - /** - * Returns a byte array containing an image (most often a photo or an - * avatar) that the contact uses as a representation. - * - * @return byte[] an image representing the contact. - */ - public byte[] getImage() - { - return icon; - } - - /** - * Returns the status of the contact. - * - * @return always DictStatusEnum.ONLINE. - */ - public PresenceStatus getPresenceStatus() - { - return this.presenceStatus; - } - - /** - * Sets dictPresenceStatus as the PresenceStatus that this - * contact is currently in. - * @param dictPresenceStatus the DictPresenceStatus - * currently valid for this contact. - */ - public void setPresenceStatus(PresenceStatus dictPresenceStatus) - { - this.presenceStatus = dictPresenceStatus; - } - - /** - * Returns a reference to the protocol provider that created the contact. - * - * @return a refererence to an instance of the ProtocolProviderService - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Determines whether or not this contact represents our own identity. - * - * @return true in case this is a contact that represents ourselves and - * false otherwise. - */ - public boolean isLocal() - { - return false; - } - - /** - * Returns the group that contains this contact. - * @return a reference to the ContactGroupDictImpl that - * contains this contact. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Returns a string representation of this contact, containing most of its - * representative details. - * - * @return a string representation of this contact. - */ - @Override - public String toString() - { - StringBuffer buff - = new StringBuffer("ContactDictImpl[ DisplayName=") - .append(getDisplayName()).append("]"); - - return buff.toString(); - } - - /** - * Determines whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @return true if the contact is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Specifies whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @param isPersistent true if the contact is persistent and false - * otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Return the current status message of this contact. - * - * @return null as the protocol has currently no support of status messages - */ - public String getStatusMessage() - { - return null; - } - - /** - * Makes the contact resolved or unresolved. - * - * @param resolved true to make the contact resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns the persistent presence operation set that this contact belongs - * to. - * - * @return the OperationSetPersistentPresenceGibberishImpl that - * this contact belongs to. - */ - public OperationSetPersistentPresenceDictImpl - getParentPresenceOperationSet() - { - return (OperationSetPersistentPresenceDictImpl) parentProvider - .getOperationSet(OperationSetPersistentPresence.class); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/ContactGroupDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/ContactGroupDictImpl.java deleted file mode 100644 index e52ce96..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/ContactGroupDictImpl.java +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * A simple, straightforward implementation of a dict ContactGroup. Since - * the Dict protocol is not a real one, we simply store all group details - * in class fields. You should know that when implementing a real protocol, - * the contact group implementation would rather encapsulate group objects from - * the protocol stack and group property values should be returned by consulting - * the encapsulated object. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class ContactGroupDictImpl - implements ContactGroup -{ - - /** - * The name of this Dict contact group. - */ - private String groupName = null; - - /** - * The list of this group's members. - */ - private List contacts = new ArrayList(); - - /** - * The list of sub groups belonging to this group. - */ - private List subGroups = new ArrayList(); - - /** - * The group that this group belongs to (or null if this is the root group). - */ - private ContactGroupDictImpl parentGroup = null; - - /** - * Determines whether this group is really in the contact list or whether - * it is here only temporarily and will be gone next time we restart. - */ - private boolean isPersistent = true; - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceDictImpl parentProvider = null; - - /** - * Determines whether this group has been resolved on the server. - * Unresolved groups are groups that were available on previous runs and - * that the meta contact list has stored. During all next runs, when - * bootstrapping, the meta contact list would create these groups as - * unresolved. Once a protocol provider implementation confirms that the - * groups are still on the server, it would issue an event indicating that - * the groups are now resolved. - */ - private boolean isResolved = true; - - /** - * An id uniquely identifying the group. For many protocols this could be - * the group name itself. - */ - private String uid = null; - private static final String UID_SUFFIX = ".uid"; - - /** - * Creates a ContactGroupDictImpl with the specified name. - * - * @param groupName the name of the group. - * @param parentProvider the protocol provider that created this group. - */ - public ContactGroupDictImpl( - String groupName, - ProtocolProviderServiceDictImpl parentProvider) - { - this.groupName = groupName; - this.uid = groupName + UID_SUFFIX; - this.parentProvider = parentProvider; - } - - /** - * Determines whether the group may contain subgroups or not. - * - * @return always true in this implementation. - */ - public boolean canContainSubgroups() - { - return true; - } - - /** - * Returns the protocol provider that this group belongs to. - * @return a regerence to the ProtocolProviderService instance that this - * ContactGroup belongs to. - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Returns an Iterator over all contacts, member of this - * ContactGroup. - * - * @return a java.util.Iterator over all contacts inside this - * ContactGroup - */ - public Iterator contacts() - { - return contacts.iterator(); - } - - /** - * Adds the specified contact to this group. - * @param contactToAdd the ContactDictImpl to add to this group. - */ - public void addContact(ContactDictImpl contactToAdd) - { - this.contacts.add(contactToAdd); - contactToAdd.setParentGroup(this); - } - - /** - * Returns the number of Contact members of this - * ContactGroup - * - * @return an int indicating the number of Contacts, members of - * this ContactGroup. - */ - public int countContacts() - { - return contacts.size(); - } - - /** - * Returns the number of subgroups contained by this - * ContactGroup. - * - * @return the number of subGroups currently added to this group. - */ - public int countSubgroups() - { - return subGroups.size(); - } - - /** - * Adds the specified contact group to the contained by this group. - * @param subgroup the ContactGroupDictImpl to add as a subgroup to this group. - */ - public void addSubgroup(ContactGroupDictImpl subgroup) - { - this.subGroups.add(subgroup); - subgroup.setParentGroup(this); - } - - /** - * Sets the group that is the new parent of this group - * @param parent ContactGroupDictImpl - */ - void setParentGroup(ContactGroupDictImpl parent) - { - this.parentGroup = parent; - } - - /** - * Returns the contact group that currently contains this group or null if - * this is the root contact group. - * @return the contact group that currently contains this group or null if - * this is the root contact group. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Removes the specified contact group from the this group's subgroups. - * @param subgroup the ContactGroupDictImpl subgroup to remove. - */ - public void removeSubGroup(ContactGroupDictImpl subgroup) - { - this.subGroups.remove(subgroup); - subgroup.setParentGroup(null); - } - - /** - * Returns the group that is parent of the specified dictGroup or null - * if no parent was found. - * @param dictGroup the group whose parent we're looking for. - * @return the ContactGroupDictImpl instance that dictGroup - * belongs to or null if no parent was found. - */ - public ContactGroupDictImpl findGroupParent(ContactGroupDictImpl dictGroup) - { - if ( subGroups.contains(dictGroup) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupDictImpl subgroup - = (ContactGroupDictImpl) subGroupsIter.next(); - - ContactGroupDictImpl parent - = subgroup.findGroupParent(dictGroup); - - if(parent != null) - return parent; - } - return null; - } - - /** - * Returns the group that is parent of the specified dictContact or - * null if no parent was found. - * - * @param dictContact the contact whose parent we're looking for. - * @return the ContactGroupDictImpl instance that dictContact - * belongs to or null if no parent was found. - */ - public ContactGroupDictImpl findContactParent( - ContactDictImpl dictContact) - { - if ( contacts.contains(dictContact) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupDictImpl subgroup - = (ContactGroupDictImpl) subGroupsIter.next(); - - ContactGroupDictImpl parent - = subgroup.findContactParent(dictContact); - - if(parent != null) - return parent; - } - return null; - } - - - - /** - * Returns the Contact with the specified address or identifier. - * - * @param id the addres or identifier of the Contact we are - * looking for. - * @return the Contact with the specified id or address. - */ - public Contact getContact(String id) - { - Iterator contactsIter = contacts(); - while (contactsIter.hasNext()) - { - ContactDictImpl contact = (ContactDictImpl) contactsIter.next(); - if (contact.getAddress().equals(id)) - return contact; - - } - return null; - } - - /** - * Returns the subgroup with the specified index. - * - * @param index the index of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(int index) - { - return subGroups.get(index); - } - - /** - * Returns the subgroup with the specified name. - * - * @param groupName the name of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(String groupName) - { - Iterator groupsIter = subgroups(); - while (groupsIter.hasNext()) - { - ContactGroupDictImpl contactGroup - = (ContactGroupDictImpl) groupsIter.next(); - if (contactGroup.getGroupName().equals(groupName)) - return contactGroup; - - } - return null; - - } - - /** - * Returns the name of this group. - * - * @return a String containing the name of this group. - */ - public String getGroupName() - { - return this.groupName; - } - - /** - * Sets this group a new name. - * @param newGrpName a String containing the new name of this group. - */ - public void setGroupName(String newGrpName) - { - this.groupName = newGrpName; - } - - /** - * Returns an iterator over the sub groups that this - * ContactGroup contains. - * - * @return a java.util.Iterator over the ContactGroup children - * of this group (i.e. subgroups). - */ - public Iterator subgroups() - { - return subGroups.iterator(); - } - - /** - * Removes the specified contact from this group. - * @param contact the ContactDictImpl to remove from this group - */ - public void removeContact(ContactDictImpl contact) - { - this.contacts.remove(contact); - } - - /** - * Returns the contact with the specified id or null if no such contact - * exists. - * @param id the id of the contact we're looking for. - * @return ContactDictImpl - */ - public ContactDictImpl findContactByID(String id) - { - //first go through the contacts that are direct children. - Iterator contactsIter = contacts(); - - while(contactsIter.hasNext()) - { - ContactDictImpl mContact = (ContactDictImpl)contactsIter.next(); - - if( mContact.getAddress().equals(id) ) - return mContact; - } - - //if we didn't find it here, let's try in the subougroups - Iterator groupsIter = subgroups(); - - while( groupsIter.hasNext() ) - { - ContactGroupDictImpl mGroup = (ContactGroupDictImpl)groupsIter.next(); - - ContactDictImpl mContact = mGroup.findContactByID(id); - - if (mContact != null) - return mContact; - } - - return null; - } - - - /** - * Returns a String representation of this group and the contacts it - * contains (may turn out to be a relatively long string). - * @return a String representing this group and its child contacts. - */ - @Override - public String toString() - { - - StringBuffer buff = new StringBuffer(getGroupName()); - buff.append(".subGroups=" + countSubgroups() + ":\n"); - - Iterator subGroups = subgroups(); - while (subGroups.hasNext()) - { - ContactGroupDictImpl group = (ContactGroupDictImpl)subGroups.next(); - buff.append(group.toString()); - if (subGroups.hasNext()) - buff.append("\n"); - } - - buff.append("\nChildContacts="+countContacts()+":["); - - Iterator contacts = contacts(); - while (contacts.hasNext()) - { - ContactDictImpl contact = (ContactDictImpl) contacts.next(); - buff.append(contact.toString()); - if(contacts.hasNext()) - buff.append(", "); - } - return buff.append("]").toString(); - } - - /** - * Specifies whether or not this contact group is being stored by the server. - * Non persistent contact groups are common in the case of simple, - * non-persistent presence operation sets. They could however also be seen - * in persistent presence operation sets when for example we have received - * an event from someone not on our contact list and the contact that we - * associated with that user is placed in a non persistent group. Non - * persistent contact groups are volatile even when coming from a persistent - * presence op. set. They would only exist until the application is closed - * and will not be there next time it is loaded. - * - * @param isPersistent true if the contact group is to be persistent and - * false otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Makes the group resolved or unresolved. - * - * @param resolved true to make the group resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns a String that uniquely represnets the group inside - * the current protocol. The string MUST be persistent (it must not change - * across connections or runs of the application). In many cases (Jabber, - * ICQ) the string may match the name of the group as these protocols - * only allow a single level of contact groups and there is no danger of - * having the same name twice in the same contact list. Other protocols - * (no examples come to mind but that doesn't bother me ;) ) may be - * supporting mutilple levels of grooups so it might be possible for group - * A and group B to both contain groups named C. In such cases the - * implementation must find a way to return a unique identifier in this - * method and this UID should never change for a given group. - * - * @return a String representing this group in a unique and persistent - * way. - */ - public String getUID() - { - return uid; - } - - /** - * Ugly but tricky conversion method. - * @param uid the uid we'd like to get a name from - * @return the name of the group with the specified uid. - */ - static String createNameFromUID(String uid) - { - return uid.substring(0, uid.length() - (UID_SUFFIX.length())); - } - - /** - * Indicates whether some other object is "equal to" this one which in terms - * of contact groups translates to having the equal names and matching - * subgroups and child contacts. The resolved status of contactgroups and - * contacts is deliberately ignored so that groups and/or contacts would - * be assumed equal even if it differs. - *

    - * @param obj the reference object with which to compare. - * @return true if this contact group has the equal child - * contacts and subgroups to those of the obj argument. - */ - @Override - public boolean equals(Object obj) - { - if(obj == null - || !(obj instanceof ContactGroupDictImpl)) - return false; - - ContactGroupDictImpl dictGroup - = (ContactGroupDictImpl)obj; - - if( ! dictGroup.getGroupName().equals(getGroupName()) - || ! dictGroup.getUID().equals(getUID()) - || dictGroup.countContacts() != countContacts() - || dictGroup.countSubgroups() != countSubgroups()) - return false; - - //traverse child contacts - Iterator theirContacts = dictGroup.contacts(); - - while(theirContacts.hasNext()) - { - ContactDictImpl theirContact - = (ContactDictImpl)theirContacts.next(); - - ContactDictImpl ourContact - = (ContactDictImpl)getContact(theirContact.getAddress()); - - if(ourContact == null - || !ourContact.equals(theirContact)) - return false; - } - - //traverse subgroups - Iterator theirSubgroups = dictGroup.subgroups(); - - while(theirSubgroups.hasNext()) - { - ContactGroupDictImpl theirSubgroup - = (ContactGroupDictImpl)theirSubgroups.next(); - - ContactGroupDictImpl ourSubgroup - = (ContactGroupDictImpl)getGroup( - theirSubgroup.getGroupName()); - - if(ourSubgroup == null - || !ourSubgroup.equals(theirSubgroup)) - return false; - } - - return true; - } -} - diff --git a/src/net/java/sip/communicator/impl/protocol/dict/DictAccountID.java b/src/net/java/sip/communicator/impl/protocol/dict/DictAccountID.java deleted file mode 100644 index 538ae71..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/DictAccountID.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Dict implementation of a sip-communicator account id. - * @author LITZELMANN Cedric - * @author ROTH Damien - */ -public class DictAccountID - extends AccountID -{ - /** - * Creates an account id from the specified id and account properties. - * - * @param userID the user identifier correspnding to the account - * @param accountProperties any other properties necessary for the account. - */ - DictAccountID(String userID, Map accountProperties) - { - super(userID, accountProperties, ProtocolNames.DICT, "dict.org"); - } - - /** - * Returns the dict server adress - * @return the dict server adress - */ - public String getHost() - { - return getAccountPropertyString(ProtocolProviderFactory.SERVER_ADDRESS); - } - - /** - * Returns the dict server port - * @return the dict server port - */ - public int getPort() - { - return Integer - .parseInt(getAccountPropertyString(ProtocolProviderFactory.SERVER_PORT)); - } - - /** - * Returns the selected strategy - * @return the selected strategy - */ - public String getStrategy() - { - return getAccountPropertyString(ProtocolProviderFactory.STRATEGY); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/DictActivator.java b/src/net/java/sip/communicator/impl/protocol/dict/DictActivator.java deleted file mode 100644 index b5976c7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/DictActivator.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Loads the Dict provider factory and registers its services in the OSGI - * bundle context. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class DictActivator - implements BundleActivator -{ - private static final Logger logger = Logger.getLogger(DictActivator.class); - - /** - * The currently valid bundle context. - */ - private static BundleContext bundleContext = null; - - private ServiceRegistration dictPpFactoryServReg = null; - private static ProtocolProviderFactoryDictImpl - dictProviderFactory = null; - - private static ResourceManagementService resourceService; - - /** - * Called when this bundle is started. In here we'll export the - * dict ProtocolProviderFactory implementation so that it could be - * possible to register accounts with it in SIP Communicator. - * - * @param context The execution context of the bundle being started. - * @throws Exception If this method throws an exception, this bundle is - * marked as stopped and the Framework will remove this bundle's - * listeners, unregister all services registered by this bundle, and - * release all services used by this bundle. - */ - public void start(BundleContext context) - throws Exception - { - bundleContext = context; - - Hashtable hashtable = new Hashtable(); - hashtable.put(ProtocolProviderFactory.PROTOCOL, ProtocolNames.DICT); - - dictProviderFactory = new ProtocolProviderFactoryDictImpl(); - - //reg the dict provider factory. - dictPpFactoryServReg = context.registerService( - ProtocolProviderFactory.class.getName(), - dictProviderFactory, - hashtable); - - if (logger.isInfoEnabled()) - logger.info("DICT protocol implementation [STARTED]."); - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return a reference to the BundleContext instance that we were started - * witn. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param context The execution context of the bundle being stopped. - * @throws Exception If this method throws an exception, the bundle is - * still marked as stopped, and the Framework will remove the bundle's - * listeners, unregister all services registered by the bundle, and - * release all services used by the bundle. - */ - public void stop(BundleContext context) - throws Exception - { - - dictProviderFactory.stop(); - dictPpFactoryServReg.unregister(); - - if (logger.isInfoEnabled()) - logger.info("DICT protocol implementation [STOPPED]."); - } - - /** - * Returns a reference to the protocol provider factory that we have - * registered. - * @return a reference to the ProtocolProviderFactoryDictImpl - * instance that we have registered from this package. - */ - public static ProtocolProviderFactoryDictImpl getProtocolProviderFactory() - { - return dictProviderFactory; - } - - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourceService == null) - { - ServiceReference serviceReference = bundleContext - .getServiceReference(ResourceManagementService.class.getName()); - - if(serviceReference == null) - return null; - - resourceService = (ResourceManagementService) bundleContext - .getService(serviceReference); - } - - return resourceService; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/DictStatusEnum.java b/src/net/java/sip/communicator/impl/protocol/dict/DictStatusEnum.java deleted file mode 100644 index 87086f7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/DictStatusEnum.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * An implementation of PresenceStatus that enumerates all states that - * a Dict contact can fall into. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class DictStatusEnum - extends PresenceStatus -{ - - /** - * Indicates an Offline status or status with 0 connectivity. - */ - public static final DictStatusEnum OFFLINE - = new DictStatusEnum( - 0, "Offline", - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.OFFLINE_STATUS_ICON")); - - /** - * The Online status. Indicate that the user is able and willing to - * communicate. - */ - public static final DictStatusEnum ONLINE - = new DictStatusEnum( - 65, "Online", - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_16x16")); - - /** - * Initialize the list of supported status states. - */ - private static List supportedStatusSet = new LinkedList(); - static - { - supportedStatusSet.add(OFFLINE); - supportedStatusSet.add(ONLINE); - } - - /** - * Creates an instance of RssPresneceStatus with the - * specified parameters. - * @param status the connectivity level of the new presence status instance - * @param statusName the name of the presence status. - * @param statusIcon the icon associated with this status - */ - private DictStatusEnum(int status, - String statusName, - byte[] statusIcon) - { - super(status, statusName, statusIcon); - } - - /** - * Returns an iterator over all status instances supproted by the rss - * provider. - * @return an Iterator over all status instances supported by the - * rss provider. - */ - static Iterator supportedStatusSet() - { - return supportedStatusSet.iterator(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/MessageDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/MessageDictImpl.java deleted file mode 100644 index 5b95dd4..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/MessageDictImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Very simple message implementation for the Dict protocol. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - * @author Lubomir Marinov - */ -public class MessageDictImpl - extends AbstractMessage -{ - - /** - * Creates a message instance according to the specified parameters. - * - * @param content the message body - * @param contentType message content type or null for text/plain - * @param contentEncoding message encoding or null for UTF8 - * @param subject the subject of the message or null for no subject. - */ - public MessageDictImpl(String content, String contentType, - String contentEncoding, String subject) - { - super(content, contentType, contentEncoding, subject); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/OperationSetBasicInstantMessagingDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/OperationSetBasicInstantMessagingDictImpl.java deleted file mode 100644 index f1f4973..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/OperationSetBasicInstantMessagingDictImpl.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.dict4j.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -/** - * Instant messaging functionalities for the Dict protocol. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class OperationSetBasicInstantMessagingDictImpl - extends AbstractOperationSetBasicInstantMessaging - implements RegistrationStateChangeListener -{ - /** - * The currently valid persistent presence operation set. - */ - private OperationSetPersistentPresenceDictImpl opSetPersPresence = null; - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceDictImpl parentProvider = null; - - private DictAccountID accountID; - - /** - * Creates an instance of this operation set keeping a reference to the - * parent protocol provider and presence operation set. - * - * @param provider The provider instance that creates us. - * @param opSetPersPresence the currently valid - * OperationSetPersistentPresenceDictImpl instance. - */ - public OperationSetBasicInstantMessagingDictImpl( - ProtocolProviderServiceDictImpl provider, - OperationSetPersistentPresenceDictImpl opSetPersPresence) - { - this.opSetPersPresence = opSetPersPresence; - this.parentProvider = provider; - this.accountID = (DictAccountID) provider.getAccountID(); - - parentProvider.addRegistrationStateChangeListener(this); - } - - @Override - public Message createMessage(String content) - { - return new MessageDictImpl(content, HTML_MIME_TYPE, - DEFAULT_MIME_ENCODING, null); - } - - @Override - public Message createMessage(String content, String contentType, - String encoding, String subject) - { - return new MessageDictImpl(content, contentType, encoding, subject); - } - - /** - * Sends the message to the destination indicated by the - * to contact. - * - * @param to the Contact to send message to - * @param message the Message to send. - * @throws IllegalStateException if the underlying ICQ stack is not - * registered and initialized. - * @throws IllegalArgumentException if to is not an instance - * belonging to the underlying implementation. - */ - public void sendInstantMessage(Contact to, Message message) - throws IllegalStateException, - IllegalArgumentException - { - if( !(to instanceof ContactDictImpl) ) - { - throw new IllegalArgumentException( - "The specified contact is not a Dict contact." - + to); - } - - // Remove all html tags from the message - message = createMessage(Html2Text.extractText(message.getContent())); - - // Display the queried word - fireMessageDelivered(message, to); - - this.submitDictQuery((ContactDictImpl) to, message); - } - - /** - * Determines whether the protocol provider (or the protocol itself) supports - * sending and receiving offline messages. Most often this method would - * return true for protocols that support offline messages and false for - * those that don't. It is however possible for a protocol to support these - * messages and yet have a particular account that does not (i.e. feature - * not enabled on the protocol server). In cases like this it is possible - * for this method to return true even when offline messaging is not - * supported, and then have the sendMessage method throw an - * OperationFailedException with code - OFFLINE_MESSAGES_NOT_SUPPORTED. - * - * @return true if the protocol supports offline messages and - * false otherwise. - */ - public boolean isOfflineMessagingSupported() - { - return false; - } - - /** - * Determines whether the protocol supports the supplied content type. - * - * @param contentType the type we want to check - * @return true if the protocol supports it and - * false otherwise. - */ - public boolean isContentTypeSupported(String contentType) - { - if(contentType.equals(DEFAULT_MIME_TYPE)) - return true; - else if(contentType.equals(HTML_MIME_TYPE)) - return true; - else - return false; - } - - /** - * Returns the protocol provider that this operation set belongs to. - * - * @return a reference to the ProtocolProviderServiceDictImpl - * instance that this operation set belongs to. - */ - public ProtocolProviderServiceDictImpl getParentProvider() - { - return this.parentProvider; - } - - /** - * Returns a reference to the presence operation set instance used by our - * source provider. - * - * @return a reference to the OperationSetPersistentPresenceDictImpl - * instance used by this provider. - */ - public OperationSetPersistentPresenceDictImpl getOpSetPersPresence() - { - return this.opSetPersPresence; - } - - /** - * The method is called by the ProtocolProvider whenever a change in the - * registration state of the corresponding provider has occurred. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - - } - - - /** - * Create, execute and display a query to a dictionary (ContactDictImpl) - * - * @param dictContact the contact containing the database name - * @param message the message containing the word - */ - private void submitDictQuery(ContactDictImpl dictContact, Message message) - { - Message msg = this.createMessage(""); - - String database = dictContact.getContactID(); - DictConnection conn = this.parentProvider.getConnection(); - boolean doMatch = false; - - String word; - - // Formatting the query message, if the word as one or more spaces we - // put it between quotes to prevent errors - word = message.getContent().replace("\"", "").trim(); - if (word.indexOf(' ') > 0) - { - word = "\"" + word + "\""; - } - - // Try to get the definition of the work - try - { - List definitions = conn.define(database, word); - msg = this.createMessage(retrieveDefine(definitions, word)); - } - catch(DictException dx) - { - if (dx.getErrorCode() == DictReturnCode.NO_MATCH) - { // No word found, we are going to try the match command - doMatch = true; - } - else - { // Otherwise we display the error returned by the server - msg = this.createMessage(manageException(dx, database)); - } - } - - if (doMatch) - { - // Trying the match command - try - { - List matchWords = conn.match(database, word, - this.accountID.getStrategy()); - msg = this.createMessage(retrieveMatch(matchWords, word)); - } - catch(DictException dx) - { - msg = this.createMessage(manageException(dx, database)); - } - } - - // Send message - fireMessageReceived(msg, dictContact); - } - - /** - * Generate the display of the results of the Define command - * - * @param data the result of the Define command - * @param word the queried word - * @return the formatted result - */ - private String retrieveDefine(List data, String word) - { - StringBuffer res = new StringBuffer(); - Definition def; - - for (int i=0; i 0) - { - res.append("


    "); - } - res.append(def.getDefinition().replaceAll("\n", "
    ")) - .append("
    -- From ") - .append(def.getDictionary()) - .append("
    "); - } - - String result = res.toString(); - result = formatResult(result, "\\\\", "", ""); - result = formatResult(result, "[\\[\\]]", "", ""); - result = formatResult(result, "[\\{\\}]", "", ""); - result = formatWordDefined(result, word); - - return result; - } - - /** - * Makes a stronger emphasis for the word defined. - * @param result The text containing the definition of the word. - * @param word The word defined to display with bold font. For this we - * had the strong HTML tag. - * @return Returns the result text with an strong emphasis of all - * the occurences of the word defined. - */ - private String formatWordDefined(String result, String word) - { - String tmpWord; - - tmpWord = word.toUpperCase(); - result = result.replaceAll("\\b" + tmpWord + "\\b", "" + tmpWord + ""); - tmpWord = word.toLowerCase(); - result = result.replaceAll("\\b" + tmpWord + "\\b", "" + tmpWord + ""); - if(tmpWord.length() > 1) - { - tmpWord = tmpWord.substring(0, 1).toUpperCase() + tmpWord.substring(1); - result = result.replaceAll("\\b" + tmpWord + "\\b", "" + tmpWord + ""); - } - - return result; - } - - /** - * Remplaces special characters into HTML tags to make some emphasis. - * @param result The text containing the definition of the word. - * @param regex The special character to replace with HTML tags. - * @param startTag The start HTML tag to use. - * @param endTag The end HTML tag to use. - * @return The result with all special characters replaced by HTML - * tags. - */ - private String formatResult(String result, String regex, String startTag, String endTag) - { - String[] tmp = result.split(regex); - String res = ""; - - for(int i = 0; i < (tmp.length - 1); i += 2) - { - res += tmp[i] + startTag + tmp[i+1] + endTag; - } - if((tmp.length % 2) != 0) - { - res += tmp[tmp.length - 1]; - } - return res; - } - - /** - * Generate the display of the results of the Match command - * - * @param data the result of the Match command - * @param word the queried word - * @return the formatted result - */ - private String retrieveMatch(List data, String word) - { - StringBuffer result = new StringBuffer(); - boolean isStart = true; - - result.append(DictActivator.getResources() - .getI18NString("plugin.dictaccregwizz.MATCH_RESULT", new String[] {word})); - - for (int i=0; imessage to the destination indicated by the - * to. Resources are not supported by this operation set - * implementation. - * - * @param to the Contact to send message to - * @param toResource the resource to which the message should be send - * @param message the Message to send. - * @throws java.lang.IllegalStateException if the underlying ICQ stack is - * not registered and initialized. - * @throws java.lang.IllegalArgumentException if to is not an - * instance belonging to the underlying implementation. - */ - @Override - public void sendInstantMessage( Contact to, - ContactResource toResource, - Message message) - throws IllegalStateException, - IllegalArgumentException - { - sendInstantMessage(to, message); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/OperationSetPersistentPresenceDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/OperationSetPersistentPresenceDictImpl.java deleted file mode 100644 index 8184fe9..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/OperationSetPersistentPresenceDictImpl.java +++ /dev/null @@ -1,988 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * A Dict implementation of a persistent presence operation set. In order - * to simulate server persistence, this operation set would simply accept all - * unresolved contacts and resolve them immediately. A real world protocol - * implementation would save it on a server using methods provided by the - * protocol stack. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class OperationSetPersistentPresenceDictImpl - extends AbstractOperationSetPersistentPresence -{ - private static final Logger logger = - Logger.getLogger(OperationSetPersistentPresenceDictImpl.class); - - /** - * The root of the dict contact list. - */ - private ContactGroupDictImpl contactListRoot = null; - - /** - * The currently active status message. - */ - private String statusMessage = "Default Status Message"; - - /** - * Our presence status. - */ - private PresenceStatus presenceStatus = DictStatusEnum.ONLINE; - - /** - * The AuthorizationHandler instance that we'd have to transmit - * authorization requests to for approval. - */ - private AuthorizationHandler authorizationHandler = null; - - /** - * Creates an instance of this operation set keeping a reference to the - * specified parent provider. - * @param provider the ProtocolProviderServiceDictImpl instance that - * created us. - */ - public OperationSetPersistentPresenceDictImpl( - ProtocolProviderServiceDictImpl provider) - { - super(provider); - - contactListRoot = new ContactGroupDictImpl("RootGroup", provider); - - //add our unregistration listener - parentProvider.addRegistrationStateChangeListener( - new UnregistrationListener()); - } - - /** - * Creates a group with the specified name and parent in the server - * stored contact list. - * - * @param parent the group where the new group should be created - * @param groupName the name of the new group to create. - */ - public void createServerStoredContactGroup(ContactGroup parent, - String groupName) - { - ContactGroupDictImpl newGroup - = new ContactGroupDictImpl(groupName, parentProvider); - - ((ContactGroupDictImpl)parent).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - /** - * A Dict Provider method to use for fast filling of a contact list. - * - * @param contactGroup the group to add - */ - public void addDictGroup(ContactGroupDictImpl contactGroup) - { - contactListRoot.addSubgroup(contactGroup); - } - - /** - * A Dict Provider method to use for fast filling of a contact list. - * This method would add both the group and fire an event. - * - * @param parent the group where contactGroup should be added. - * @param contactGroup the group to add - */ - public void addDictGroupAndFireEvent( - ContactGroupDictImpl parent - , ContactGroupDictImpl contactGroup) - { - parent.addSubgroup(contactGroup); - - this.fireServerStoredGroupEvent( - contactGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - - /** - * Returns a reference to the contact with the specified ID in case we - * have a subscription for it and null otherwise/ - * - * @param contactID a String identifier of the contact which we're - * seeking a reference of. - * @return a reference to the Contact with the specified - * contactID or null if we don't have a subscription for the - * that identifier. - */ - public Contact findContactByID(String contactID) - { - return contactListRoot.findContactByID(contactID); - } - - /** - * Sets the specified status message. - * @param statusMessage a String containing the new status message. - */ - public void setStatusMessage(String statusMessage) - { - this.statusMessage = statusMessage; - } - - /** - * Returns the status message that was last set through - * setCurrentStatusMessage. - * - * @return the last status message that we have requested and the aim - * server has confirmed. - */ - public String getCurrentStatusMessage() - { - return statusMessage; - } - - /** - * Returns the protocol specific contact instance representing the local - * user. - * - * @return the Contact (address, phone number, or uin) that the Provider - * implementation is communicating on behalf of. - */ - public Contact getLocalContact() - { - return null; - } - - /** - * Returns a PresenceStatus instance representing the state this provider - * is currently in. - * - * @return the PresenceStatus last published by this provider. - */ - public PresenceStatus getPresenceStatus() - { - return presenceStatus; - } - - /** - * Returns the root group of the server stored contact list. - * - * @return the root ContactGroup for the ContactList stored by this - * service. - */ - public ContactGroup getServerStoredContactListRoot() - { - return contactListRoot; - } - - /** - * Returns the set of PresenceStatus objects that a user of this service - * may request the provider to enter. - * - * @return Iterator a PresenceStatus array containing "enterable" status - * instances. - */ - public Iterator getSupportedStatusSet() - { - return DictStatusEnum.supportedStatusSet(); - } - - /** - * Removes the specified contact from its current parent and places it - * under newParent. - * - * @param contactToMove the Contact to move - * @param newParent the ContactGroup where Contact - * would be placed. - */ - public void moveContactToGroup(Contact contactToMove, - ContactGroup newParent) - { - ContactDictImpl dictContact - = (ContactDictImpl)contactToMove; - - ContactGroupDictImpl parentDictGroup - = findContactParent(dictContact); - - parentDictGroup.removeContact(dictContact); - - //if this is a volatile contact then we haven't really subscribed to - //them so we'd need to do so here - if(!dictContact.isPersistent()) - { - //first tell everyone that the volatile contact was removed - fireSubscriptionEvent(dictContact - , parentDictGroup - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - - try - { - //now subscribe - this.subscribe(newParent, contactToMove.getAddress()); - - //now tell everyone that we've added the contact - fireSubscriptionEvent(dictContact - , newParent - , SubscriptionEvent.SUBSCRIPTION_CREATED); - } - catch (Exception ex) - { - logger.error("Failed to move contact " - + dictContact.getAddress() - , ex); - } - } - else - { - ( (ContactGroupDictImpl) newParent) - .addContact(dictContact); - - fireSubscriptionMovedEvent(contactToMove - , parentDictGroup - , newParent); - } - } - - /** - * Requests the provider to enter into a status corresponding to the - * specified paramters. - * - * @param status the PresenceStatus as returned by - * getRequestableStatusSet - * @param statusMessage the message that should be set as the reason to - * enter that status - * @throws IllegalArgumentException if the status requested is not a - * valid PresenceStatus supported by this provider. - * @throws IllegalStateException if the provider is not currently - * registered. - * @throws OperationFailedException with code NETWORK_FAILURE if - * publishing the status fails due to a network error. - */ - public void publishPresenceStatus(PresenceStatus status, - String statusMessage) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - PresenceStatus oldPresenceStatus = this.presenceStatus; - this.presenceStatus = status; - this.statusMessage = statusMessage; - - this.fireProviderStatusChangeEvent(oldPresenceStatus); - - //since we are not a real protocol, we set the contact presence status - //ourselves and make them have the same status as ours. - changePresenceStatusForAllContacts( getServerStoredContactListRoot() - , getPresenceStatus()); - - //now check whether we are in someone else's contact list and modify - //our status there - List contacts = findContactsPointingToUs(); - - Iterator contactsIter = contacts.iterator(); - while (contactsIter.hasNext()) - { - ContactDictImpl contact - = (ContactDictImpl) contactsIter.next(); - - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(status); - contact.getParentPresenceOperationSet() - .fireContactPresenceStatusChangeEvent( - contact - , contact.getParentContactGroup() - , oldStatus); - - } - } - - - - /** - * Get the PresenceStatus for a particular contact. - * - * @param contactIdentifier the identifier of the contact whose status - * we're interested in. - * @return PresenceStatus the PresenceStatus of the specified - * contact - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * retrieving the status fails due to errors experienced during - * network communication - */ - public PresenceStatus queryContactStatus(String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - return findContactByID(contactIdentifier).getPresenceStatus(); - } - - /** - * Sets the presence status of contact to newStatus. - * - * @param contact the ContactDictImpl whose status we'd like - * to set. - * @param newStatus the new status we'd like to set to contact. - */ - private void changePresenceStatusForContact( - ContactDictImpl contact - , PresenceStatus newStatus) - { - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, findContactParent(contact), oldStatus); - } - - /** - * Sets the presence status of all contacts in our contact list - * (except those that correspond to another provider registered with SC) - * to newStatus. - * - * @param newStatus the new status we'd like to set to contact. - * @param parent the group in which we'd have to update the status of all - * direct and indirect child contacts. - */ - private void changePresenceStatusForAllContacts(ContactGroup parent, - PresenceStatus newStatus) - { - //first set the status for contacts in this group - Iterator childContacts = parent.contacts(); - - while(childContacts.hasNext()) - { - ContactDictImpl contact - = (ContactDictImpl)childContacts.next(); - - if(findProviderForDictUserID(contact.getAddress()) != null) - { - //this is a contact corresponding to another SIP Communicator - //provider so we won't change it's status here. - continue; - } - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, parent, oldStatus); - } - - //now call this method recursively for all subgroups - Iterator subgroups = parent.subgroups(); - - while(subgroups.hasNext()) - { - ContactGroup subgroup = subgroups.next(); - changePresenceStatusForAllContacts(subgroup, newStatus); - } - } - - /** - * Returns the group that is parent of the specified dictGroup or null - * if no parent was found. - * @param dictGroup the group whose parent we're looking for. - * @return the ContactGroupDictImpl instance that dictGroup - * belongs to or null if no parent was found. - */ - public ContactGroupDictImpl findGroupParent( - ContactGroupDictImpl dictGroup) - { - return contactListRoot.findGroupParent(dictGroup); - } - - /** - * Returns the group that is parent of the specified dictContact or - * null if no parent was found. - * @param dictContact the contact whose parent we're looking for. - * @return the ContactGroupDictImpl instance that dictContact - * belongs to or null if no parent was found. - */ - public ContactGroupDictImpl findContactParent( - ContactDictImpl dictContact) - { - return (ContactGroupDictImpl)dictContact - .getParentContactGroup(); - } - - - /** - * Removes the specified group from the server stored contact list. - * - * @param group the group to remove. - * - * @throws IllegalArgumentException if group was not found in this - * protocol's contact list. - */ - public void removeServerStoredContactGroup(ContactGroup group) - throws IllegalArgumentException - { - ContactGroupDictImpl dictGroup - = (ContactGroupDictImpl)group; - - ContactGroupDictImpl parent = findGroupParent(dictGroup); - - if(parent == null){ - throw new IllegalArgumentException( - "group " + group - + " does not seem to belong to this protocol's contact list."); - } - - parent.removeSubGroup(dictGroup); - - this.fireServerStoredGroupEvent( - dictGroup, ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - } - - /** - * Renames the specified group from the server stored contact list. - * - * @param group the group to rename. - * @param newName the new name of the group. - */ - public void renameServerStoredContactGroup(ContactGroup group, - String newName) - { - ((ContactGroupDictImpl)group).setGroupName(newName); - - this.fireServerStoredGroupEvent( - group, ServerStoredGroupEvent.GROUP_RENAMED_EVENT); - } - - /** - * Handler for incoming authorization requests. - * - * @param handler an instance of an AuthorizationHandler for - * authorization requests coming from other users requesting - * permission add us to their contact list. - */ - public void setAuthorizationHandler(AuthorizationHandler handler) - { - this.authorizationHandler = handler; - } - - /** - * Persistently adds a subscription for the presence status of the - * contact corresponding to the specified contactIdentifier and indicates - * that it should be added to the specified group of the server stored - * contact list. - * - * @param parent the parent group of the server stored contact list - * where the contact should be added.

    - * @param contactIdentifier the contact whose status updates we are - * subscribing for. - * @throws IllegalArgumentException if contact or - * parent are not a contact known to the underlying protocol - * provider. - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(ContactGroup parent, String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - ContactDictImpl contact = new ContactDictImpl( - contactIdentifier - , parentProvider); - - ((ContactGroupDictImpl)parent).addContact(contact); - - fireSubscriptionEvent(contact, - parent, - SubscriptionEvent.SUBSCRIPTION_CREATED); - - //notify presence listeners for the status change. - fireContactPresenceStatusChangeEvent(contact - , parent - , DictStatusEnum.ONLINE); - } - - - /** - * Depending on whether contact corresponds to another protocol - * provider installed in sip-communicator, this method would either deliver - * it to that provider or simulate a corresponding request from the - * destination contact and make return a response after it has received - * one If the destination contact matches us, then we'll ask the user to - * act upon the request, and return the response. - * - * @param request the authorization request that we'd like to deliver to the - * destination contact. - * @param contact the Contact to notify - * - * @return the AuthorizationResponse that has been given or - * generated in response to request. - */ - private AuthorizationResponse deliverAuthorizationRequest( - AuthorizationRequest request, - Contact contact) - { - String userID = contact.getAddress(); - - //if the user id is our own id, then this request is being routed to us - //from another instance of the dict provider. - if (userID.equals(this.parentProvider.getAccountID().getUserID())) - { - //check who is the provider sending the message - String sourceUserID = contact.getProtocolProvider() - .getAccountID().getUserID(); - - //check whether they are in our contact list - Contact from = findContactByID(sourceUserID); - - //and if not - add them there as volatile. - if (from == null) - { - from = createVolatileContact(sourceUserID); - } - - //and now handle the request. - return authorizationHandler.processAuthorisationRequest( - request, from); - } - else - { - //if userID is not our own, try a check whether another provider - //has that id and if yes - deliver the request to them. - ProtocolProviderServiceDictImpl dictProvider - = this.findProviderForDictUserID(userID); - if (dictProvider != null) - { - OperationSetPersistentPresenceDictImpl opSetPersPresence - = (OperationSetPersistentPresenceDictImpl) - dictProvider.getOperationSet( - OperationSetPersistentPresence.class); - return opSetPersPresence - .deliverAuthorizationRequest(request, contact); - } - else - { - //if we got here then "to" is simply someone in our contact - //list so let's just simulate a reciproce request and generate - //a response accordingly. - - //pretend that the remote contact is asking for authorization - authorizationHandler.processAuthorisationRequest( - request, contact); - - //and now pretend that the remote contact has granted us - //authorization - return new AuthorizationResponse(AuthorizationResponse.ACCEPT - , "You are welcome!"); - } - } - } - - /** - * Adds a subscription for the presence status of the contact - * corresponding to the specified contactIdentifier. - * - * @param contactIdentifier the identifier of the contact whose status - * updates we are subscribing for.

    - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - //subscribe(contactListRoot, contactIdentifier); - - } - - /** - * Removes a subscription for the presence status of the specified - * contact. - * - * @param contact the contact whose status updates we are unsubscribing - * from. - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * unsubscribing fails due to errors experienced during network - * communication - */ - public void unsubscribe(Contact contact) throws IllegalArgumentException, - IllegalStateException, OperationFailedException - { - ContactGroupDictImpl parentGroup - = (ContactGroupDictImpl)((ContactDictImpl)contact) - .getParentContactGroup(); - - parentGroup.removeContact((ContactDictImpl)contact); - - fireSubscriptionEvent(contact, - ((ContactDictImpl)contact).getParentContactGroup() - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData) - { - return createUnresolvedContact(address - , persistentData - , getServerStoredContactListRoot()); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @param parent the group where the unresolved contact is - * supposed to belong to. - * - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData, - ContactGroup parent) - { - - ContactDictImpl contact = new ContactDictImpl( - address - , parentProvider); - contact.setResolved(false); - - ( (ContactGroupDictImpl) parent).addContact(contact); - - fireSubscriptionEvent(contact, - parent, - SubscriptionEvent.SUBSCRIPTION_CREATED); - - //since we don't have any server, we'll simply resolve the contact - //ourselves as if we've just received an event from the server telling - //us that it has been resolved. - contact.setResolved(true); - fireSubscriptionEvent(contact, parent, SubscriptionEvent.SUBSCRIPTION_RESOLVED); - - //since we are not a real protocol, we set the contact presence status - //ourselves - changePresenceStatusForContact( contact, getPresenceStatus()); - - return contact; - } - - /** - * Looks for a dict protocol provider registered for a user id matching - * dictUserID. - * - * @param dictUserID the ID of the Dict user whose corresponding - * protocol provider we'd like to find. - * @return ProtocolProviderServiceDictImpl a dict protocol - * provider registered for a user with id dictUserID or null - * if there is no such protocol provider. - */ - public ProtocolProviderServiceDictImpl - findProviderForDictUserID(String dictUserID) - { - BundleContext bc = DictActivator.getBundleContext(); - - String osgiQuery = "(&" - + "(" + ProtocolProviderFactory.PROTOCOL - + "=Dict)" - + "(" + ProtocolProviderFactory.USER_ID - + "=" + dictUserID + ")" - + ")"; - - ServiceReference[] refs = null; - try - { - refs = bc.getServiceReferences( - ProtocolProviderService.class.getName() - ,osgiQuery); - } - catch (InvalidSyntaxException ex) - { - logger.error("Failed to execute the following osgi query: " - + osgiQuery - , ex); - } - - if(refs != null && refs.length > 0) - { - return (ProtocolProviderServiceDictImpl)bc.getService(refs[0]); - } - - return null; - } - - /** - * Looks for dict protocol providers that have added us to their - * contact list and returns list of all contacts representing us in these - * providers. - * - * @return a list of all contacts in other providers' contact lists that - * point to us. - */ - public List findContactsPointingToUs() - { - List contacts = new LinkedList(); - BundleContext bc = DictActivator.getBundleContext(); - - String osgiQuery = - "(" + ProtocolProviderFactory.PROTOCOL - + "=Dict)"; - - ServiceReference[] refs = null; - try - { - refs = bc.getServiceReferences( - ProtocolProviderService.class.getName() - ,osgiQuery); - } - catch (InvalidSyntaxException ex) - { - logger.error("Failed to execute the following osgi query: " - + osgiQuery - , ex); - } - - for (int i =0; refs != null && i < refs.length; i++) - { - ProtocolProviderServiceDictImpl gibProvider - = (ProtocolProviderServiceDictImpl)bc.getService(refs[i]); - - OperationSetPersistentPresenceDictImpl opSetPersPresence - = (OperationSetPersistentPresenceDictImpl)gibProvider - .getOperationSet(OperationSetPersistentPresence.class); - - Contact contact = opSetPersPresence.findContactByID( - parentProvider.getAccountID().getUserID()); - - if (contact != null) - contacts.add(contact); - } - - return contacts; - } - - - /** - * Creates and returns a unresolved contact group from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created - * ContactGroup against the server or the contact itself. The - * protocol provider will later resolve the contact group. When this happens - * the corresponding event would notify interested subscription listeners. - * - * @param groupUID an identifier, returned by ContactGroup's getGroupUID, - * that the protocol provider may use in order to create the group. - * @param persistentData a String returned ContactGroups's - * getPersistentData() method during a previous run and that has been - * persistently stored locally. - * @param parentGroup the group under which the new group is to be created - * or null if this is group directly underneath the root. - * @return the unresolved ContactGroup created from the specified - * uid and persistentData - */ - public ContactGroup createUnresolvedContactGroup(String groupUID, - String persistentData, ContactGroup parentGroup) - { - ContactGroupDictImpl newGroup - = new ContactGroupDictImpl( - ContactGroupDictImpl.createNameFromUID(groupUID) - , parentProvider); - newGroup.setResolved(false); - - //if parent is null then we're adding under root. - if(parentGroup == null) - parentGroup = getServerStoredContactListRoot(); - - ((ContactGroupDictImpl)parentGroup).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - - return newGroup; - } - - private class UnregistrationListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenver - * a change in the registration state of the corresponding provider had - * occurred. The method is particularly interested in events stating - * that the dict provider has unregistered so that it would fire - * status change events for all contacts in our buddy list. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (! evt.getNewState().equals(RegistrationState.UNREGISTERED) - && !evt.getNewState().equals(RegistrationState.AUTHENTICATION_FAILED) - && !evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) - { - return; - } - - //send event notifications saying that all our buddies are - //offline. The icq protocol does not implement top level buddies - //nor subgroups for top level groups so a simple nested loop - //would be enough. - Iterator groupsIter = getServerStoredContactListRoot() - .subgroups(); - while (groupsIter.hasNext()) - { - ContactGroupDictImpl group - = (ContactGroupDictImpl) groupsIter.next(); - - Iterator contactsIter = group.contacts(); - - while (contactsIter.hasNext()) - { - ContactDictImpl contact - = (ContactDictImpl) contactsIter.next(); - - PresenceStatus oldContactStatus - = contact.getPresenceStatus(); - - if (!oldContactStatus.isOnline()) - continue; - - contact.setPresenceStatus(DictStatusEnum.OFFLINE); - - fireContactPresenceStatusChangeEvent( - contact - , contact.getParentContactGroup() - , oldContactStatus); - } - } - } - } - - /** - * Returns the volatile group or null if this group has not yet been - * created. - * - * @return a volatile group existing in our contact list or null - * if such a group has not yet been created. - */ - private ContactGroupDictImpl getNonPersistentGroup() - { - for (int i = 0 - ; i < getServerStoredContactListRoot().countSubgroups() - ; i++) - { - ContactGroupDictImpl gr = - (ContactGroupDictImpl)getServerStoredContactListRoot() - .getGroup(i); - - if(!gr.isPersistent()) - return gr; - } - - return null; - } - - - /** - * Creates a non persistent contact for the specified address. This would - * also create (if necessary) a group for volatile contacts that would not - * be added to the server stored contact list. This method would have no - * effect on the server stored contact list. - * - * @param contactAddress the address of the volatile contact we'd like to - * create. - * @return the newly created volatile contact. - */ - public ContactDictImpl createVolatileContact(String contactAddress) - { - //First create the new volatile contact; - ContactDictImpl newVolatileContact - = new ContactDictImpl(contactAddress - , this.parentProvider); - newVolatileContact.setPersistent(false); - - - //Check whether a volatile group already exists and if not create - //one - ContactGroupDictImpl theVolatileGroup = getNonPersistentGroup(); - - - //if the parent volatile group is null then we create it - if (theVolatileGroup == null) - { - theVolatileGroup = new ContactGroupDictImpl( - DictActivator.getResources().getI18NString( - "service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME") - , parentProvider); - theVolatileGroup.setResolved(false); - theVolatileGroup.setPersistent(false); - - this.contactListRoot.addSubgroup(theVolatileGroup); - - fireServerStoredGroupEvent(theVolatileGroup - , ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - //now add the volatile contact instide it - theVolatileGroup.addContact(newVolatileContact); - fireSubscriptionEvent(newVolatileContact - , theVolatileGroup - , SubscriptionEvent.SUBSCRIPTION_CREATED); - - return newVolatileContact; - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolIconDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/ProtocolIconDictImpl.java deleted file mode 100644 index 4f09f22..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolIconDictImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Represents the Dict protocol icon. Implements the ProtocolIcon - * interface in order to provide a Dict logo image in two different sizes. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class ProtocolIconDictImpl - implements ProtocolIcon -{ - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconsTable - = new Hashtable(); - static - { - iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_16x16")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_32x32, - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_32x32")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_48x48")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_64x64, - DictActivator.getResources() - .getImageInBytes("service.protocol.dict.DICT_64x64")); - } - - /** - * A hash table containing the path to the protocol icon in different sizes. - */ - private static Hashtable iconPathsTable - = new Hashtable(); - static - { - iconPathsTable.put(ProtocolIcon.ICON_SIZE_16x16, - DictActivator.getResources() - .getImagePath("service.protocol.dict.DICT_16x16")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_32x32, - DictActivator.getResources() - .getImagePath("service.protocol.dict.DICT_32x32")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_48x48, - DictActivator.getResources() - .getImagePath("service.protocol.dict.DICT_48x48")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_64x64, - DictActivator.getResources() - .getImagePath("service.protocol.dict.DICT_64x64")); - } - - /** - * Implements the ProtocolIcon.getSupportedSizes() method. Returns - * an iterator to a set containing the supported icon sizes. - * @return Returns an iterator to a set containing the supported icon sizes - */ - public Iterator getSupportedSizes() - { - return iconsTable.keySet().iterator(); - } - - /** - * Returns TRUE if an icon with the given size is supported, FALSE otherwise. - * @param iconSize The size of the icon, that we want to know if it is - * supported. - * @return Returns true if the size is supported. False otherwise. - */ - public boolean isSizeSupported(String iconSize) - { - return iconsTable.containsKey(iconSize); - } - - /** - * Returns the icon image in the given size. - * @param iconSize The icon size one of ICON_SIZE_XXX constants - * @return Returns a byte[] containing the pixels of the icon for the given - * size. - */ - public byte[] getIcon(String iconSize) - { - return iconsTable.get(iconSize); - } - - /** - * Returns a path to the icon with the given size. - * @param iconSize the size of the icon we're looking for - * @return the path to the icon with the given size - */ - public String getIconPath(String iconSize) - { - return iconPathsTable.get(iconSize); - } - - /** - * Returns the icon image used to represent the protocol connecting state. - * @return Returns the icon image used to represent the protocol connecting - * state. - */ - public byte[] getConnectingIcon() - { - return iconsTable.get(ProtocolIcon.ICON_SIZE_16x16); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderFactoryDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderFactoryDictImpl.java deleted file mode 100644 index d7eaf30..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderFactoryDictImpl.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import java.util.*; - -import net.java.sip.communicator.service.contactlist.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The Dict protocol provider factory creates instances of the Dict - * protocol provider service. One Service instance corresponds to one account. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class ProtocolProviderFactoryDictImpl - extends ProtocolProviderFactory -{ - private static final Logger logger - = Logger.getLogger(ProtocolProviderFactoryDictImpl.class); - - /** - * Creates an instance of the ProtocolProviderFactoryDictImpl. - */ - public ProtocolProviderFactoryDictImpl() - { - super(DictActivator.getBundleContext(), ProtocolNames.DICT); - } - - /** - * Initializaed and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. - * - * @param userIDStr The user identifier uniquely representing the newly - * created account within the protocol namespace. - * @param accountProperties a set of protocol (or implementation) - * specific properties defining the new account. - * @return the AccountID of the newly created account. - */ - @Override - public AccountID installAccount( String userIDStr, - Map accountProperties) - { - BundleContext context = DictActivator.getBundleContext(); - if (context == null) - { - throw new NullPointerException("The specified BundleContext was null"); - } - if (userIDStr == null) - { - throw new NullPointerException("The specified AccountID was null"); - } - if (accountProperties == null) - { - throw new NullPointerException("The specified property map was null"); - } - - accountProperties.put(USER_ID, userIDStr); - - AccountID accountID = new DictAccountID(userIDStr, accountProperties); - - //make sure we haven't seen this account id before. - if (registeredAccounts.containsKey(accountID)) - { - throw new IllegalStateException("An account for id " + userIDStr + " was already installed!"); - } - - //first store the account and only then load it as the load generates - //an osgi event, the osgi event triggers (through the UI) a call to the - //ProtocolProviderService.register() method and it needs to acces - //the configuration service and check for a stored password. - this.storeAccount(accountID, false); - - accountID = loadAccount(accountProperties); - - // Creates the dict contact group. - this.createGroup(); - // Creates the default conatct for this dict server. - this.createDefaultContact(accountID); - - return accountID; - } - - @Override - protected AccountID createAccountID(String userID, Map accountProperties) - { - return new DictAccountID(userID, accountProperties); - } - - @Override - protected ProtocolProviderService createService(String userID, - AccountID accountID) - { - ProtocolProviderServiceDictImpl service = - new ProtocolProviderServiceDictImpl(); - - service.initialize(userID, accountID); - return service; - } - - /** - * Creates a group for the dict contacts - */ - private void createGroup() - { - // Get MetaContactListService - BundleContext bundleContext = getBundleContext(); - ServiceReference mfcServiceRef - = bundleContext.getServiceReference(MetaContactListService.class); - - MetaContactListService mcl = bundleContext.getService(mfcServiceRef); - - try - { - String groupName = DictActivator.getResources() - .getI18NString("service.protocol.DICTIONARIES"); - - mcl.createMetaContactGroup(mcl.getRoot(), groupName); - } - catch (MetaContactListException ex) - { - int errorCode = ex.getErrorCode(); - if (errorCode != MetaContactListException.CODE_GROUP_ALREADY_EXISTS_ERROR) - { - logger.error(ex); - } - } - } - - /** - * Creates a default contact for the new DICT server. - * @param accountID The accountID of the dict protocol provider for which we - * want to add a default contact. - */ - private void createDefaultContact(AccountID accountID) - { - // Gets the MetaContactListService. - BundleContext bundleContext = getBundleContext(); - ServiceReference mfcServiceRef - = bundleContext.getServiceReference(MetaContactListService.class); - MetaContactListService mcl = bundleContext.getService(mfcServiceRef); - - // Gets the ProtocolProviderService. - ServiceReference serRef - = getProviderForAccount(accountID); - ProtocolProviderService protocolProvider - = DictActivator.getBundleContext().getService(serRef); - - // Gets group name - String groupName = DictActivator.getResources() - .getI18NString("service.protocol.DICTIONARIES"); - - // Gets contact name - String contactName = DictActivator.getResources() - .getI18NString("plugin.dictaccregwizz.ANY_DICTIONARY_FORM", - new String[] {accountID.getUserID()}); - - // Gets the MetaContactGroup for the "dictionaries" group. - MetaContactGroup group = mcl.getRoot().getMetaContactSubgroup(groupName); - - // Sets the default contact identifier to "*" corresponding to "all the - // dictionaries" available on the server (cf. RFC-2229). - String dict_uin = "*"; - // Create the default contact. - mcl.createMetaContact(protocolProvider, group, dict_uin); - // Rename the default contact. - mcl.renameMetaContact( - group.getMetaContact(protocolProvider, dict_uin), - contactName); - } - - @Override - public void modifyAccount( - ProtocolProviderService protocolProvider, - Map accountProperties) - throws NullPointerException - { - // TODO Auto-generated method stub - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderServiceDictImpl.java b/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderServiceDictImpl.java deleted file mode 100644 index aa9ef50..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/ProtocolProviderServiceDictImpl.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.dict; - -import net.java.dict4j.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.version.*; -import org.osgi.framework.*; - -/** - * A Dict implementation of the ProtocolProviderService. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class ProtocolProviderServiceDictImpl - extends AbstractProtocolProviderService -{ - private static final Logger logger - = Logger.getLogger(ProtocolProviderServiceDictImpl.class); - - /** - * The name of this protocol. - */ - public static final String DICT_PROTOCOL_NAME = "Dict"; - - /** - * The id of the account that this protocol provider represents. - */ - private DictAccountID accountID = null; - - /** - * We use this to lock access to initialization. - */ - private Object initializationLock = new Object(); - - /** - * Indicates whether or not the provider is initialized and ready for use. - */ - private boolean isInitialized = false; - - /** - * The logo corresponding to the gibberish protocol. - */ - private ProtocolIconDictImpl dictIcon = new ProtocolIconDictImpl(); - - /** - * The registration state that we are currently in. Note that in a real - * world protocol implementation this field won't exist and the registration - * state would be retrieved from the protocol stack. - */ - private RegistrationState currentRegistrationState - = RegistrationState.UNREGISTERED; - - /** - * the DictConnection opened by this provider - */ - private DictConnection dictConnection; - - /** - * The default constructor for the Dict protocol provider. - */ - public ProtocolProviderServiceDictImpl() - { - if (logger.isTraceEnabled()) - logger.trace("Creating a Dict provider."); - } - - /** - * Initializes the service implementation, and puts it in a sate where it - * could interoperate with other services. It is strongly recomended that - * properties in this Map be mapped to property names as specified by - * AccountProperties. - * - * @param userID the user id of the gibberish account we're currently - * initializing - * @param accountID the identifier of the account that this protocol - * provider represents. - * - * @see net.java.sip.communicator.service.protocol.AccountID - */ - protected void initialize(String userID, - AccountID accountID) - { - synchronized(initializationLock) - { - this.accountID = (DictAccountID) accountID; - - this.dictConnection = new DictConnection(this.accountID.getHost(), - this.accountID.getPort()); - this.dictConnection.setClientName(getSCVersion()); - - //initialize the presence operationset - OperationSetPersistentPresenceDictImpl persistentPresence = - new OperationSetPersistentPresenceDictImpl(this); - - addSupportedOperationSet( - OperationSetPersistentPresence.class, - persistentPresence); - //register it once again for those that simply need presence and - //won't be smart enough to check for a persistent presence - //alternative - addSupportedOperationSet( - OperationSetPresence.class, - persistentPresence); - - //initialize the IM operation set - addSupportedOperationSet( - OperationSetBasicInstantMessaging.class, - new OperationSetBasicInstantMessagingDictImpl( - this, - persistentPresence)); - - //initialize the typing notifications operation set - /*OperationSetTypingNotifications typingNotifications = - new OperationSetTypingNotificationsDictImpl( - this, persistentPresence); - - supportedOperationSets.put( - OperationSetTypingNotifications.class.getName(), - typingNotifications); - */ - isInitialized = true; - } - } - - /** - * Returns the DictConnection opened by this provider - * @return the DictConnection opened by this provider - */ - public DictConnection getConnection() - { - return this.dictConnection; - } - - /** - * Returns the AccountID that uniquely identifies the account represented - * by this instance of the ProtocolProviderService. - * - * @return the id of the account represented by this provider. - */ - public AccountID getAccountID() - { - return accountID; - } - - /** - * Returns the short name of the protocol that the implementation of this - * provider is based upon (like SIP, Jabber, ICQ/AIM, or others for - * example). - * - * @return a String containing the short name of the protocol this - * service is implementing (most often that would be a name in - * ProtocolNames). - */ - public String getProtocolName() - { - return DICT_PROTOCOL_NAME; - } - - /** - * Returns the dict protocol icon. - * @return the dict protocol icon - */ - public ProtocolIcon getProtocolIcon() - { - return this.dictIcon; - } - - /** - * Returns the state of the registration of this protocol provider with - * the corresponding registration service. - * - * @return ProviderRegistrationState - */ - public RegistrationState getRegistrationState() - { - return currentRegistrationState; - } - - /** - * Starts the registration process. - * - * @param authority the security authority that will be used for - * resolving any security challenges that may be returned during the - * registration or at any moment while wer're registered. - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void register(SecurityAuthority authority) - throws OperationFailedException - { - // Try to connect to the server - boolean connected = connect(); - - if (connected) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.REGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, - null); - currentRegistrationState = RegistrationState.REGISTERED; - } - else - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_SERVER_NOT_FOUND, - null); - currentRegistrationState = RegistrationState.UNREGISTERED; - } - } - - /** - * Checks if the connection to the dict server is open - * @return TRUE if the connection is open - FALSE otherwise - */ - private boolean connect() - { - if (this.dictConnection.isConnected()) - { - return true; - } - - try - { - return this.dictConnection.isAvailable(); - } - catch (DictException dx) - { - if (logger.isInfoEnabled()) - logger.info(dx); - } - - return false; - } - - /** - * Makes the service implementation close all open sockets and release - * any resources that it might have taken and prepare for - * shutdown/garbage collection. - */ - public void shutdown() - { - if(!isInitialized) - { - return; - } - if (logger.isTraceEnabled()) - logger.trace("Killing the Dict Protocol Provider for account " - + this.accountID.getUserID()); - - closeConnection(); - - if(isRegistered()) - { - try - { - //do the unregistration - unregister(); - } - catch (OperationFailedException ex) - { - //we're shutting down so we need to silence the exception here - logger.error( - "Failed to properly unregister before shutting down. " - + getAccountID() - , ex); - } - } - - isInitialized = false; - } - - /** - * Ends the registration of this protocol provider with the current - * registration service. - * - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void unregister() - throws OperationFailedException - { - closeConnection(); - - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, - null); - } - - /** - * DICT has no support for secure transport. - */ - public boolean isSignalingTransportSecure() - { - return false; - } - - /** - * Returns the "transport" protocol of this instance used to carry the - * control channel for the current protocol service. - * - * @return The "transport" protocol of this instance: TCP. - */ - public TransportProtocol getTransportProtocol() - { - return TransportProtocol.TCP; - } - - /** - * Close the connection to the server - */ - private void closeConnection() - { - try - { - this.dictConnection.close(); - } - catch (DictException dx) - { - if (logger.isInfoEnabled()) - logger.info(dx); - } - } - - /** - * Returns the current version of SIP-Communicator - * @return the current version of SIP-Communicator - */ - private String getSCVersion() - { - BundleContext bc = DictActivator.getBundleContext(); - ServiceReference vsr = bc.getServiceReference(VersionService.class.getName()); - - VersionService vs = (VersionService) bc.getService(vsr); - return vs.getCurrentVersion().toString(); - - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/dict/dict.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/dict/dict.provider.manifest.mf deleted file mode 100644 index d764657..0000000 --- a/src/net/java/sip/communicator/impl/protocol/dict/dict.provider.manifest.mf +++ /dev/null @@ -1,15 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.impl.protocol.dict.DictActivator -Bundle-Name: Dict Protocol Provider -Bundle-Description: A bundle providing support for the Dict protocol. -Bundle-Vendor: jitsi.org -Bundle-Version: 1.0.0 -Bundle-SymbolicName: net.java.sip.communicator.protocol.dict -Import-Package: org.osgi.framework, - org.jitsi.service.version, - net.java.sip.communicator.service.contactlist, - org.jitsi.service.configuration, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, -Export-Package: net.java.dict4j diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccRegWizzActivator.java deleted file mode 100644 index 7911eeb..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccRegWizzActivator.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Registers the DictAccountRegistrationWizard in the UI Service. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class DictAccRegWizzActivator - implements BundleActivator -{ - /** - * OSGi bundle context. - */ - public static BundleContext bundleContext; - - private static Logger logger = Logger.getLogger( - DictAccRegWizzActivator.class); - - private static BrowserLauncherService browserLauncherService; - - private static WizardContainer wizardContainer; - - private static DictAccountRegistrationWizard dictWizard; - - private static UIService uiService; - - /** - * Starts this bundle. - * - * @param bc The bundle context. - */ - public void start(BundleContext bc) throws Exception { - - bundleContext = bc; - - ServiceReference uiServiceRef = bundleContext - .getServiceReference(UIService.class.getName()); - - uiService = (UIService) bundleContext.getService(uiServiceRef); - - wizardContainer = uiService.getAccountRegWizardContainer(); - - dictWizard = new DictAccountRegistrationWizard(wizardContainer); - - //wizardContainer.addAccountRegistrationWizard(dictWizard); - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.DICT); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - dictWizard, - containerFilter); - } - - - /** - * Stops this bundle. - * - * @param bundleContext The bundle context (unused). - * - * @throws Exception Throws an execption from the - * "wizardContainer.removeAccountRegistrationWizard" method. - * - */ - public void stop(BundleContext bundleContext) throws Exception - { - //wizardContainer.removeAccountRegistrationWizard(dictWizard); - } - - /** - * Returns the ProtocolProviderFactory for the Dict protocol. - * @return the ProtocolProviderFactory for the Dict protocol - */ - public static ProtocolProviderFactory getDictProtocolProviderFactory() { - - ServiceReference[] serRefs = null; - - String osgiFilter = "(" - + ProtocolProviderFactory.PROTOCOL - + "="+ProtocolNames.DICT+")"; - - try { - serRefs = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex){ - logger.error("DictAccRegWizzActivator : " + ex); - } - - return (ProtocolProviderFactory) bundleContext.getService(serRefs[0]); - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() { - if (browserLauncherService == null) { - ServiceReference serviceReference = bundleContext - .getServiceReference(BrowserLauncherService.class.getName()); - - browserLauncherService = (BrowserLauncherService) bundleContext - .getService(serviceReference); - } - - return browserLauncherService; - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistration.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistration.java deleted file mode 100644 index a7aca60..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistration.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import net.java.dict4j.*; - -/** - * The DictAccountRegistration is used to store all user input data - * through the DictAccountRegistrationWizard. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class DictAccountRegistration -{ - private String userID; - - /** - * The hostname of the DICT server. - */ - private String host; - - /** - * The port of the DICT server. - */ - private int port; - - /** - * The strategy selected for the matching of words in dictionaries. - */ - private Strategy strategy; - - /** - * Returns the User ID of the dict registration account. - * @return the User ID of the dict registration account. - */ - public String getUserID() - { - return userID; - } - - /** - * Returns the port of the dict registration account. - * @return the port of the dict registration account. - */ - public int getPort() { - return this.port; - } - - /** - * Sets the port of the dict registration account. - * @param port the port of the dict registration account. - */ - public void setPort(int port) { - this.port = port; - } - - /** - * Returns the host of the dict registration account. - * @return the host of the dict registration account. - */ - public String getHost() { - return this.host; - } - - /** - * Sets the host of the dict registration account. - * @param host The host of the dict registration account. - */ - public void setHost(String host) { - this.host = host; - } - - /** - * Returns the strategy that will be used for this dict account. - * @return the strategy that will be used for this dict account. - */ - public Strategy getStrategy() { - return this.strategy; - } - - /** - * Sets the strategy for this dict account. - * @param strategy the strategy for this dict account. - */ - public void setStrategy(Strategy strategy) { - this.strategy = strategy; - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistrationWizard.java deleted file mode 100644 index 115d65c..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/DictAccountRegistrationWizard.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.awt.*; -import java.util.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The DictAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Dict protocol. It should allow - * the user to create and configure a new Dict account. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class DictAccountRegistrationWizard - extends DesktopAccountRegistrationWizard -{ - private final Logger logger - = Logger.getLogger(DictAccountRegistrationWizard.class); - - /** - * The reference to the first page of the wizard. - */ - private FirstWizardPage firstWizardPage; - - /** - * The registration of the DICT account. - */ - private DictAccountRegistration registration = new DictAccountRegistration(); - - /** - * The protocole provider. - */ - private ProtocolProviderService protocolProvider; - - /** - * Creates an instance of DictAccountRegistrationWizard. - * - * @param wizardContainer the wizard container, where this wizard is added - */ - public DictAccountRegistrationWizard(WizardContainer wizardContainer) - { - setWizardContainer(wizardContainer); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * @return Returns the icon to be used for this wizard. - */ - @Override - public byte[] getIcon() - { - return Resources.getImage(Resources.DICT_LOGO); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage - * method. Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Resources.getImage(Resources.PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. - * @return Returns the protocol name for this wizard. - */ - @Override - public String getProtocolName() - { - return Resources.getString("plugin.dictaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. - * @return Returns the description of the protocol for this wizard. - */ - @Override - public String getProtocolDescription() - { - return Resources.getString("plugin.dictaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns the set of pages contained in this wizard. - * - * @return Returns the set of pages contained in this wizard. - */ - @Override - public Iterator getPages() - { - java.util.List pages = new ArrayList(); - this.firstWizardPage = new FirstWizardPage(this); - pages.add(this.firstWizardPage); - return pages.iterator(); - } - - /** - * Returns the set of data that user has entered through this wizard. - * @return Returns the set of data that user has entered through this wizard. - */ - @Override - public Iterator> getSummary() - { - Map summaryTable = new LinkedHashMap(); - - summaryTable.put("Host", registration.getHost()); - summaryTable.put("Port", String.valueOf(registration.getPort())); - summaryTable.put("Strategy", registration.getStrategy().getName()); - - return summaryTable.entrySet().iterator(); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin() - throws OperationFailedException - { - firstWizardPage.commitPage(); - - return signin(registration.getUserID(), null); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @param userName the user name to sign in with - * @param password the password to sign in with - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin(String userName, String password) - throws OperationFailedException - { - ProtocolProviderFactory factory - = DictAccRegWizzActivator.getDictProtocolProviderFactory(); - - return this.installAccount(factory, registration.getHost(), - registration.getPort(), - registration.getStrategy().getCode()); - } - - /** - * Creates an account for the given user and password. - * - * @param providerFactory the ProtocolProviderFactory which will create the - * account. - * @param host The hostname of the DICT server. - * @param port The port used by the DICT server. - * @param strategy The strategy choosen for matching words in the - * dictionnaries. - * @return the ProtocolProviderService for the new account. - */ - public ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, - String host, - int port, - String strategy) - throws OperationFailedException - { - Hashtable accountProperties - = new Hashtable(); - - accountProperties.put( ProtocolProviderFactory.ACCOUNT_ICON_PATH, - "resources/images/protocol/dict/dict-32x32.png"); - - // Set this property to indicate that Dict account does not require - // authentication. - accountProperties.put( - ProtocolProviderFactory.NO_PASSWORD_REQUIRED, - new Boolean(true).toString()); - - // Save host - accountProperties.put(ProtocolProviderFactory.SERVER_ADDRESS, host); - // Save port - accountProperties.put( ProtocolProviderFactory.SERVER_PORT, - String.valueOf(port)); - // Save strategy - accountProperties.put(ProtocolProviderFactory.STRATEGY, strategy); - - if (isModification()) - { - providerFactory.uninstallAccount(protocolProvider.getAccountID()); - this.protocolProvider = null; - setModification(false); - } - - try - { - String uid = this.generateUID(); - AccountID accountID = - providerFactory.installAccount(uid, accountProperties); - - ServiceReference serRef = - providerFactory.getProviderForAccount(accountID); - - protocolProvider = - (ProtocolProviderService) DictAccRegWizzActivator.bundleContext - .getService(serRef); - } - catch (IllegalStateException exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Account already exists.", - OperationFailedException.IDENTIFICATION_CONFLICT); - } - catch (Exception exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Failed to add account", - OperationFailedException.GENERAL_ERROR); - } - - - return protocolProvider; - } - - /** - * Fills the UIN and Password fields in this panel with the data coming - * from the given protocolProvider. - * - * @param protocolProvider The ProtocolProviderService to load - * the data from. - */ - @Override - public void loadAccount(ProtocolProviderService protocolProvider) - { - setModification(true); - - this.protocolProvider = protocolProvider; - - this.registration = new DictAccountRegistration(); - - this.firstWizardPage.loadAccount(protocolProvider); - } - - /** - * Returns the registration object, which will store all the data through - * the wizard. - * - * @return the registration object, which will store all the data through - * the wizard - */ - public DictAccountRegistration getRegistration() - { - return registration; - } - - /** - * Returns the size of this wizard. - * @return the size of this wizard - */ - @Override - public Dimension getSize() - { - return new Dimension(300, 150); - } - - /** - * Returns the identifier of the page to show first in the wizard. - * @return the identifier of the page to show first in the wizard. - */ - @Override - public Object getFirstPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns the identifier of the page to show last in the wizard. - * @return the identifier of the page to show last in the wizard. - */ - @Override - public Object getLastPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Generate the UID for the acount - * @return the new UID - */ - private String generateUID() - { - String uid; - int nbAccounts = this.getNumberOfAccounts(); - String host = this.registration.getHost(); - int nbAccountsForHost = this.getNbAccountForHost(host); - - if (nbAccounts == 0 || (this.isModification() && nbAccounts == 1) || - nbAccountsForHost == 0 - || (this.isModification() && nbAccountsForHost == 1)) - { - // We create the first account or we edit the onlyone - // Or we create the first account for this server or edit the onlyone - uid = host; - } - else - { - uid = host + ":" + this.registration.getPort(); - } - - return uid; - } - - /** - * Returns the number of accounts stored for the protocol - * @return the number of accounts stored for the protocol - */ - private int getNumberOfAccounts() - { - ProtocolProviderFactory factory = - DictAccRegWizzActivator.getDictProtocolProviderFactory(); - - return factory.getRegisteredAccounts().size(); - } - - /** - * Returns the number of account for a given host - * @param hostName the host - * @return the number of account for a given host - */ - private int getNbAccountForHost(String host) - { - ProtocolProviderFactory factory = - DictAccRegWizzActivator.getDictProtocolProviderFactory(); - - ArrayList registeredAccounts - = factory.getRegisteredAccounts(); - int total = 0; - - for (int i = 0; i < registeredAccounts.size(); i++) - { - AccountID accountID = registeredAccounts.get(i); - - // The host is always stored at the start - if (accountID.getUserID().startsWith(host.toLowerCase())) - { - total++; - } - } - return total; - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return null; - } - - /** - * Indicates whether this wizard enables the simple "sign in" form shown - * when the user opens the application for the first time. The simple - * "sign in" form allows user to configure her account in one click, just - * specifying her username and password and leaving any other configuration - * as by default. - * @return true if the simple "Sign in" form is enabled or - * false otherwise. - */ - @Override - public boolean isSimpleFormEnabled() - { - return false; - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - firstWizardPage = new FirstWizardPage(this); - - return firstWizardPage.getSimpleForm(); - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/FirstWizardPage.java deleted file mode 100644 index 59cfd27..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/FirstWizardPage.java +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.awt.*; -import java.awt.event.*; -import java.util.List; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.dict4j.*; -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; - -/** - * The FirstWizardPage is the page, where user could enter the host, - * port and the strategy of the account. - * - * @author ROTH Damien - * @author LITZELMANN Cedric - */ -public class FirstWizardPage - extends TransparentPanel - implements WizardPage, DocumentListener, ActionListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier"; - - private JPanel hostPortPanel = new TransparentPanel(new BorderLayout(10, 10)); - - private JPanel labelsPanel = new TransparentPanel(); - - private JPanel valuesPanel = new TransparentPanel(); - - private JLabel hostLabel - = new JLabel(Resources.getString("plugin.dictaccregwizz.HOST")); - - private JPanel emptyPanel = new TransparentPanel(); - - private JLabel hostExampleLabel = new JLabel("Ex: dict.org"); - - private JLabel portLabel - = new JLabel(Resources.getString("service.gui.PORT")); - - private JTextField hostField = new JTextField(); - - private JTextField portField = new JTextField("2628"); - - private JPanel strategyPanel = new TransparentPanel(new BorderLayout(10, 10)); - - private JPanel strategyTitleBloc = new TransparentPanel(new BorderLayout()); - - private JLabel strategyTitle = new JLabel(Resources.getString( - "plugin.dictaccregwizz.STRATEGY_LIST")); - - private JButton strategyLoader - = new JButton(Resources.getString( - "plugin.dictaccregwizz.SEARCH_STRATEGIES")); - - private StrategiesList strategiesList; - - private JTextArea strategyDescription - = new JTextArea(Resources.getString( - "plugin.dictaccregwizz.STRATEGY_DESCRIPTION")); - - private ProgressPanel searchProgressPanel; - - private JPanel mainPanel = new TransparentPanel(new BorderLayout()); - - private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER; - - private DictAccountRegistrationWizard wizard; - - private String initstrategy = ""; - - private ThreadManager searchThread = null; - - private boolean firstAccount = false; - - private boolean isPageCommitted = false; - - /** - * Initial AccountID (null if new account) - * Used to check if there are modifications to the account - */ - private AccountID initAccountID = null; - - /** - * Creates an instance of FirstWizardPage. - * - * @param wizard the parent wizard - */ - public FirstWizardPage(DictAccountRegistrationWizard wizard) - { - super(new BorderLayout()); - - this.wizard = wizard; - - this.setPreferredSize(new Dimension(300, 150)); - - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - - this.searchThread = new ThreadManager(this); - this.searchProgressPanel = new ProgressPanel(this.searchThread); - - this.firstAccount = !this.hasAccount(); - - if (this.firstAccount) - { - this.initFirstAccount(); - } - else - { - this.init(); - } - - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - } - - /** - * Initializes all panels, buttons, etc. - */ - private void init() - { - // Host and port Field - this.hostField = new JTextField(); - this.portField = new JTextField("2628"); - - this.hostField.getDocument().addDocumentListener(this); - this.portField.getDocument().addDocumentListener(this); - - this.hostExampleLabel.setForeground(Color.GRAY); - this.hostExampleLabel.setFont(hostExampleLabel.getFont().deriveFont(8)); - this.emptyPanel.setMaximumSize(new Dimension(40, 35)); - this.hostExampleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, - 0)); - - labelsPanel.add(hostLabel); - labelsPanel.add(emptyPanel); - labelsPanel.add(portLabel); - - valuesPanel.add(hostField); - valuesPanel.add(hostExampleLabel); - valuesPanel.add(portField); - - hostPortPanel.add(labelsPanel, BorderLayout.WEST); - hostPortPanel.add(valuesPanel, BorderLayout.CENTER); - - hostPortPanel.setBorder(BorderFactory.createTitledBorder( - Resources.getString("plugin.dictaccregwizz.SERVER_INFO"))); - - this.labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); - this.valuesPanel.setLayout(new BoxLayout(valuesPanel, BoxLayout.Y_AXIS)); - - mainPanel.add(hostPortPanel); - - this.portField.addKeyListener(new KeyListener() { - public void keyTyped(KeyEvent evt) - { - // If evt isn't a digit, we don't add it - if (!Character.isDigit(evt.getKeyChar())) - { - evt.consume(); - } - } - - // Not used - public void keyPressed(KeyEvent evt) {;} - public void keyReleased(KeyEvent evt) {;} - }); - - // Strategies list - this.strategiesList = new StrategiesList(); - - JScrollPane scrollPane = new JScrollPane(); - scrollPane.getViewport().add(this.strategiesList); - this.strategyPanel.add(scrollPane); - - // Strategy title + button - this.strategyTitleBloc.add(this.strategyTitle, BorderLayout.WEST); - this.strategyTitleBloc.add(this.strategyLoader, BorderLayout.EAST); - - // Button action listener - this.strategyLoader.setActionCommand("populateList"); - this.strategyLoader.addActionListener(this); - - // South Panel - JPanel sSouthPanel = new TransparentPanel(new BorderLayout()); - - // Description - this.strategyDescription.setLineWrap(true); - this.strategyDescription.setLineWrap(true); - this.strategyDescription.setRows(4); - this.strategyDescription.setWrapStyleWord(true); - this.strategyDescription.setAutoscrolls(false); - sSouthPanel.add(this.strategyDescription); - - // Message - sSouthPanel.add(this.searchProgressPanel, BorderLayout.SOUTH); - - this.strategyPanel.add(sSouthPanel, BorderLayout.SOUTH); - - this.strategyPanel.add(this.strategyTitleBloc, BorderLayout.NORTH); - this.strategyPanel.setBorder(BorderFactory.createTitledBorder( - Resources.getString("plugin.dictaccregwizz.STRATEGY_SELECTION"))); - mainPanel.add(this.strategyPanel); - - this.add(mainPanel, BorderLayout.NORTH); - } - - /** - * Initialize the UI for the first account - */ - private void initFirstAccount() - { - // Data init - this.hostField = new JTextField("dict.org"); - this.portField = new JTextField("2628"); - - // Init strategies list - this.strategiesList = new StrategiesList(); - - this.mainPanel = new TransparentPanel(new BorderLayout()); - - JPanel infoTitlePanel - = new TransparentPanel(new FlowLayout(FlowLayout.CENTER)); - JTextArea firstDescription - = new JTextArea(Resources.getString( - "plugin.dictaccregwizz.FIRST_ACCOUNT")); - JLabel title - = new JLabel(Resources.getString( - "plugin.dictaccregwizz.ACCOUNT_INFO_TITLE")); - - // Title - title.setFont(title.getFont().deriveFont(Font.BOLD, 14.0f)); - infoTitlePanel.add(title); - this.mainPanel.add(infoTitlePanel, BorderLayout.NORTH); - this.mainPanel.add(this.searchProgressPanel, BorderLayout.SOUTH); - - // Description - firstDescription.setLineWrap(true); - firstDescription.setEditable(false); - firstDescription.setOpaque(false); - firstDescription.setRows(6); - firstDescription.setWrapStyleWord(true); - firstDescription.setAutoscrolls(false); - this.mainPanel.add(firstDescription); - } - - /** - * Implements the WizardPage.getIdentifier to return this - * page identifier. - * - * @return Returns the identifier of the current (the first) page of the - * wizard. - */ - public Object getIdentifier() - { - return FIRST_PAGE_IDENTIFIER; - } - - /** - * Implements the WizardPage.getNextPageIdentifier to return - * the next page identifier - the summary page. - * - * @return Returns the identifier of the next page of the wizard. - */ - public Object getNextPageIdentifier() - { - return nextPageIdentifier; - } - - /** - * Implements the WizardPage.getBackPageIdentifier to return - * the back identifier, which is null as this is the first wizard page. - * - * @return the identifier of the previous page of the wizard. - */ - public Object getBackPageIdentifier() - { - return null; - } - - /** - * Implements the WizardPage.getWizardForm to return this - * panel. - * @return Returns this form of the wizard. - */ - public Object getWizardForm() - { - return this; - } - - /** - * Before this page is displayed enables or disables the "Next" wizard - * button according to whether the UIN field is empty. - */ - public void pageShowing() - { - this.setNextButtonEnabled(); - } - - /** - * Saves the user input when the "Next" wizard buttons is clicked. - */ - public void commitPage() - { - String host = hostField.getText(); - int port = Integer.parseInt(portField.getText()); - boolean isModified = false; - - if (this.initAccountID != null) - { // We check if there are modifications to the server - String accHost = - this.initAccountID.getAccountPropertyString( - ProtocolProviderFactory.SERVER_ADDRESS); - int accPort = - Integer.parseInt(this.initAccountID - .getAccountPropertyString(ProtocolProviderFactory.SERVER_PORT)); - - if (((accHost == null) ? (host != null) : !accHost.equals(host)) - || (accPort != port)) - { - isModified = true; - } - } - - // We check if a strategy has been selected - if (this.strategiesList.getModel().getSize() == 0) - { // No Strategy, we get them - this.populateStrategies(); - - if (!this.searchThread.waitThread()) - { - // TODO error dialog : thread interrupted ? no thread ? - this.strategiesList.clear(); - } - } - - if (this.strategiesList.getModel().getSize() == 0) - { - // No strategy, maybe not connected - // Information message is already on the wizard - nextPageIdentifier = FIRST_PAGE_IDENTIFIER; - this.revalidate(); - } - else - { - nextPageIdentifier = SUMMARY_PAGE_IDENTIFIER; - - DictAccountRegistration registration = wizard.getRegistration(); - - registration.setHost(host); - registration.setPort(port); - registration.setStrategy( - (Strategy) this.strategiesList.getSelectedValue()); - } - - isPageCommitted = true; - } - - /** - * Enables or disables the "Next" wizard button according to whether the UIN - * field is empty. - */ - private void setNextButtonEnabled() - { - boolean hostOK = DictConnection.isUrl(hostField.getText()); - boolean portOK = (this.portField.getText().length() != 0) - && Integer.parseInt(this.portField.getText()) > 10; - - if (this.firstAccount) - { - wizard.getWizardContainer().setNextFinishButtonEnabled(true); - } - else if (hostOK && portOK) - { - this.strategyLoader.setEnabled(true); - wizard.getWizardContainer().setNextFinishButtonEnabled(true); - } - else - { - // Disable the finish button - wizard.getWizardContainer().setNextFinishButtonEnabled(false); - - // Clear the list and disable the button - this.strategiesList.clear(); - this.strategyLoader.setEnabled(false); - } - } - - /** - * Handles the DocumentEvent triggered when user types in the UIN - * field. Enables or disables the "Next" wizard button according to whether - * the UIN field is empty. - * - * @param e the DocumentEvent triggered when user types in the UIN - * field. - */ - public void insertUpdate(DocumentEvent e) - { - this.setNextButtonEnabled(); - } - - /** - * Handles the DocumentEvent triggered when user deletes letters - * from the UIN field. Enables or disables the "Next" wizard button - * according to whether the UIN field is empty. - * - * @param e The DocumentEvent triggered when user deletes letters - * from the UIN field. - */ - public void removeUpdate(DocumentEvent e) - { - this.setNextButtonEnabled(); - } - - /** - * Handles the DocumentEvent triggered when user changes an - * attribute or set of attributes from the UIN field. - * Currently this notification has no effect and is just here to implement - * the DocumentListener interface. - * - * @param e The DocumentEvent triggered when an attribute or set of - * attributes changed from the UIN field. - */ - public void changedUpdate(DocumentEvent e) - { - } - - /** - * Invoked when this WizardPage will be hidden eighter because the user has - * clicked "Back" or "Next". - * This function has no effect. - */ - public void pageHiding() - { - } - - /** - * Invoked when this WizardPage will be shown eighter because the user has - * clicked "Back" on the next wizard page or "Next" on the previous one. - * This function has no effect. - */ - public void pageShown() - { - } - - /** - * Invoked when user clicks on the "Back" wizard button. - * This function has no effect. - */ - public void pageBack() - { - } - - /** - * Fills the Host, Port and Strategy fields in this panel with the data comming - * from the given protocolProvider. - * - * @param protocolProvider The ProtocolProviderService to load - * the data from. - */ - public void loadAccount(ProtocolProviderService protocolProvider) - { - AccountID accountID = protocolProvider.getAccountID(); - String host = - accountID - .getAccountPropertyString(ProtocolProviderFactory.SERVER_ADDRESS); - String port = - accountID - .getAccountPropertyString(ProtocolProviderFactory.SERVER_PORT); - String strategy = - accountID - .getAccountPropertyString(ProtocolProviderFactory.STRATEGY); - - this.initAccountID = accountID; - - // Host field - this.hostField.setText(host); - - // Port Field - this.portField.setText(port); - - // Load strategies - this.initstrategy = strategy; - this.populateStrategies(); - } - - /** - * Handles the action of the button. - * - * @param e The event generated when the button is pressed. - */ - public void actionPerformed(ActionEvent e) - { - // Button action -> populate the list - if (e.getActionCommand().equals("populateList")) - { - this.populateStrategies(); - } - } - - /** - * Checks if an account is stored for this protocol - * @return TRUE, if an account is stored - FALSE otherwise - */ - private boolean hasAccount() - { - ProtocolProviderFactory factory = - DictAccRegWizzActivator.getDictProtocolProviderFactory(); - - return !factory.getRegisteredAccounts().isEmpty(); - } - - /** - * Start the thread which will populate the Strategies List - */ - public void populateStrategies() - { - // Clear ArrayList - this.strategiesList.clear(); - - boolean ok = this.searchThread.submitRequest(this.hostField.getText(), - Integer.parseInt(this.portField.getText())); - - if (!ok) - { - // TODO Display error - } - } - - /** - * Automatic selection of a strategy - */ - public void autoSelectStrategy() - { - this.strategiesList.autoSelectStrategy(this.initstrategy); - } - - /** - * - * @param strategies - */ - public void setStrategies(List strategies) - { - this.strategiesList.setStrategies(strategies); - } - - /** - * Informs the user of the current status of the search - * Should only be called by the thread - * @param message Search status - */ - public void progressMessage(String message) - { - this.searchProgressPanel.nextStep(message); - } - - /** - * Informs the wizard that the search of the strategies is complete. - * Should only be called by the thread - */ - public void strategiesSearchComplete() - { - setStrategyButtonEnable(true); - this.searchProgressPanel.finish(); - } - - /** - * Informs the wizard that the search of the strategies is a failure - * Should only be called by the thread - * @param reason Reason message - * @param de Exception thrown - */ - public void strategiesSearchFailure(String reason, DictException de) - { - strategiesSearchComplete(); - // TODO SHOW ERROR MESSAGE - } - - /** - * Enables or disable the Next Button and the Strategy Button - * @param e TRUE enables - FALSE disables - */ - public void setStrategyButtonEnable(boolean e) - { - // During all the process the buttons and the fieldsset are in the same state - - this.hostField.setEnabled(e); - this.portField.setEnabled(e); - - this.strategyLoader.setEnabled(e); - wizard.getWizardContainer().setNextFinishButtonEnabled(e); - } - - public Object getSimpleForm() - { - return mainPanel; - } - - /** - * Indicates if this is the first dict account - * - * @return TRUE if this is the first dict account - FALSE otherwise - */ - public boolean isFirstAccount() - { - return this.firstAccount; - } - - public boolean isCommitted() - { - return isPageCommitted; - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/ProgressPanel.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/ProgressPanel.java deleted file mode 100644 index 7d46fa5..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/ProgressPanel.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * Panel showing the current status of the search of the strategies - * - * @author ROTH Damien - */ -public class ProgressPanel - extends TransparentPanel - implements ActionListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private JPanel rightPanel; - - private JLabel messageLabel; - private JLabel progressLabel; - private JButton cancelButton; - - private int currentStep; - private int totalSteps; - - private boolean isBuild; - - private ThreadManager searchThread; - - /** - * Create an instance of ProgressPanel - * @param searchThread The thread manager - */ - public ProgressPanel(ThreadManager searchThread) - { - super(new BorderLayout()); - - // Element creation - this.messageLabel = new JLabel(" "); - this.progressLabel = new JLabel(" "); - this.cancelButton - = new JButton(Resources.getString("service.gui.CANCEL")); - this.cancelButton.addActionListener(this); - - // Right panel init - this.rightPanel = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); - this.rightPanel.add(this.progressLabel); - this.rightPanel.add(this.cancelButton); - - this.searchThread = searchThread; - - init(); - this.totalSteps = ThreadManager.NB_STEPS; - } - - /** - * Init the values - */ - private void init() - { - this.isBuild = false; - this.currentStep = 1; - - this.add(this.messageLabel, BorderLayout.CENTER); - } - - /** - * Build the UI - */ - private void build() - { - if (this.isBuild) - { - return; - } - - this.add(this.messageLabel, BorderLayout.CENTER); - this.add(this.rightPanel, BorderLayout.EAST); - - this.isBuild = true; - } - - /** - * Move to the next step without updating the message - */ - public void nextStep() - { - nextStep(this.messageLabel.getText()); - } - - /** - * Mode to the next step with a new message - * @param message Message - */ - public void nextStep(String message) - { - if (this.currentStep > this.totalSteps) - { - finish(); - } - - build(); - this.messageLabel.setText(message); - this.progressLabel.setText(currentStep + "/" + totalSteps); - - this.currentStep++; - } - - /** - * Informs the end of the progress. Remove all the components and - * reset the values - */ - public void finish() - { - // Remove all elements - this.removeAll(); - - // Re-init the panel - this.messageLabel.setText(" "); - this.progressLabel.setText(" "); - init(); - - this.repaint(); - this.validate(); - } - - public void actionPerformed(ActionEvent arg0) - { - this.searchThread.cancel(); - this.finish(); - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/Resources.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/Resources.java deleted file mode 100644 index 55856be..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/Resources.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author ROTH Damien - * @author LITZELMAN Cedric - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - public static ImageID DICT_LOGO - = new ImageID("service.protocol.dict.DICT_16x16"); - - public static ImageID PAGE_IMAGE - = new ImageID("service.protocol.dict.DICT_64x64"); - - /** - * Returns an internationalized string corresponding to the given key. - * - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImage(ImageID imageID) - { - return getResources().getImageInBytes(imageID.getId()); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(DictAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/StrategiesList.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/StrategiesList.java deleted file mode 100644 index ace9127..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/StrategiesList.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.awt.*; -import java.util.*; -import java.util.List; - -import javax.swing.*; - -import net.java.dict4j.*; - -/** - * Class managing the list of strategies - * - * @author ROTH Damien - */ -public class StrategiesList - extends JList -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private ListModel model; - private CellRenderer renderer; - - /** - * Create an instance of the StrategiesList - */ - public StrategiesList() - { - super(); - - this.model = new ListModel(); - this.renderer = new CellRenderer(); - - this.setCellRenderer(this.renderer); - this.setModel(model); - this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - this.setVisibleRowCount(6); - } - - /** - * Stores a new set of strategies - * @param strategies List of strategies - */ - public void setStrategies(List strategies) - { - this.model.setStrategies(strategies); - } - - /** - * Remove all the strategies of the list - */ - public void clear() - { - this.model.clear(); - } - - /** - * Automatic selection of strategies - * @param initStrategy - */ - public void autoSelectStrategy(String initStrategy) - { - int index = -1; - - if (initStrategy.length() > 0) - { // saved strategy - index = this.model.indexOf(initStrategy); - } - if (index < 0) - { - // First case : levenstein distance - index = this.model.indexOf("lev"); - } - if (index < 0) - { - // Second case : soundex - index = this.model.indexOf("soundex"); - } - if (index < 0) - { - // Last case : prefix - index = this.model.indexOf("prefix"); - } - - // If the index is still < 0, we select the first index - if (index < 0) - { - index = 0; - } - if (index < this.getVisibleRowCount()) - { - // If the index is visible row, we don't need to scroll - this.setSelectedIndex(index); - } - else - { - // Otherwise, we scroll to the selected value - this.setSelectedValue(this.model.getElementAt(index), true); - } - } - - /** - * Class managing the list datas - * - * @author ROTH Damien - */ - static class ListModel - extends AbstractListModel - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private List data; - - /** - * Create an instance of ListModel - */ - public ListModel() - { - data = new ArrayList(); - } - - /** - * Stores the strategies into this model - * @param strategies the strategies list - */ - public void setStrategies(List strategies) - { - data = strategies; - fireContentsChanged(this, 0, data.size()); - } - - /** - * Remove all the strategies of the list - */ - public void clear() - { - data.clear(); - } - - /** - * Implements ListModel.getElementAt - */ - public Strategy getElementAt(int row) - { - return data.get(row); - } - - /** - * Implements ListModel.getSize - */ - public int getSize() - { - return data.size(); - } - - /** - * Find the index of a strategy. - * - * @param strategyCode the code of the strategy - * @return the index of the strategy - */ - public int indexOf(String strategyCode) - { - for (int i = 0, size = data.size(); i < size; i++) - { - if (data.get(i).getCode().equals(strategyCode)) - return i; - } - return -1; - } - } - - /** - * Class managing the cell rendering - * - * @author ROTH Damien - */ - static class CellRenderer - extends JLabel - implements ListCellRenderer - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * implements ListCellRenderer.getListCellRendererComponent - */ - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - setText(((Strategy) value).getName()); - - if (isSelected) - { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } - else - { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - setEnabled(list.isEnabled()); - setFont(list.getFont()); - setOpaque(true); - - return this; - } - } -} - diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/ThreadManager.java b/src/net/java/sip/communicator/plugin/dictaccregwizz/ThreadManager.java deleted file mode 100644 index 4abcc75..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/ThreadManager.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.dictaccregwizz; - -import java.util.*; - -import net.java.dict4j.*; -import net.java.sip.communicator.util.*; - -/** - * Class manager the thread called for searching the strategies' list - * - * @author ROTH Damien - */ -public class ThreadManager -{ - protected static Logger logger = Logger.getLogger(ThreadManager.class); - public static int NB_STEPS = 4; - - private StrategyThread thread = null; - private FirstWizardPage wizard = null; - - /** - * Create an instance of ThreadManager - * @param wiz Wizard - */ - public ThreadManager(FirstWizardPage wiz) - { - this.wizard = wiz; - } - - /** - * Submit a request to launch the thread - * @param host Server host - * @param port Server port - * @return TRUE if the thread is started - FALSE otherwise - */ - public boolean submitRequest(String host, int port) - { - if (this.thread != null) - { - return false; - } - - this.thread = new StrategyThread(this.wizard, host, port); - this.thread.start(); - - return true; - } - - /** - * Stop the thread - */ - public void cancel() - { - if (this.thread != null) - { - this.thread.interrupt(); - this.thread = null; - } - } - - /** - * Wait for the searching thread to stop - * @return true if success, false otherwise - */ - public boolean waitThread() - { - if (this.thread == null) - { - return false; - } - - try - { - this.thread.join(); - } - catch (InterruptedException e) - { - if (logger.isInfoEnabled()) - logger.info(e); - return false; - } - return true; - } - - /** - * Thread used to search the strategies - * - * @author ROTH Damien, LITZELMANN Cedric - */ - static class StrategyThread - extends Thread - { - private final FirstWizardPage wizard; - private final String host; - private final int port; - - /** - * Informations messages - */ - private String[] messages = new String[] { - Resources.getString( - "plugin.dictaccregwizz.THREAD_CONNECT"), - Resources.getString( - "plugin.dictaccregwizz.THREAD_CONNECT_FAILED"), - Resources.getString( - "plugin.dictaccregwizz.RETRIEVING_STRATEGIES"), - Resources.getString( - "plugin.dictaccregwizz.NO_STRATEGIES_FOUND"), - Resources.getString( - "plugin.dictaccregwizz.POPULATE_LIST"), - Resources.getString( - "plugin.dictaccregwizz.CLOSING_CONNECTION") - }; - - /** - * Create an instance of the thread - * @param wizard The wizard who started the thread - * @param host Server host - * @param port Server port - */ - public StrategyThread(FirstWizardPage wizard, String host, int port) - { - this.wizard = wizard; - this.host = host; - this.port = port; - } - - @Override - public void run() - { - List strategies = null; - - DictConnection dictConnection = new DictConnection(host, port); - - // Open the connection to the server - this.wizard.progressMessage(messages[0]); - try - { - dictConnection.connect(); - } - catch (DictException e) - { - this.wizard.strategiesSearchFailure(this.messages[1], e); - return; - } - - // Get the strategies - this.wizard.progressMessage(messages[2]); - try - { - strategies = dictConnection.getStrategies(); - } - catch (DictException e) - { - this.wizard.strategiesSearchFailure(this.messages[3], e); - return; - } - - // Store the strategies - this.wizard.progressMessage(messages[4]); - this.wizard.setStrategies(strategies); - this.wizard.autoSelectStrategy(); - - // Close the connection - this.wizard.progressMessage(messages[5]); - try - { - dictConnection.close(); - } - catch (DictException e) - { - // An error while closing the connection isn't very important - // We just log it - ThreadManager.logger.info("DICT search strategies thread : " + - "Error while closing connection", e); - } - - // End of the search - this.wizard.strategiesSearchComplete(); - } - } -} diff --git a/src/net/java/sip/communicator/plugin/dictaccregwizz/dictaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/dictaccregwizz/dictaccregwizz.manifest.mf deleted file mode 100644 index 02dc2c4..0000000 --- a/src/net/java/sip/communicator/plugin/dictaccregwizz/dictaccregwizz.manifest.mf +++ /dev/null @@ -1,34 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.dictaccregwizz.DictAccRegWizzActivator -Bundle-Name: Dict account registration wizard -Bundle-Description: Dict account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.dictaccregwizz -Import-Package: org.osgi.framework, - net.java.dict4j, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - net.java.sip.communicator.service.protocol.icqconstants, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - javax.swing, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.accessibility, - javax.swing.plaf, - javax.swing.plaf.metal, - javax.swing.plaf.basic, - javax.imageio, - javax.swing.filechooser, - javax.swing.tree, - javax.swing.undo, - javax.swing.border -- cgit v1.1 From 260015284b818e0c1b43f9821dd6007213a7805e Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:24:34 +0200 Subject: Remove the ssh protocol It has been abandoned since Oct. 2010 --- .classpath | 2 - build.xml | 21 - lib/installer-exclude/jsch-0.1.36.jar | Bin 177603 -> 0 bytes .../impl/protocol/ssh/ContactGroupSSHImpl.java | 580 ------------ .../communicator/impl/protocol/ssh/ContactSSH.java | 370 -------- .../impl/protocol/ssh/ContactSSHImpl.java | 918 ------------------- .../impl/protocol/ssh/ContactTimerSSHImpl.java | 116 --- .../impl/protocol/ssh/FileTransferSSHImpl.java | 96 -- .../impl/protocol/ssh/MessageSSHImpl.java | 63 -- .../OperationSetBasicInstantMessagingSSHImpl.java | 312 ------- .../ssh/OperationSetFileTransferSSHImpl.java | 161 ---- .../ssh/OperationSetPersistentPresenceSSHImpl.java | 980 --------------------- .../impl/protocol/ssh/ProtocolIconSSHImpl.java | 159 ---- .../protocol/ssh/ProtocolProviderFactorySSH.java | 49 -- .../ssh/ProtocolProviderFactorySSHImpl.java | 179 ---- .../ssh/ProtocolProviderServiceSSHImpl.java | 662 -------------- .../communicator/impl/protocol/ssh/Resources.java | 53 -- .../impl/protocol/ssh/SSHAccountID.java | 45 - .../impl/protocol/ssh/SSHActivator.java | 145 --- .../impl/protocol/ssh/SSHContactInfo.java | 352 -------- .../impl/protocol/ssh/SSHFileTransferDaemon.java | 468 ---------- .../impl/protocol/ssh/SSHReaderDaemon.java | 211 ----- .../impl/protocol/ssh/SSHStatusEnum.java | 138 --- .../impl/protocol/ssh/SSHUserInfo.java | 164 ---- .../impl/protocol/ssh/ssh.provider.manifest.mf | 20 - .../plugin/sshaccregwizz/FirstWizardPage.java | 423 --------- .../plugin/sshaccregwizz/Resources.java | 74 -- .../sshaccregwizz/SSHAccRegWizzActivator.java | 145 --- .../sshaccregwizz/SSHAccountRegistration.java | 101 --- .../SSHAccountRegistrationWizard.java | 342 ------- .../plugin/sshaccregwizz/sshaccregwizz.manifest.mf | 32 - 31 files changed, 7381 deletions(-) delete mode 100644 lib/installer-exclude/jsch-0.1.36.jar delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ContactGroupSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ContactSSH.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ContactSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ContactTimerSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/FileTransferSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/MessageSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/OperationSetBasicInstantMessagingSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/OperationSetFileTransferSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/OperationSetPersistentPresenceSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ProtocolIconSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSH.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderServiceSSHImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/Resources.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHAccountID.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHActivator.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHContactInfo.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHFileTransferDaemon.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHReaderDaemon.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHStatusEnum.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/SSHUserInfo.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/ssh/ssh.provider.manifest.mf delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/FirstWizardPage.java delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/Resources.java delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistration.java delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/sshaccregwizz/sshaccregwizz.manifest.mf diff --git a/.classpath b/.classpath index ee1728a..25f00a5 100755 --- a/.classpath +++ b/.classpath @@ -48,8 +48,6 @@ - - diff --git a/build.xml b/build.xml index b80d638..b363fb5 100644 --- a/build.xml +++ b/build.xml @@ -1661,27 +1661,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - - - - - - diff --git a/lib/installer-exclude/jsch-0.1.36.jar b/lib/installer-exclude/jsch-0.1.36.jar deleted file mode 100644 index fde92b4..0000000 Binary files a/lib/installer-exclude/jsch-0.1.36.jar and /dev/null differ diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ContactGroupSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ContactGroupSSHImpl.java deleted file mode 100644 index 7de2e16..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ContactGroupSSHImpl.java +++ /dev/null @@ -1,580 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * A simple, straightforward implementation of a ssh ContactGroup. Since - * the SSH protocol is not a real one, we simply store all group details - * in class fields. You should know that when implementing a real protocol, - * the contact group implementation would rather encapsulate group objects from - * the protocol stack and group property values should be returned by - * consulting the encapsulated object. - * - * @author Shobhit Jindal - */ -public class ContactGroupSSHImpl - implements ContactGroup -{ - - /** - * The name of this SSH contact group. - */ - private String groupName = null; - - /** - * The list of this group's members. - */ - private Vector contacts = new Vector(); - - /** - * The list of sub groups belonging to this group. - */ - private Vector subGroups = new Vector(); - - /** - * The group that this group belongs to (or null if this is the root group). - */ - private ContactGroupSSHImpl parentGroup = null; - - /** - * Determines whether this group is really in the contact list or whether - * it is here only temporarily and will be gone next time we restart. - */ - private boolean isPersistent = true; - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceSSHImpl parentProvider = null; - - /** - * Determines whether this group has been resolved on the server. - * Unresolved groups are groups that were available on previous runs and - * that the meta contact list has stored. During all next runs, when - * bootstrapping, the meta contact list would create these groups as - * unresolved. Once a protocol provider implementation confirms that the - * groups are still on the server, it would issue an event indicating that - * the groups are now resolved. - */ - private boolean isResolved = true; - - /** - * An id uniquely identifying the group. For many protocols this could be - * the group name itself. - */ - private String uid = null; - private static final String UID_SUFFIX = ".uid"; - - /** - * Creates a ContactGroupSSHImpl with the specified name. - * - * @param groupName the name of the group. - * @param parentProvider the protocol provider that created this group. - */ - public ContactGroupSSHImpl( - String groupName, - ProtocolProviderServiceSSHImpl parentProvider) - { - this.groupName = groupName; - this.uid = groupName + UID_SUFFIX; - this.parentProvider = parentProvider; - } - - /** - * Determines whether the group may contain subgroups or not. - * - * @return always true in this implementation. - */ - public boolean canContainSubgroups() - { - return true; - } - - /** - * Returns the protocol provider that this group belongs to. - * @return a regerence to the ProtocolProviderService instance that this - * ContactGroup belongs to. - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Returns an Iterator over all contacts, member of this - * ContactGroup. - * - * @return a java.util.Iterator over all contacts inside this - * ContactGroup - */ - public Iterator contacts() - { - return contacts.iterator(); - } - - /** - * Adds the specified contact to this group. - * @param contactToAdd the ContactSSHImpl to add to this group. - */ - public void addContact(ContactSSH contactToAdd) - { - this.contacts.add(contactToAdd); - contactToAdd.setParentGroup(this); - } - - /** - * Returns the number of Contact members of this - * ContactGroup - * - * @return an int indicating the number of Contacts, members of - * this ContactGroup. - */ - public int countContacts() - { - return contacts.size(); - } - - /** - * Returns the number of subgroups contained by this - * ContactGroup. - * - * @return the number of subGroups currently added to this group. - */ - public int countSubgroups() - { - return subGroups.size(); - } - - /** - * Adds the specified contact group to the contained by this group. - * @param subgroup the ContactGroupSSHImpl to add as a subgroup to this - * group. - */ - public void addSubgroup(ContactGroupSSHImpl subgroup) - { - this.subGroups.add(subgroup); - subgroup.setParentGroup(this); - } - - /** - * Sets the group that is the new parent of this group - * @param parent ContactGroupSSHImpl - */ - void setParentGroup(ContactGroupSSHImpl parent) - { - this.parentGroup = parent; - } - - /** - * Returns the contact group that currently contains this group or null if - * this is the root contact group. - * @return the contact group that currently contains this group or null if - * this is the root contact group. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Removes the specified contact group from the this group's subgroups. - * @param subgroup the ContactGroupSSHImpl subgroup to remove. - */ - public void removeSubGroup(ContactGroupSSHImpl subgroup) - { - this.subGroups.remove(subgroup); - subgroup.setParentGroup(null); - } - - /** - * Returns the group that is parent of the specified sshGroup or null - * if no parent was found. - * @param sshGroup the group whose parent we're looking for. - * @return the ContactGroupSSHImpl instance that sshGroup - * belongs to or null if no parent was found. - */ - public ContactGroupSSHImpl findGroupParent( - ContactGroupSSHImpl sshGroup) - { - if ( subGroups.contains(sshGroup) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupSSHImpl subgroup - = (ContactGroupSSHImpl) subGroupsIter.next(); - - ContactGroupSSHImpl parent - = subgroup.findGroupParent(sshGroup); - - if(parent != null) - return parent; - } - return null; - } - - /** - * Returns the group that is parent of the specified sshContact or - * null if no parent was found. - * - * @param sshContact the contact whose parent we're looking for. - * @return the ContactGroupSSHImpl instance that sshContact - * belongs to or null if no parent was found. - */ - public ContactGroupSSHImpl findContactParent( - ContactSSHImpl sshContact) - { - if ( contacts.contains(sshContact) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupSSHImpl subgroup - = (ContactGroupSSHImpl) subGroupsIter.next(); - - ContactGroupSSHImpl parent - = subgroup.findContactParent(sshContact); - - if(parent != null) - return parent; - } - return null; - } - - - - /** - * Returns the Contact with the specified address or identifier. - * - * @param id the addres or identifier of the Contact we are - * looking for. - * @return the Contact with the specified id or address. - */ - public Contact getContact(String id) - { - Iterator contactsIter = contacts(); - while (contactsIter.hasNext()) - { - ContactSSHImpl contact = (ContactSSHImpl) contactsIter.next(); - if (contact.getAddress().equals(id)) - return contact; - - } - return null; - } - - /** - * Returns the subgroup with the specified index. - * - * @param index the index of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(int index) - { - return subGroups.get(index); - } - - /** - * Returns the subgroup with the specified name. - * - * @param groupName the name of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(String groupName) - { - Iterator groupsIter = subgroups(); - while (groupsIter.hasNext()) - { - ContactGroupSSHImpl contactGroup - = (ContactGroupSSHImpl) groupsIter.next(); - if (contactGroup.getGroupName().equals(groupName)) - return contactGroup; - - } - return null; - - } - - /** - * Returns the name of this group. - * - * @return a String containing the name of this group. - */ - public String getGroupName() - { - return this.groupName; - } - - /** - * Sets this group a new name. - * @param newGrpName a String containing the new name of this group. - */ - public void setGroupName(String newGrpName) - { - this.groupName = newGrpName; - } - - /** - * Returns an iterator over the sub groups that this - * ContactGroup contains. - * - * @return a java.util.Iterator over the ContactGroup children - * of this group (i.e. subgroups). - */ - public Iterator subgroups() - { - return subGroups.iterator(); - } - - /** - * Removes the specified contact from this group. - * @param contact the ContactSSHImpl to remove from this group - */ - public void removeContact(ContactSSHImpl contact) - { - this.contacts.remove(contact); - } - - /** - * Returns the contact with the specified id or null if no such contact - * exists. - * @param id the id of the contact we're looking for. - * @return ContactSSHImpl - */ - public ContactSSHImpl findContactByID(String id) - { - //first go through the contacts that are direct children. - Iterator contactsIter = contacts(); - - while(contactsIter.hasNext()) - { - ContactSSHImpl mContact = (ContactSSHImpl)contactsIter.next(); - - if( mContact.getAddress().equals(id) ) - return mContact; - } - - //if we didn't find it here, let's try in the subougroups - Iterator groupsIter = subgroups(); - - while( groupsIter.hasNext() ) - { - ContactGroupSSHImpl mGroup = (ContactGroupSSHImpl)groupsIter.next(); - - ContactSSHImpl mContact = mGroup.findContactByID(id); - - if (mContact != null) - return mContact; - } - - return null; - } - - /** - * Returns a String representation of this group and the contacts it - * contains (may turn out to be a relatively long string). - * @return a String representing this group and its child contacts. - */ - @Override - public String toString() - { - StringBuffer buff = new StringBuffer(getGroupName()); - buff.append(".subGroups=" + countSubgroups() + ":\n"); - - Iterator subGroups = subgroups(); - while (subGroups.hasNext()) - { - ContactGroup group = subGroups.next(); - buff.append(group.toString()); - if (subGroups.hasNext()) - buff.append("\n"); - } - - buff.append("\nChildContacts="+countContacts()+":["); - - Iterator contacts = contacts(); - while (contacts.hasNext()) - { - Contact contact = contacts.next(); - buff.append(contact.toString()); - if(contacts.hasNext()) - buff.append(", "); - } - return buff.append("]").toString(); - } - - /** - * Specifies whether or not this contact group is being stored by the - * server. - * Non persistent contact groups are common in the case of simple, - * non-persistent presence operation sets. They could however also be seen - * in persistent presence operation sets when for example we have received - * an event from someone not on our contact list and the contact that we - * associated with that user is placed in a non persistent group. Non - * persistent contact groups are volatile even when coming from a - * persistent presence op. set. They would only exist until the - * application is closed and will not be there next time it is loaded. - * - * @param isPersistent true if the contact group is to be persistent and - * false otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Makes the group resolved or unresolved. - * - * @param resolved true to make the group resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns a String that uniquely represnets the group inside - * the current protocol. The string MUST be persistent (it must not change - * across connections or runs of the application). In many cases (Jabber, - * ICQ) the string may match the name of the group as these protocols - * only allow a single level of contact groups and there is no danger of - * having the same name twice in the same contact list. Other protocols - * (no examples come to mind but that doesn't bother me ;) ) may be - * supporting mutilple levels of grooups so it might be possible for group - * A and group B to both contain groups named C. In such cases the - * implementation must find a way to return a unique identifier in this - * method and this UID should never change for a given group. - * - * @return a String representing this group in a unique and persistent - * way. - */ - public String getUID() - { - return uid; - } - - /** - * Ugly but tricky conversion method. - * @param uid the uid we'd like to get a name from - * @return the name of the group with the specified uid. - */ - static String createNameFromUID(String uid) - { - return uid.substring(0, uid.length() - (UID_SUFFIX.length())); - } - - /** - * Indicates whether some other object is "equal to" this one which in terms - * of contact groups translates to having the equal names and matching - * subgroups and child contacts. The resolved status of contactgroups and - * contacts is deliberately ignored so that groups and/or contacts would - * be assumed equal even if it differs. - *

    - * @param obj the reference object with which to compare. - * @return true if this contact group has the equal child - * contacts and subgroups to those of the obj argument. - */ - @Override - public boolean equals(Object obj) - { - if(obj == null - || !(obj instanceof ContactGroupSSHImpl)) - return false; - - ContactGroupSSHImpl sshGroup - = (ContactGroupSSHImpl)obj; - - if( ! sshGroup.getGroupName().equals(getGroupName()) - || ! sshGroup.getUID().equals(getUID()) - || sshGroup.countContacts() != countContacts() - || sshGroup.countSubgroups() != countSubgroups()) - return false; - - //traverse child contacts - Iterator theirContacts = sshGroup.contacts(); - - while(theirContacts.hasNext()) - { - Contact theirContact = theirContacts.next(); - Contact ourContact = getContact(theirContact.getAddress()); - - if(ourContact == null - || !ourContact.equals(theirContact)) - return false; - } - - //traverse subgroups - Iterator theirSubgroups = sshGroup.subgroups(); - - while(theirSubgroups.hasNext()) - { - ContactGroup theirSubgroup = theirSubgroups.next(); - ContactGroup ourSubgroup = getGroup(theirSubgroup.getGroupName()); - - if(ourSubgroup == null - || !ourSubgroup.equals(theirSubgroup)) - return false; - } - - return true; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSH.java b/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSH.java deleted file mode 100644 index a13414b..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSH.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; - -import net.java.sip.communicator.service.protocol.*; - -import com.jcraft.jsch.*; - -/** - * This interface represents a Contact of SSH Type - * As a SSH Session is specific to a contact, additional information needed - * to maintain its state with the remote server is present here - * - * @author Shobhit Jindal - */ -interface ContactSSH - extends Contact -{ - /** - * An event type indicating that the message being received is a standard - * conversation message sent by another contact. - */ - public static final int CONVERSATION_MESSAGE_RECEIVED = 1; - - /** - * An event type indicting that the message being received is a system - * message being sent by the server or a system administrator. - */ - public static final int SYSTEM_MESSAGE_RECEIVED = 2; - - //Following eight function declations to be moved to Contact - - /** - * This method is only called when the contact is added to a new - * ContactGroupSSHImpl by the - * ContactGroupSSHImpl itself. - * - * @param newParentGroup the ContactGroupSSHImpl that is now - * parent of this ContactSSHImpl - */ - void setParentGroup (ContactGroupSSHImpl newParentGroup); - - /** - * Sets sshPresenceStatus as the PresenceStatus that this - * contact is currently in. - * @param sshPresenceStatus the SSHPresenceStatus - * currently valid for this contact. - */ - public void setPresenceStatus (PresenceStatus sshPresenceStatus); - - /** - * Returns the persistent presence operation set that this contact belongs - * to. - * - * @return the OperationSetPersistentPresenceSSHImpl that - * this contact belongs to. - */ - public OperationSetPersistentPresence - getParentPresenceOperationSet (); - - /** - * Returns the BasicInstant Messaging operation set that this contact - * belongs to. - * - * @return the OperationSetBasicInstantMessagingSSHImpl that - * this contact belongs to. - */ - public OperationSetBasicInstantMessaging - getParentBasicInstantMessagingOperationSet (); - - /** - * Returns the File Transfer operation set that this contact belongs - * to. - * - * @return the OperationSetFileTransferSSHImpl that - * this contact belongs to. - */ - public OperationSetFileTransfer - getFileTransferOperationSet (); - - /** - * Return the type of message received from remote server - * - * @return messageType - */ - public int getMessageType (); - - /** - * Sets the type of message received from remote server - * - * @param messageType - */ - public void setMessageType (int messageType); - - /** - * Stores persistent data of the contact. - * - * @param persistentData of the contact - */ - public void setPersistentData (String persistentData); - - /** - * Makes the contact resolved or unresolved. - * - * @param resolved true to make the contact resolved; false to - * make it unresolved - */ - public void setResolved (boolean resolved); - - /** - * Specifies whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @param isPersistent true if the contact is persistent and false - * otherwise. - */ - public void setPersistent (boolean isPersistent); - - /** - * Returns true if a command has been sent whos reply was not received yet - * false otherwise - * - * @return commandSent - */ - public boolean isCommandSent (); - - /** - * Set the state of commandSent variable which determines whether a reply - * to a command sent is awaited - * - * @param commandSent - */ - public void setCommandSent (boolean commandSent); - - /** - * Initializes the reader and writers associated with shell of this contact - * - * @param shellInputStream The InputStream of stack - * @param shellOutputStream The OutputStream of stack - */ - void initializeShellIO (InputStream shellInputStream, - OutputStream shellOutputStream); - - /** - * Closes the readers and writer associated with shell of this contact - */ - void closeShellIO (); - - /** - * Determines whether a connection to a remote server is already underway - * - * @return connectionInProgress - */ - public boolean isConnectionInProgress (); - - /** - * Sets the status of connection attempt to remote server - * - * @param connectionInProgress - */ - public void setConnectionInProgress (boolean connectionInProgress); - -// /** -// * Sets the PS1 prompt of the current shell of Contact -// * This method is synchronized -// * -// * @param sshPrompt to be associated -// */ -// public void setShellPrompt(String sshPrompt); -// -// /** -// * Returns the PS1 prompt of the current shell of Contact -// * -// * @return sshPrompt -// */ -// public String getShellPrompt(); - - - /** - * Saves the details of contact in persistentData - */ - public void savePersistentDetails (); - - /* - * Returns the SSHContactInfo associated with this contact - * - * @return sshConfigurationForm - */ - public SSHContactInfo getSSHConfigurationForm (); - - /** - * Returns the JSch Stack identified associated with this contact - * - * @return jsch - */ - JSch getJSch (); - - /** - * Starts the timer and its task to periodically update the status of - * remote machine - */ - void startTimerTask (); - - /** - * Stops the timer and its task to stop updating the status of - * remote machine - */ - void stopTimerTask (); - - /** - * Sets the JSch Stack identified associated with this contact - * - * @param jsch to be associated - */ - void setJSch (JSch jsch); - - /** - * Returns the Username associated with this contact - * - * @return userName - */ - String getUserName (); - - /** - * Returns the Hostname associated with this contact - * - * @return hostName - */ - String getHostName (); - - /** - * Returns the Password associated with this contact - * - * @return password - */ - String getPassword (); - - /** - * Sets the Password associated with this contact - * - * @param password - */ - void setPassword (String password); - - /** - * Returns the SSH Session associated with this contact - * - * @return sshSession - */ - Session getSSHSession (); - - /** - * Sets the SSH Session associated with this contact - * - * @param sshSession the newly created SSH Session to be associated - */ - void setSSHSession (Session sshSession); - - /** - * Returns the SSH Shell Channel associated with this contact - * - * @return shellChannel - */ - Channel getShellChannel (); - - /** - * Sets the SSH Shell channel associated with this contact - * - * @param shellChannel to be associated with SSH Session of this contact - */ - void setShellChannel (Channel shellChannel); - - /** - * Sends a message a line to remote machine via the Shell Writer - * - * @param message to be sent - * @throws IOException if message failed to be sent - */ - public void sendLine (String message) - throws IOException; - -// /** -// * Reads a line from the remote machine via the Shell Reader -// * -// * @return message read -// */ -// public String getLine() -// throws IOException; - - /** - * Returns the Input Stream associated with SSH Channel of this contact - * - * @return shellInputStream associated with SSH Channel of this contact - */ - public InputStream getShellInputStream (); - -// /** -// * Sets the Input Stream associated with SSH Channel of this contact -// * -// * @param shellInputStream to be associated with SSH Channel of this -// * contact -// */ -// public void setShellInputStream(InputStream shellInputStream); - - /** - * Returns the Output Stream associated with SSH Channel of this contact - * - * @return shellOutputStream associated with SSH Channel of this contact - */ - public OutputStream getShellOutputStream (); - -// /** -// * Sets the Output Stream associated with SSH Channel of this contact -// * -// * @param shellOutputStream to be associated with SSH Channel of this -// * contact -// */ -// public void setShellOutputStream(OutputStream shellOutputStream); -// - /** - * Returns the BufferedReader associated with SSH Channel of this contact - * - * @return shellReader associated with SSH Channel of this contact - */ - public InputStreamReader getShellReader (); -// -// /** -// * Sets the BufferedReader associated with SSH Channel of this contact -// * -// * @param shellReader to be associated with SSH Channel of this contact -// */ -// public void setShellReader(BufferedReader shellReader); - - /** - * Returns the PrintWriter associated with SSH Channel of this contact - * - * @return shellWriter associated with SSH Channel of this contact - */ - public PrintWriter getShellWriter (); - -// /** -// * Sets the PrintWriter associated with SSH Channel of this contact -// * -// * @param shellWriter to be associated with SSH Channel of this contact -// */ -// public void setShellWriter(PrintWriter shellWriter); -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSHImpl.java deleted file mode 100644 index 15da209..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ContactSSHImpl.java +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.Base64; // disambiguation -import net.java.sip.communicator.util.Logger; - -import com.jcraft.jsch.*; -// disambiguation - -/** - * A Contact of SSH Type - * - * @author Shobhit Jindal - */ -public class ContactSSHImpl - extends AbstractContact - implements ContactSSH -{ - private static final Logger logger - = Logger.getLogger(ContactSSHImpl.class); - - /** - * This acts as a separator between details stored in persistent data - */ - private final String separator = - Resources.getString("impl.protocol.ssh.DETAILS_SEPARATOR"); - - /** - * The identifier for SSH Stack - * Java Secure Channel JSch - */ - private JSch jsch; - - /** - * Interface for user to provide details about machine - */ - private SSHContactInfo sshConfigurationForm; - - /** - * A Timer Daemon to update the status of this contact - */ - private Timer timer = new Timer(true); - - /** - * A Daemon to retrieve and fire messages received from remote machine - */ - private SSHReaderDaemon contactSSHReaderDaemon; - - /** - * The id of the contact. - */ - private String contactID = null; - - /** - * The persistentData of the contact. - */ - private String persistentData = null; - -// /** -// * This stores the prompt string of shell -// */ -// private String sshPrompt; - - /** - * The provider that created us. - */ - private ProtocolProviderServiceSSHImpl parentProvider = null; - - /** - * The identifier of the type of message received from server - */ - private int messageType; - - - - /** - * The identifier for SSH Session with the remote server - */ - private Session sshSession = null; - - /** - * The identifier for a sshShellChannel with the remote server is of type - * shell - for an interactive SSH Session with the remote machine - * - * Other types - * sftp - to tranfer files from/to the remote machine - * exec - X forwarding - * direct-tcpip - stream forwarding - */ - private Channel sshShellChannel = null; - - /** - * The identifier for the Shell Input Stream associated with SSH Sesion - */ - private InputStream shellInputStream = null; - - /** - * The identifier for the Shell Output Stream associated with SSH Sesion - */ - private OutputStream shellOutputStream = null; - - /** - * Higher wrapper for shellInputStream - */ - private InputStreamReader shellReader = null; - - /** - * Higher wrapper for shellOutputStream - */ - private PrintWriter shellWriter = null; - - /** - * The group that belong to. - */ - private ContactGroupSSHImpl parentGroup = null; - - /** - * The presence status of the contact. - */ - private PresenceStatus presenceStatus = SSHStatusEnum.NOT_AVAILABLE; - - /** - * Determines whether this contact is persistent, i.e. member of the contact - * list or whether it is here only temporarily. - */ - private boolean isPersistent = false; - - /** - * Determines whether the contact has been resolved (i.e. we have a - * confirmation that it is still on the server contact list). - */ - private boolean isResolved = true; - - /** - * Determines whether an connection attempt to remote server is already - * underway - */ - private boolean isConnectionInProgress = false; - - /** - * Determines whether the message received from remote machine is as a - * result of command sent to it - */ - private boolean commandSent = false; - - /** - * A lock to synchronize the access of commandSent boolean object - * with the reader thread. - */ - private final Object lock = new Object(); - - /** - * Creates an instance of a meta contact with the specified string used - * as a name and identifier. - * - * @param id the identifier of this contact (also used as a name). - * @param parentProvider the provider that created us. - */ - public ContactSSHImpl( - String id, - ProtocolProviderServiceSSHImpl parentProvider) - { - this.contactID = id; - this.parentProvider = parentProvider; - - this.sshConfigurationForm = - new SSHContactInfo(this); - - this.savePersistentDetails(); - } - - /** - * Initializes the reader and writers associated with shell of this contact - * - * @param shellInputStream The InputStream of stack - * @param shellOutputStream The OutputStream of stack - */ - public void initializeShellIO( - InputStream shellInputStream, - OutputStream shellOutputStream) - { - this.shellInputStream = shellInputStream; - this.shellOutputStream = shellOutputStream; - shellReader = new InputStreamReader(shellInputStream); - shellWriter = new PrintWriter(shellOutputStream); - - contactSSHReaderDaemon = new SSHReaderDaemon(this); - contactSSHReaderDaemon.setDaemon(true); - contactSSHReaderDaemon.isActive(true); - contactSSHReaderDaemon.start(); - } - - /** - * Closes the readers and writer associated with shell of this contact - */ - public void closeShellIO() - { - try - { - shellReader.close(); - shellInputStream.close(); - } - catch(IOException ex) - {} - - try - { - shellWriter.close(); - shellOutputStream.close(); - } - catch(IOException ex) - {} - - shellInputStream = null; - - shellReader = null; - - shellOutputStream = null; - - shellWriter = null; - - try - { - sshShellChannel.disconnect(); - } - catch(Exception e) - {} - - // Removing the reference to current channel - // a new shell channel will be created for the next message - sshShellChannel = null; - - // remove the reference of session if it were also disconnected - // like in the case of exit command - if(!sshSession.isConnected()) - { - sshSession = null; - jsch = null; - } - - ((OperationSetPersistentPresenceSSHImpl) - getParentPresenceOperationSet()). - changeContactPresenceStatus(this, SSHStatusEnum.ONLINE); - } - - /** - * Sends a message a line to remote machine via the Shell Writer - * - * @param message to be sent - */ - public void sendLine(String message) - throws IOException - { -// logger.debug("SSH TO: " + this.contactID + ": " + message); - shellWriter.println(message); - shellWriter.flush(); - } - - /** - * Reads a line from the remote machine via the Shell Reader - * - * @return message read - */ -// public String getLine() -// throws IOException -// { -// String line = shellReader.readLine(); -//// logger.debug("SSH FROM: " + this.contactID + ": " + line); -// -// // null is never returned normally, the reading attempt returs a -// // string -// // or blocks until one line is available -// if(line == null) -// { -// sshShellChannel.disconnect(); -// sshShellChannel = null; -// sshSession = null; -// throw(new IOException("Unexpected Reply from remote Server")); -// } -// return line; -// } - - /** - * Starts the timer and its task to periodically update the status of - * remote machine - */ - public void startTimerTask() - { - timer.scheduleAtFixedRate(new ContactTimerSSHImpl(this), - 2000, sshConfigurationForm.getUpdateInterval()*1000); - } - - /** - * Stops the timer and its task to stop updating the status of - * remote machine - */ - public void stopTimerTask() - { - timer.cancel(); - } - - - /** - * Saves the details of contact in persistentData seperated by - * separator - * Passowrd is saved unsecurely using Base64 encoding - */ - public void savePersistentDetails() - { - persistentData = - this.sshConfigurationForm.getHostName() + - separator + - this.sshConfigurationForm.getUserName() + - separator + - new String(Base64.encode(this.sshConfigurationForm.getPassword() - .getBytes())) + - separator + sshConfigurationForm.getPort() + - separator + - sshConfigurationForm.getTerminalType() + - separator + - sshConfigurationForm.getUpdateInterval(); - } - - /** - * Stores persistent data in fields of the contact seperated by - * separator. - * - * @param persistentData of the contact - */ - public void setPersistentData(String persistentData) - { - try - { - this.persistentData = persistentData; - int firstCommaIndex = this.persistentData.indexOf(separator); - int secondCommaIndex = this.persistentData.indexOf(separator, - firstCommaIndex +1); - int thirdCommaIndex = this.persistentData.indexOf(separator, - secondCommaIndex +1); - int fourthCommaIndex = this.persistentData.indexOf(separator, - thirdCommaIndex +1); - int fifthCommaIndex = this.persistentData.indexOf(separator, - fourthCommaIndex +1); - - if (logger.isDebugEnabled()) - logger.debug("Commas: " + firstCommaIndex + " " + secondCommaIndex + " " - + thirdCommaIndex + " " +fourthCommaIndex + " " - +fifthCommaIndex); - - this.sshConfigurationForm.setHostNameField( - this.persistentData.substring(0,firstCommaIndex)); - - this.sshConfigurationForm.setUserNameField( - this.persistentData.substring(firstCommaIndex+1, - secondCommaIndex)); - - if( (thirdCommaIndex - secondCommaIndex) > 1) - { - if(this.persistentData.substring(secondCommaIndex+1).length()>0) - this.sshConfigurationForm.setPasswordField( - new String(Base64.decode(this.persistentData - .substring(secondCommaIndex+1, thirdCommaIndex)))); - } - - - this.sshConfigurationForm.setPort( - this.persistentData.substring(thirdCommaIndex + 1, - fourthCommaIndex)); - - this.sshConfigurationForm.setTerminalType( - this.persistentData.substring(fourthCommaIndex + 1, - fifthCommaIndex)); - - this.sshConfigurationForm.setUpdateInterval( - Integer.parseInt(this.persistentData.substring(fifthCommaIndex+1))); - } - catch(Exception ex) - { - logger.error("Error setting persistent data!", ex); - } - } - - /** - * Determines whether a connection to a remote server is already underway - * - * @return isConnectionInProgress - */ - public boolean isConnectionInProgress() - { - return this.isConnectionInProgress; - } - - /** - * Sets the status of connection attempt to remote server - * This method is synchronized - * - * @param isConnectionInProgress - */ - public synchronized void setConnectionInProgress( - boolean isConnectionInProgress) - { - this.isConnectionInProgress = isConnectionInProgress; - } - - /** - * Returns the SSHContactInfo associated with this contact - * - * @return sshConfigurationForm - */ - public SSHContactInfo getSSHConfigurationForm() - { - return this.sshConfigurationForm; - } - - /** - * Returns the JSch Stack identified associated with this contact - * - * @return jsch - */ - public JSch getJSch() - { - return this.jsch; - } - - /** - * Sets the JSch Stack identified associated with this contact - * - * @param jsch to be associated - */ - public void setJSch(JSch jsch) - { - this.jsch = jsch; - } - - /** - * This method is only called when the contact is added to a new - * ContactGroupSSHImpl by the - * ContactGroupSSHImpl itself. - * - * @param newParentGroup the ContactGroupSSHImpl that is now - * parent of this ContactSSHImpl - */ - public void setParentGroup(ContactGroupSSHImpl newParentGroup) - { - this.parentGroup = newParentGroup; - } - - /** - * Returns the Hostname associated with this contact - * - * @return hostName - */ - public String getHostName() - { - return sshConfigurationForm.getHostName(); - } - - /** - * Returns a String that can be used for identifying the contact. - * - * @return a String id representing and uniquely identifying the contact. - */ - public String getAddress() - { - return contactID; - } - - /** - * Returns a String that could be used by any user interacting modules - * for referring to this contact. - * - * @return a String that can be used for referring to this contact when - * interacting with the user. - */ - public String getDisplayName() - { - return contactID; - } - - /** - * Returns a byte array containing an image (most often a photo or an - * avatar) that the contact uses as a representation. - * - * @return byte[] an image representing the contact. - */ - public byte[] getImage() - { - return null; - } - - /** - * Returns true if a command has been sent whos reply was not received yet - * false otherwise - * - * @return commandSent - */ - public boolean isCommandSent() - { - return this.commandSent; - } - - /** - * Set the state of commandSent variable which determines whether a reply - * to a command sent is awaited - */ - public void setCommandSent(boolean commandSent) - { - synchronized(lock) - { - this.commandSent = commandSent; - } - } - - /** - * Return the type of message received from remote server - * - * @return messageType - */ - public int getMessageType() - { - return this.messageType; - } - - /** - * Sets the type of message received from remote server - * - * @param messageType - */ - public void setMessageType(int messageType) - { - this.messageType = messageType; - } - - /** - * Returns the status of the contact. - * - * @return presenceStatus - */ - public PresenceStatus getPresenceStatus() - { - return this.presenceStatus; - } - - /** - * Sets sshPresenceStatus as the PresenceStatus that this - * contact is currently in. - * @param sshPresenceStatus the SSHPresenceStatus - * currently valid for this contact. - */ - public void setPresenceStatus(PresenceStatus sshPresenceStatus) - { - this.presenceStatus = sshPresenceStatus; - } - - /** - * Returns a reference to the protocol provider that created the contact. - * - * @return a refererence to an instance of the ProtocolProviderService - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Determines whether or not this contact represents our own identity. - * - * @return true - */ - public boolean isLocal() - { - return true; - } - - /** - * Returns the group that contains this contact. - * @return a reference to the ContactGroupSSHImpl that - * contains this contact. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Returns a string representation of this contact, containing most of its - * representative details. - * - * @return a string representation of this contact. - */ - @Override - public String toString() - { - StringBuffer buff - = new StringBuffer("ContactSSHImpl[ DisplayName=") - .append(getDisplayName()).append("]"); - - return buff.toString(); - } - - /** - * Determines whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @return true if the contact is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Specifies whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @param isPersistent true if the contact is persistent and false - * otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - - /** - * Returns persistent data of the contact. - * - * @return persistentData of the contact - */ - public String getPersistentData() - { - return persistentData; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Makes the contact resolved or unresolved. - * - * @param resolved true to make the contact resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns the persistent presence operation set that this contact belongs - * to. - * - * @return the OperationSetPersistentPresenceSSHImpl that - * this contact belongs to. - */ - public OperationSetPersistentPresence - getParentPresenceOperationSet() - { - return - parentProvider - .getOperationSet(OperationSetPersistentPresence.class); - } - - /** - * Returns the BasicInstant Messaging operation set that this contact - * belongs to. - * - * @return the OperationSetBasicInstantMessagingSSHImpl that - * this contact belongs to. - */ - public OperationSetBasicInstantMessaging - getParentBasicInstantMessagingOperationSet() - { - return - parentProvider - .getOperationSet(OperationSetBasicInstantMessaging.class); - } - - /** - * Returns the File Transfer operation set that this contact belongs - * to. - * - * @return the OperationSetFileTransferSSHImpl that - * this contact belongs to. - */ - public OperationSetFileTransfer - getFileTransferOperationSet() - { - return parentProvider.getOperationSet(OperationSetFileTransfer.class); - } - - - /** - * Returns the SSH Session associated with this contact - * - * @return sshSession - */ - public Session getSSHSession() - { - return this.sshSession; - } - - /** - * Sets the SSH Session associated with this contact - * - * @param sshSession the newly created SSH Session to be associated - */ - public void setSSHSession(Session sshSession) - { - this.sshSession = sshSession; - } - - /** - * Returns the SSH Shell Channel associated with this contact - * - * @return sshShellChannel - */ - public Channel getShellChannel() - { - return this.sshShellChannel; - } - - /** - * Sets the SSH Shell channel associated with this contact - * - * @param sshShellChannel to be associated with SSH Session of this contact - */ - public void setShellChannel(Channel sshShellChannel) - { - this.sshShellChannel = sshShellChannel; - } - - /** - * Returns the Input Stream associated with SSH Channel of this contact - * - * @return shellInputStream associated with SSH Channel of this contact - */ - public InputStream getShellInputStream() - { - return this.shellInputStream; - } - -// /** -// * Sets the Input Stream associated with SSH Channel of this contact -// * -// * @param shellInputStream to be associated with SSH Channel of -// * this contact -// */ -// public void setShellInputStream(InputStream shellInputStream) -// { -// this.shellInputStream = shellInputStream; -// } - - /** - * Returns the Output Stream associated with SSH Channel of this contact - * - * @return shellOutputStream associated with SSH Channel of this contact - */ - public OutputStream getShellOutputStream() - { - return this.shellOutputStream; - } - -// /** -// * Sets the Output Stream associated with SSH Channel of this contact -// * -// * @param shellOutputStream to be associated with SSH Channel of this contact -// */ -// public void setShellOutputStream(OutputStream shellOutputStream) -// { -// this.shellOutputStream = shellOutputStream; -// } - - /** - * Returns the BufferedReader associated with SSH Channel of this contact - * - * @return shellReader associated with SSH Channel of this contact - */ - public InputStreamReader getShellReader() - { - return this.shellReader; - } - -// /** -// * Sets the BufferedReader associated with SSH Channel of this contact -// * -// * @param shellReader to be associated with SSH Channel of this contact -// */ -// public void setShellReader(BufferedReader shellReader) -// { -// this.shellReader = shellReader; -// } - - /** - * Returns the PrintWriter associated with SSH Channel of this contact - * - * @return shellWriter associated with SSH Channel of this contact - */ - public PrintWriter getShellWriter() - { - return this.shellWriter; - } - -// /** -// * Sets the PrintWriter associated with SSH Channel of this contact -// * -// * @param shellWriter to be associated with SSH Channel of this contact -// */ -// public void setShellWriter(PrintWriter shellWriter) -// { -// this.shellWriter = shellWriter; -// } - - /** - * Returns the userName associated with SSH Channel of this contact - * - * @return userName associated with SSH Channel of this contact - */ - public String getUserName() - { - return sshConfigurationForm.getUserName(); - } - - /** - * Returns the password associated with SSH Channel of this contact - * - * @return password associated with SSH Channel of this contact - */ - public String getPassword() - { - return sshConfigurationForm.getPassword(); - } - - /** - * Sets the Password associated with this contact - * - * @param password - */ - public void setPassword(String password) - { - this.sshConfigurationForm.setPasswordField(password); - savePersistentDetails(); - } - -// /** -// * Sets the PS1 prompt of the current shell of Contact -// * -// * @param sshPrompt to be associated -// */ -// public void setShellPrompt(String sshPrompt) -// { -// this.sshPrompt = sshPrompt; -// } -// -// /** -// * Returns the PS1 prompt of the current shell of Contact -// * -// * @return sshPrompt -// */ -// public String getShellPrompt() -// { -// return this.sshPrompt; -// } - - /** - * Return the current status message of this contact. - * - * @return the current status message - */ - public String getStatusMessage() - { - return presenceStatus.getStatusName(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ContactTimerSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ContactTimerSSHImpl.java deleted file mode 100644 index 4e3664d..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ContactTimerSSHImpl.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.util.*; - -/** - * Timer Task to update the reachability status of SSH Contact in contact list. - * (Reachability of remote machine from user's machine) - * The timer is started at either of the two places - * - A new contact - OperationSetPersistentPresenceSSHImpl - * .createUnresolvedContact - * - Existing Contact - OperationSetPersistentPresenceSSHImpl.subscribe - * - * @author Shobhit Jindal - */ -public class ContactTimerSSHImpl - extends TimerTask -{ - private static final Logger logger - = Logger.getLogger(OperationSetFileTransferSSHImpl.class); - - /** - * The contact ID of the remote machine - */ - private ContactSSH sshContact; - - /** - * PersistentPresence Identifer assoiciated with SSH Contact - */ - private OperationSetPersistentPresenceSSHImpl persistentPresence; - - /** - * The method which is called at regular intervals to update the status - * of remote machines - * - * Presently only ONLINE and OFFILINE status are checked - */ - @Override - public void run() - { - try - { - InetAddress remoteMachine = InetAddress.getByName( - sshContact.getSSHConfigurationForm().getHostName()); - - //check if machine is reachable - if(remoteMachine.isReachable( - sshContact.getSSHConfigurationForm().getUpdateInterval())) - { - if (sshContact.getPresenceStatus().equals(SSHStatusEnum.OFFLINE) - || sshContact.getPresenceStatus().equals(SSHStatusEnum - .NOT_AVAILABLE)) - { - // change status to online - persistentPresence.changeContactPresenceStatus( - sshContact, SSHStatusEnum.ONLINE); - - if (logger.isDebugEnabled()) - logger.debug("SSH Host " + sshContact - .getSSHConfigurationForm().getHostName() + ": Online"); - } - - } - else throw new IOException(); - - } - catch (IOException ex) - { - if (sshContact.getPresenceStatus().equals(SSHStatusEnum.ONLINE) - || sshContact.getPresenceStatus().equals( - SSHStatusEnum.NOT_AVAILABLE)) - { - persistentPresence.changeContactPresenceStatus( - sshContact, SSHStatusEnum.OFFLINE); - - if (logger.isDebugEnabled()) - logger.debug("SSH Host " + sshContact.getSSHConfigurationForm() - .getHostName() + ": Offline"); - } - } - } - /** - * Creates a new instance of ContactTimerSSHImpl - * - * @param sshContact the Contact - */ - public ContactTimerSSHImpl(ContactSSH sshContact) - { - super(); - this.sshContact = sshContact; - this.persistentPresence = (OperationSetPersistentPresenceSSHImpl) - sshContact.getParentPresenceOperationSet(); - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/FileTransferSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/FileTransferSSHImpl.java deleted file mode 100644 index 1e95032..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/FileTransferSSHImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * SSH implementation of the AbstractFileTransfer. - * - * @author Yana Stamcheva - */ -public class FileTransferSSHImpl - extends AbstractFileTransfer -{ - private final SSHFileTransferDaemon fileTransfer; - - private final Date initialDate; - - /** - * Creates an SSH implementation of the file transfer interface. - * - * @param fileTransfer the SSH file transfer - * @param date the initial date of the transfer - */ - public FileTransferSSHImpl( SSHFileTransferDaemon fileTransfer, - Date date) - { - this.fileTransfer = fileTransfer; - this.initialDate = date; - } - - /** - * Cancels this file transfer. When this method is called transfer should - * be interrupted. - */ - @Override - public void cancel() - { - // TODO: Implement cancel() for SSH file transfer. - } - - /** - * Returns the number of bytes already transfered through this file transfer. - * - * @return the number of bytes already transfered through this file transfer - */ - @Override - public long getTransferedBytes() - { - // TODO: Implement getTransferedBytes() for SSH file transfer. - return 0; - } - - public int getDirection() - { - return IN; - } - - public File getLocalFile() - { - return null; - } - - public Contact getContact() - { - return null; - } - - public String getID() - { - return null; - } - - public Date getInitialDate() - { - return initialDate; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/MessageSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/MessageSSHImpl.java deleted file mode 100644 index a8324f7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/MessageSSHImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Very simple message implementation for the SSH protocol. - * - * @author Shobhit Jindal - * @author Lubomir Marinov - */ -public class MessageSSHImpl - extends AbstractMessage -{ - - /** - * The content type of the message. - */ - public static String contentType = "text/plain"; - - /** - * Creates a message instance according to the specified parameters. - * - * @param content the message body - * @param contentType message content type or null for text/plain - * @param contentEncoding message encoding or null for UTF8 - * @param subject the subject of the message or null for no subject. - */ - public MessageSSHImpl(String content, String contentType, - String contentEncoding, String subject) - { - super(content, null, contentEncoding, subject); - - MessageSSHImpl.contentType = contentType; - } - - /** - * Returns the type of the content of this message. - * - * @return the type of the content of this message. - */ - @Override - public String getContentType() - { - return contentType; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetBasicInstantMessagingSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetBasicInstantMessagingSSHImpl.java deleted file mode 100644 index 9073ad5..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetBasicInstantMessagingSSHImpl.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; - -/** - * Instant messaging functionality for the SSH protocol. - * - * @author Shobhit Jindal - */ -public class OperationSetBasicInstantMessagingSSHImpl - extends AbstractOperationSetBasicInstantMessaging -{ - - /** - * The currently valid persistent presence operation set.. - */ - private OperationSetPersistentPresenceSSHImpl opSetPersPresence = null; - - /** - * The currently valid file transfer operation set - */ - private OperationSetFileTransferSSHImpl fileTransfer; - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceSSHImpl parentProvider = null; - - /** - * Creates an instance of this operation set keeping a reference to the - * parent protocol provider and presence operation set. - * - * @param provider The provider instance that creates us. - */ - public OperationSetBasicInstantMessagingSSHImpl( - ProtocolProviderServiceSSHImpl provider) - { - this.parentProvider = provider; - - this.opSetPersPresence - = (OperationSetPersistentPresenceSSHImpl) - provider - .getOperationSet(OperationSetPersistentPresence.class); - } - - @Override - public Message createMessage(String content, String contentType, - String encoding, String subject) - { - return new MessageSSHImpl(content, contentType, encoding, subject); - } - - /** - * Sends the message to the destination indicated by the - * to contact. An attempt is made to re-establish the shell - * connection if the current one is invalid. - * The reply from server is sent by a seperate reader thread - * - * @param to the Contact to send message to - * @param message the Message to send. - * @throws IllegalStateException if the underlying ICQ stack is not - * registered and initialized. - * @throws IllegalArgumentException if to is not an instance - * belonging to the underlying implementation. - */ - public void sendInstantMessage( - Contact to, - Message message) - throws IllegalStateException, - IllegalArgumentException - { - if( !(to instanceof ContactSSHImpl) ) - throw new IllegalArgumentException( - "The specified contact is not a SSH contact." - + to); - - ContactSSH sshContact = (ContactSSH)to; - - // making sure no messages are sent and no new threads are triggered, - // until a thread trying to connect to remote server returns - if(sshContact.isConnectionInProgress()) - { - deliverMessage( - createMessage("A connection attempt is in progress"), - (ContactSSHImpl)to); - return; - } - - if( !parentProvider.isShellConnected(sshContact) ) - { - - try - { - /** - * creating a new SSH session / shell channel - * - first message - * - session is timed out - * - network problems - */ - parentProvider.connectShell(sshContact, message); - - //the first message is ignored - return; - } - catch (Exception ex) - { - throw new IllegalStateException(ex.getMessage()); - } - } - - if(wrappedMessage(message.getContent(), sshContact)) - { - fireMessageDelivered(message, to); - return; - } - - try - { - sshContact.sendLine(message.getContent()); - sshContact.setCommandSent(true); - } - catch (IOException ex) - { - // Closing IO Streams - sshContact.closeShellIO(); - - throw new IllegalStateException(ex.getMessage()); - } - - fireMessageDelivered(message, to); - } - - /** - * Check the message for wrapped Commands - * All commands begin with / - * - * @param message from user - * @param sshContact of the remote machine - * - * @return true if the message had commands, false otherwise - */ - private boolean wrappedMessage( - String message, - ContactSSH sshContact) - { - if(message.startsWith("/upload")) - { - int firstSpace = message.indexOf(' '); - - try - { - sshContact.getFileTransferOperationSet().sendFile( - sshContact, - null, - message.substring(message.indexOf(' ', firstSpace+1) + 1), - message.substring( - firstSpace+1, - message.indexOf(' ', firstSpace+1))); - } - catch (Exception e) - { - e.printStackTrace(); - } - - return true; - } - else if(message.startsWith("/download")) - { - int firstSpace = message.indexOf(' '); - - try - { - sshContact.getFileTransferOperationSet().sendFile( - null, - sshContact, - message.substring(firstSpace+1, message.indexOf(' ', - firstSpace+1)), - message.substring(message.indexOf(' ', firstSpace+1) + 1)); - } - catch(Exception e) - { - e.printStackTrace(); - } - return true; - } - return false; - } - - /** - * In case the to Contact corresponds to another ssh - * protocol provider registered with SIP Communicator, we deliver - * the message to them, in case the to Contact represents us, we - * fire a MessageReceivedEvent, and if to is simply - * a contact in our contact list, then we simply echo the message. - * - * @param message the Message the message to deliver. - * @param to the Contact that we should deliver the message to. - */ - void deliverMessage( - Message message, - ContactSSH to) - { - String userID = to.getAddress(); - - //if the user id is owr own id, then this message is being routed to us - //from another instance of the ssh provider. - if (userID.equals(this.parentProvider.getAccountID().getUserID())) - { - //check who is the provider sending the message - String sourceUserID - = to.getProtocolProvider().getAccountID().getUserID(); - - //check whether they are in our contact list - Contact from = opSetPersPresence.findContactByID(sourceUserID); - - //and if not - add them there as volatile. - if(from == null) - { - from = opSetPersPresence.createVolatileContact(sourceUserID); - } - - //and now fire the message received event. - fireMessageReceived(message, from); - } - else - { - //if userID is not our own, try an check whether another provider - //has that id and if yes - deliver the message to them. - ProtocolProviderServiceSSHImpl sshProvider - = this.opSetPersPresence.findProviderForSSHUserID(userID); - if(sshProvider != null) - { - OperationSetBasicInstantMessagingSSHImpl opSetIM - = (OperationSetBasicInstantMessagingSSHImpl) - sshProvider - .getOperationSet( - OperationSetBasicInstantMessaging.class); - opSetIM.deliverMessage(message, to); - } - else - { - //if we got here then "to" is simply someone in our contact - //list so let's just echo the message. - fireMessageReceived(message, to); - } - } - } - - /** - * Notifies all registered message listeners that a message has been - * received. - * - * @param message the Message that has been received. - * @param from the Contact that message was received from. - */ - @Override - protected void fireMessageReceived(Message message, Contact from) - { - fireMessageEvent( - new MessageReceivedEvent( - message, - from, - new Date(), - ((ContactSSH) from).getMessageType())); - } - - /** - * Determines whether the SSH protocol provider supports - * sending and receiving offline messages. - * - * @return false - */ - public boolean isOfflineMessagingSupported() - { - return false; - } - - /** - * Determines wheter the protocol supports the supplied content type - * - * @param contentType the type we want to check - * @return true if the protocol supports it and - * false otherwise. - */ - public boolean isContentTypeSupported(String contentType) - { - return MessageSSHImpl.contentType.equals(contentType); - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetFileTransferSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetFileTransferSSHImpl.java deleted file mode 100644 index 61d8160..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetFileTransferSSHImpl.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -/** - * This class provides operations to upload/download files to remote machines - * - * @author Shobhit Jindal - */ -public class OperationSetFileTransferSSHImpl - implements OperationSetFileTransfer -{ - private static final Logger logger - = Logger.getLogger(OperationSetFileTransferSSHImpl.class); - - /** - * Currently registered message listeners. - */ - private Vector fileTransferListeners - = new Vector(); - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceSSHImpl parentProvider = null; - - - /** - * Creates a new instance of OperationSetFileTransferSSHImpl - * - * @param parentProvider the parent protocol provider service - */ - public OperationSetFileTransferSSHImpl( - ProtocolProviderServiceSSHImpl parentProvider) - { - this.parentProvider = parentProvider; - } - - /** - * Registers a FileTransferListener with this operation set so that it gets - * notifications of start, complete, failure of file transfers - * - * @param listener the FileListener to register. - */ - public void addFileTransferListener( - FileTransferListener listener) - { - synchronized (fileTransferListeners) - { - if(!fileTransferListeners.contains(listener)) - fileTransferListeners.add(listener); - } - } - - public void removeFileTransferListener( - FileTransferListener listener) - { - synchronized (fileTransferListeners) - { - fileTransferListeners.remove(listener); - } - } - - /** - * Sends a file transfer request to the given toContact. - * @param toContact the contact that should receive the file - * @param file the file to send - */ - public FileTransfer sendFile( Contact toContact, - File file) - { - return this.sendFile( toContact, - null, - file.getAbsolutePath(), - file.getAbsolutePath()); - } - - /** - * The file transfer method to/from the remote machine - * either toContact is null(we are downloading file from remote machine - * or fromContact is null(we are uploading file to remote machine - * - * @param toContact - the file recipient - * @param fromContact - the file sender - * @param remotePath - the identifier for the remote file - * @param localPath - the identifier for the local file - */ - public FileTransfer sendFile( - Contact toContact, - Contact fromContact, - String remotePath, - String localPath) - { - if(toContact == null) - { - SSHFileTransferDaemon fileTransferDaemon - = new SSHFileTransferDaemon( - (ContactSSH)fromContact, - parentProvider); - - if(localPath.endsWith(System.getProperty("file.separator"))) - localPath += remotePath.substring(remotePath.lastIndexOf( - System.getProperty("file.separator")) + 1); - - fileTransferDaemon.downloadFile( - remotePath, - localPath); - - return new FileTransferSSHImpl(fileTransferDaemon, new Date()); - } - else if(fromContact == null) - { - SSHFileTransferDaemon fileTransferDaemon - = new SSHFileTransferDaemon( - (ContactSSH) toContact, - parentProvider); - - fileTransferDaemon.uploadFile( - remotePath, - localPath); - - return new FileTransferSSHImpl(fileTransferDaemon, new Date()); - } - - // code should not reach here - // assert false; - logger.error("we should not be here !"); - return null; - } - - /** - * Returns the maximum file length supported by the protocol in bytes. - * @return the file length that is supported. - */ - public long getMaximumFileLength() - { - return 2048*1024*1024; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetPersistentPresenceSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetPersistentPresenceSSHImpl.java deleted file mode 100644 index d4c63bd..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/OperationSetPersistentPresenceSSHImpl.java +++ /dev/null @@ -1,980 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * A SSH implementation of a persistent presence operation set. In order - * to simulate server persistence, this operation set would simply accept all - * unresolved contacts and resolve them immediately. A real world protocol - * implementation would save it on a server using methods provided by the - * protocol stack. - * - * @author Shobhit Jindal - */ -public class OperationSetPersistentPresenceSSHImpl - extends AbstractOperationSetPersistentPresence -{ - private static final Logger logger = - Logger.getLogger(OperationSetPersistentPresenceSSHImpl.class); - - /** - * The root of the ssh contact list. - */ - private ContactGroupSSHImpl contactListRoot = null; - - /** - * The currently active status message. - */ - private String statusMessage = "Online"; - - /** - * Our default presence status. - */ - private PresenceStatus presenceStatus = SSHStatusEnum.ONLINE; - - /** - * Creates an instance of this operation set keeping a reference to the - * specified parent provider. - * @param provider the ProtocolProviderServiceSSHImpl instance that - * created us. - */ - public OperationSetPersistentPresenceSSHImpl( - ProtocolProviderServiceSSHImpl provider) - { - super(provider); - - contactListRoot = new ContactGroupSSHImpl("RootGroup", provider); - - //add our unregistration listener - parentProvider.addRegistrationStateChangeListener( - new UnregistrationListener()); - } - - /** - * This function changes the status of contact as well as that of the - * provider - * - * @param sshContact the contact of the remote machine - * @param newStatus new status of the contact - */ - public void changeContactPresenceStatus( - ContactSSH sshContact, - PresenceStatus newStatus) - { - PresenceStatus oldStatus = sshContact.getPresenceStatus(); - sshContact.setPresenceStatus(newStatus); - fireContactPresenceStatusChangeEvent( - sshContact - , sshContact.getParentContactGroup() - , oldStatus); - fireProviderStatusChangeEvent(oldStatus); - } - - /** - * Creates a group with the specified name and parent in the server - * stored contact list. - * - * @param parent the group where the new group should be created - * @param groupName the name of the new group to create. - */ - public void createServerStoredContactGroup( - ContactGroup parent, - String groupName) - { - ContactGroupSSHImpl newGroup - = new ContactGroupSSHImpl(groupName, parentProvider); - - ((ContactGroupSSHImpl)parent).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - /** - * A SSH Provider method to use for fast filling of a contact list. - * - * @param contactGroup the group to add - */ - public void addSSHGroup(ContactGroupSSHImpl contactGroup) - { - contactListRoot.addSubgroup(contactGroup); - } - - /** - * A SSH Provider method to use for fast filling of a contact list. - * This method would add both the group and fire an event. - * - * @param parent the group where contactGroup should be added. - * @param contactGroup the group to add - */ - public void addSSHGroupAndFireEvent( - ContactGroupSSHImpl parent, - ContactGroupSSHImpl contactGroup) - { - parent.addSubgroup(contactGroup); - - this.fireServerStoredGroupEvent( - contactGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - - /** - * Returns a reference to the contact with the specified ID in case we - * have a subscription for it and null otherwise/ - * - * @param contactID a String identifier of the contact which we're - * seeking a reference of. - * @return a reference to the Contact with the specified - * contactID or null if we don't have a subscription for the - * that identifier. - */ - public Contact findContactByID(String contactID) - { - return contactListRoot.findContactByID(contactID); - } - - /** - * Sets the specified status message. - * @param statusMessage a String containing the new status message. - */ - public void setStatusMessage(String statusMessage) - { - this.statusMessage = statusMessage; - } - - /** - * Returns the status message that was last set through - * setCurrentStatusMessage. - * - * @return the last status message that we have requested and the aim - * server has confirmed. - */ - public String getCurrentStatusMessage() - { - return statusMessage; - } - - /** - * Returns the protocol specific contact instance representing the local - * user. - * - * @return the Contact (address, phone number, or uin) that the Provider - * implementation is communicating on behalf of. - */ - public Contact getLocalContact() - { - return null; - } - - /** - * Returns a PresenceStatus instance representing the state this provider - * is currently in. - * - * @return the PresenceStatus last published by this provider. - */ - public PresenceStatus getPresenceStatus() - { - return presenceStatus; - } - - /** - * Returns the root group of the server stored contact list. - * - * @return the root ContactGroup for the ContactList stored by this - * service. - */ - public ContactGroup getServerStoredContactListRoot() - { - return contactListRoot; - } - - /** - * Returns the set of PresenceStatus objects that a user of this service - * may request the provider to enter. - * - * @return Iterator a PresenceStatus array containing "enterable" status - * instances. - */ - public Iterator getSupportedStatusSet() - { - return SSHStatusEnum.supportedStatusSet(); - } - - /** - * Removes the specified contact from its current parent and places it - * under newParent. - * - * @param contactToMove the Contact to move - * @param newParent the ContactGroup where Contact - * would be placed. - */ - public void moveContactToGroup( - Contact contactToMove, - ContactGroup newParent) - { - ContactSSHImpl sshContact - = (ContactSSHImpl)contactToMove; - - ContactGroupSSHImpl parentSSHGroup - = findContactParent(sshContact); - - parentSSHGroup.removeContact(sshContact); - - //if this is a volatile contact then we haven't really subscribed to - //them so we'd need to do so here - if(!sshContact.isPersistent()) - { - //first tell everyone that the volatile contact was removed - fireSubscriptionEvent(sshContact - , parentSSHGroup - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - - try - { - //now subscribe - this.subscribe(newParent, contactToMove.getAddress()); - - //now tell everyone that we've added the contact - fireSubscriptionEvent(sshContact - , newParent - , SubscriptionEvent.SUBSCRIPTION_CREATED); - } - catch (Exception ex) - { - logger.error("Failed to move contact " - + sshContact.getAddress() - , ex); - } - } - else - { - ( (ContactGroupSSHImpl) newParent) - .addContact(sshContact); - - fireSubscriptionMovedEvent(contactToMove - , parentSSHGroup - , newParent); - } - } - - /** - * Requests the provider to enter into a status corresponding to the - * specified paramters. - * - * @param status the PresenceStatus as returned by - * getRequestableStatusSet - * @param statusMessage the message that should be set as the reason to - * enter that status - * @throws IllegalArgumentException if the status requested is not a - * valid PresenceStatus supported by this provider. - * @throws IllegalStateException if the provider is not currently - * registered. - */ - public void publishPresenceStatus( - PresenceStatus status, - String statusMessage) - throws IllegalArgumentException, - IllegalStateException - { - PresenceStatus oldPresenceStatus = this.presenceStatus; - this.presenceStatus = status; - this.statusMessage = statusMessage; - - this.fireProviderStatusChangeEvent(oldPresenceStatus); - - -// //since we are not a real protocol, we set the contact presence status -// //ourselves and make them have the same status as ours. -// changePresenceStatusForAllContacts( getServerStoredContactListRoot() -// , getPresenceStatus()); -// -// //now check whether we are in someone else's contact list and modify -// //our status there -// List contacts = findContactsPointingToUs(); -// -// Iterator contactsIter = contacts.iterator(); -// while (contactsIter.hasNext()) -// { -// ContactSSHImpl contact -// = (ContactSSHImpl) contactsIter.next(); -// -// PresenceStatus oldStatus = contact.getPresenceStatus(); -// contact.setPresenceStatus(status); -// contact.getParentPresenceOperationSet() -// .fireContactPresenceStatusChangeEvent( -// contact -// , contact.getParentContactGroup() -// , oldStatus); -// -// } - } - - - - /** - * Get the PresenceStatus for a particular contact. - * - * @param contactIdentifier the identifier of the contact whose status - * we're interested in. - * @return PresenceStatus the PresenceStatus of the specified - * contact - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * retrieving the status fails due to errors experienced during - * network communication - */ - public PresenceStatus queryContactStatus(String contactIdentifier) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - return findContactByID(contactIdentifier).getPresenceStatus(); - } - - /** - * Sets the presence status of contact to newStatus. - * - * @param contact the ContactSSHImpl whose status we'd like - * to set. - * @param newStatus the new status we'd like to set to contact. - */ - private void changePresenceStatusForContact( - ContactSSH contact, - PresenceStatus newStatus) - { - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, findContactParent(contact), oldStatus); - } - - /** - * Sets the presence status of all contacts in our contact list - * (except those that correspond to another provider registered with SC) - * to newStatus. - * - * @param newStatus the new status we'd like to set to contact. - * @param parent the group in which we'd have to update the status of all - * direct and indirect child contacts. - */ - private void changePresenceStatusForAllContacts( - ContactGroup parent, - PresenceStatus newStatus) - { - //first set the status for contacts in this group - Iterator childContacts = parent.contacts(); - - while(childContacts.hasNext()) - { - ContactSSHImpl contact - = (ContactSSHImpl)childContacts.next(); - - if(findProviderForSSHUserID(contact.getAddress()) != null) - { - //this is a contact corresponding to another SIP Communicator - //provider so we won't change it's status here. - continue; - } - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, parent, oldStatus); - } - - //now call this method recursively for all subgroups - Iterator subgroups = parent.subgroups(); - - while(subgroups.hasNext()) - { - ContactGroup subgroup = subgroups.next(); - changePresenceStatusForAllContacts(subgroup, newStatus); - } - } - - /** - * Returns the group that is parent of the specified sshGroup or null - * if no parent was found. - * @param sshGroup the group whose parent we're looking for. - * @return the ContactGroupSSHImpl instance that sshGroup - * belongs to or null if no parent was found. - */ - public ContactGroupSSHImpl findGroupParent( - ContactGroupSSHImpl sshGroup) - { - return contactListRoot.findGroupParent(sshGroup); - } - - /** - * Returns the group that is parent of the specified sshContact or - * null if no parent was found. - * @param sshContact the contact whose parent we're looking for. - * @return the ContactGroupSSHImpl instance that sshContact - * belongs to or null if no parent was found. - */ - public ContactGroupSSHImpl findContactParent( - ContactSSH sshContact) - { - return (ContactGroupSSHImpl)sshContact - .getParentContactGroup(); - } - - - /** - * Removes the specified group from the server stored contact list. - * - * @param group the group to remove. - * - * @throws IllegalArgumentException if group was not found in this - * protocol's contact list. - */ - public void removeServerStoredContactGroup(ContactGroup group) - throws IllegalArgumentException - { - ContactGroupSSHImpl sshGroup - = (ContactGroupSSHImpl)group; - - ContactGroupSSHImpl parent = findGroupParent(sshGroup); - - if(parent == null) - { - throw new IllegalArgumentException( - "group " + group - + " does not seem to belong to this protocol's contact " - + "list."); - } - - parent.removeSubGroup(sshGroup); - - this.fireServerStoredGroupEvent( - sshGroup, ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - } - - /** - * Renames the specified group from the server stored contact list. - * - * @param group the group to rename. - * @param newName the new name of the group. - */ - public void renameServerStoredContactGroup( - ContactGroup group, - String newName) - { - ((ContactGroupSSHImpl)group).setGroupName(newName); - - this.fireServerStoredGroupEvent( - group, ServerStoredGroupEvent - .GROUP_RENAMED_EVENT); - } - - - /** - * Persistently adds a subscription for the presence status of the - * contact corresponding to the specified contactIdentifier and indicates - * that it should be added to the specified group of the server stored - * contact list. - * - * @param parent the parent group of the server stored contact list - * where the contact should be added.

    - * @param contactIdentifier the contact whose status updates we are - * subscribing for. - * @throws IllegalArgumentException if contact or - * parent are not a contact known to the underlying protocol - * provider. - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe( - ContactGroup parent, - String contactIdentifier) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - ContactSSH sshContact = new ContactSSHImpl(contactIdentifier, - parentProvider); - -/* ProtocolProviderServiceSSHImpl.getUIService().getConfigurationWindow() - .setVisible(true); -*/ - sshContact.setParentGroup((ContactGroupSSHImpl)parent); - sshContact.getSSHConfigurationForm().setVisible(true); - - - -/* Gets the domain name or IP address of the sshContact machine via the - * UI Service Interface - sshContact.setPersistentData(ProtocolProviderServiceSSHImpl - .getUIService().getPopupDialog() - .showInputPopupDialog("Enter Domain Name or IP Address of " - + sshContact.getDisplayName())); - - // contact is added to list later after the user has provided - // details in SSHConfigurationForm - - // addContactToList method is called -*/ - } - - /** - * Add a contact to the specified group - * - * @param parent the group - * @param sshContact the contact - */ - public void addContactToList( - ContactGroup parent, - ContactSSH sshContact) - { - // Adds the sshContact to the sshContact list - - ((ContactGroupSSHImpl)parent).addContact(sshContact); - - fireSubscriptionEvent(sshContact, - parent, - SubscriptionEvent.SUBSCRIPTION_CREATED); - - //notify presence listeners for the status change. - fireContactPresenceStatusChangeEvent(sshContact - , parent - , SSHStatusEnum.NOT_AVAILABLE); - - sshContact.startTimerTask(); - } - - /** - * Adds a subscription for the presence status of the contact - * corresponding to the specified contactIdentifier. - * - * @param contactIdentifier the identifier of the contact whose status - * updates we are subscribing for.

    - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(String contactIdentifier) throws - IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - subscribe(contactListRoot, contactIdentifier); - - } - - /** - * Removes a subscription for the presence status of the specified - * contact. - * - * @param contact the contact whose status updates we are unsubscribing - * from. - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * unsubscribing fails due to errors experienced during network - * communication - */ - public void unsubscribe(Contact contact) throws - IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - ContactGroupSSHImpl parentGroup - = (ContactGroupSSHImpl)((ContactSSHImpl)contact) - .getParentContactGroup(); - - parentGroup.removeContact((ContactSSHImpl)contact); - - fireSubscriptionEvent(contact, - ((ContactSSHImpl)contact).getParentContactGroup() - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact( - String address, - String persistentData) - { - return createUnresolvedContact(address - , persistentData - , getServerStoredContactListRoot()); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @param parent the group where the unresolved contact is - * supposed to belong to. - * - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact( - String address, - String persistentData, - ContactGroup parent) - { - ContactSSH contact = new ContactSSHImpl( - address, - parentProvider); - - contact.setPersistentData(persistentData); - contact.startTimerTask(); - - // SSH Contacts are resolved by default - contact.setResolved(true); - - ( (ContactGroupSSHImpl) parent).addContact(contact); - - fireSubscriptionEvent(contact, - parent, - SubscriptionEvent.SUBSCRIPTION_CREATED); - - //since we don't have any server, we'll simply resolve the contact - //ourselves as if we've just received an event from the server telling - //us that it has been resolved. - fireSubscriptionEvent( - contact, parent, SubscriptionEvent.SUBSCRIPTION_RESOLVED); - - return contact; - } - - /** - * Looks for a ssh protocol provider registered for a user id matching - * sshUserID. - * - * @param sshUserID the ID of the SSH user whose corresponding - * protocol provider we'd like to find. - * @return ProtocolProviderServiceSSHImpl a ssh protocol - * provider registered for a user with id sshUserID or null - * if there is no such protocol provider. - */ - public ProtocolProviderServiceSSHImpl - findProviderForSSHUserID(String sshUserID) - { - BundleContext bc = SSHActivator.getBundleContext(); - - String osgiQuery = "(&" - + "(" + ProtocolProviderFactory.PROTOCOL - + "=" + ProtocolNames.SSH + ")" - + "(" + ProtocolProviderFactory.USER_ID - + "=" + sshUserID + ")" - + ")"; - - ServiceReference[] refs = null; - try - { - refs = bc.getServiceReferences( - ProtocolProviderService.class.getName() - ,osgiQuery); - } - catch (InvalidSyntaxException ex) - { - logger.error("Failed to execute the following osgi query: " - + osgiQuery - , ex); - } - - if(refs != null && refs.length > 0) - { - return (ProtocolProviderServiceSSHImpl)bc.getService(refs[0]); - } - - return null; - } - - /** - * Looks for ssh protocol providers that have added us to their - * contact list and returns list of all contacts representing us in these - * providers. - * - * @return a list of all contacts in other providers' contact lists that - * point to us. - */ - public List findContactsPointingToUs() - { - List contacts = new LinkedList(); - BundleContext bc = SSHActivator.getBundleContext(); - - String osgiQuery = - "(" + ProtocolProviderFactory.PROTOCOL - + "=SSH)"; - - ServiceReference[] refs = null; - try - { - refs = bc.getServiceReferences( - ProtocolProviderService.class.getName() - ,osgiQuery); - } - catch (InvalidSyntaxException ex) - { - logger.error("Failed to execute the following osgi query: " - + osgiQuery - , ex); - } - - for (int i =0; refs != null && i < refs.length; i++) - { - ProtocolProviderServiceSSHImpl gibProvider - = (ProtocolProviderServiceSSHImpl)bc.getService(refs[i]); - - OperationSetPersistentPresenceSSHImpl opSetPersPresence - = (OperationSetPersistentPresenceSSHImpl)gibProvider - .getOperationSet(OperationSetPersistentPresence.class); - - Contact contact = opSetPersPresence.findContactByID( - parentProvider.getAccountID().getUserID()); - - if (contact != null) - contacts.add(contact); - } - - return contacts; - } - - - /** - * Creates and returns a unresolved contact group from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created - * ContactGroup against the server or the contact itself. The - * protocol provider will later resolve the contact group. When this happens - * the corresponding event would notify interested subscription listeners. - * - * @param groupUID an identifier, returned by ContactGroup's getGroupUID, - * that the protocol provider may use in order to create the group. - * @param persistentData a String returned ContactGroups's - * getPersistentData() method during a previous run and that has been - * persistently stored locally. - * @param parentGroup the group under which the new group is to be created - * or null if this is group directly underneath the root. - * @return the unresolved ContactGroup created from the specified - * uid and persistentData - */ - public ContactGroup createUnresolvedContactGroup( - String groupUID, - String persistentData, - ContactGroup parentGroup) - { - ContactGroupSSHImpl newGroup - = new ContactGroupSSHImpl( - ContactGroupSSHImpl.createNameFromUID(groupUID) - , parentProvider); - newGroup.setResolved(false); - - //if parent is null then we're adding under root. - if(parentGroup == null) - parentGroup = getServerStoredContactListRoot(); - - ((ContactGroupSSHImpl)parentGroup).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - - return newGroup; - } - - private class UnregistrationListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenver - * a change in the registration state of the corresponding provider had - * occurred. The method is particularly interested in events stating - * that the ssh provider has unregistered so that it would fire - * status change events for all contacts in our buddy list. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (! evt.getNewState().equals(RegistrationState.UNREGISTERED) - && !evt.getNewState().equals(RegistrationState - .AUTHENTICATION_FAILED) - && !evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) - { - return; - } - - //send event notifications saying that all our buddies are - //offline. The icq protocol does not implement top level buddies - //nor subgroups for top level groups so a simple nested loop - //would be enough. - Iterator groupsIter - = getServerStoredContactListRoot().subgroups(); - while (groupsIter.hasNext()) - { - ContactGroup group = groupsIter.next(); - Iterator contactsIter = group.contacts(); - - while (contactsIter.hasNext()) - { - ContactSSHImpl contact - = (ContactSSHImpl) contactsIter.next(); - - PresenceStatus oldContactStatus - = contact.getPresenceStatus(); - - if (!oldContactStatus.isOnline()) - continue; - - contact.setPresenceStatus(SSHStatusEnum.OFFLINE); - - fireContactPresenceStatusChangeEvent( - contact - , contact.getParentContactGroup() - , oldContactStatus); - } - } - } - } - - /** - * Returns the volatile group or null if this group has not yet been - * created. - * - * @return a volatile group existing in our contact list or null - * if such a group has not yet been created. - */ - private ContactGroupSSHImpl getNonPersistentGroup() - { - for (int i = 0 - ; i < getServerStoredContactListRoot().countSubgroups() - ; i++) - { - ContactGroupSSHImpl gr = - (ContactGroupSSHImpl)getServerStoredContactListRoot() - .getGroup(i); - - if(!gr.isPersistent()) - return gr; - } - - return null; - } - - - /** - * Creates a non persistent contact for the specified address. This would - * also create (if necessary) a group for volatile contacts that would not - * be added to the server stored contact list. This method would have no - * effect on the server stored contact list. - * - * @param contactAddress the address of the volatile contact we'd like to - * create. - * @return the newly created volatile contact. - */ - public ContactSSHImpl createVolatileContact(String contactAddress) - { - //First create the new volatile contact; - ContactSSHImpl newVolatileContact = new ContactSSHImpl( - contactAddress, - this.parentProvider); - - newVolatileContact.setPersistent(false); - - - //Check whether a volatile group already exists and if not create - //one - ContactGroupSSHImpl theVolatileGroup = getNonPersistentGroup(); - - - //if the parent volatile group is null then we create it - if (theVolatileGroup == null) - { - theVolatileGroup = new ContactGroupSSHImpl( - SSHActivator.getResources().getI18NString( - "service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME") - , parentProvider); - theVolatileGroup.setResolved(false); - theVolatileGroup.setPersistent(false); - theVolatileGroup.addContact(newVolatileContact); - - this.contactListRoot.addSubgroup(theVolatileGroup); - - fireServerStoredGroupEvent(theVolatileGroup - , ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - //now add the volatile contact instide it - theVolatileGroup.addContact(newVolatileContact); - fireSubscriptionEvent(newVolatileContact - , theVolatileGroup - , SubscriptionEvent.SUBSCRIPTION_CREATED); - - return newVolatileContact; - } - - /** - * DUMMY METHOD - * Handler for incoming authorization requests. - * - * @param handler an instance of an AuthorizationHandler for - * authorization requests coming from other users requesting - * permission add us to their contact list. - */ - public void setAuthorizationHandler(AuthorizationHandler handler) - { - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolIconSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolIconSSHImpl.java deleted file mode 100644 index 592b2b1..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolIconSSHImpl.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Represents the SSH protocol icon. Implements the ProtocolIcon - * interface in order to provide a SSH logo image in two different sizes. - * - * @author Shobhit Jindal - */ -public class ProtocolIconSSHImpl - implements ProtocolIcon -{ - private static Logger logger - = Logger.getLogger(ProtocolIconSSHImpl.class); - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconsTable - = new Hashtable(); - static { - iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, - getImageInBytes("service.protocol.ssh.SSH_16x16")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_32x32, - getImageInBytes("service.protocol.ssh.SSH_32x32")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, - getImageInBytes("service.protocol.ssh.SSH_48x48")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_64x64, - getImageInBytes("service.protocol.ssh.SSH_64x64")); - } - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconPathsTable - = new Hashtable(); - static { - iconPathsTable.put(ProtocolIcon.ICON_SIZE_16x16, - SSHActivator.getResources().getImagePath( - "service.protocol.ssh.SSH_16x16")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_32x32, - SSHActivator.getResources().getImagePath( - "service.protocol.ssh.SSH_32x32")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_48x48, - SSHActivator.getResources().getImagePath( - "service.protocol.ssh.SSH_48x48")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_64x64, - SSHActivator.getResources().getImagePath( - "service.protocol.ssh.SSH_64x64")); - } - - /** - * Implements the ProtocolIcon.getSupportedSizes() method. Returns - * an iterator to a set containing the supported icon sizes. - * @return an iterator to a set containing the supported icon sizes - */ - public Iterator getSupportedSizes() - { - return iconsTable.keySet().iterator(); - } - - /** - * Returns TRUE if a icon with the given size is supported, FALSE-otherwise. - * - * @return TRUE if a icon with the given size is supported, FALSE otherwise - */ - public boolean isSizeSupported(String iconSize) - { - return iconsTable.containsKey(iconSize); - } - - /** - * Returns the icon image in the given size. - * @param iconSize the icon size; one of ICON_SIZE_XXX constants - * @return the icon - */ - public byte[] getIcon(String iconSize) - { - return iconsTable.get(iconSize); - } - - /** - * Returns a path to the icon with the given size. - * @param iconSize the size of the icon we're looking for - * @return the path to the icon with the given size - */ - public String getIconPath(String iconSize) - { - return iconPathsTable.get(iconSize); - } - - /** - * Returns the icon image used to represent the protocol connecting state. - * @return the icon image used to represent the protocol connecting state - */ - public byte[] getConnectingIcon() - { - return getImageInBytes("protocolIconSsh"); - } - - /** - * Returns the byte representation of the image corresponding to the given - * identifier. - * - * @param imageID the identifier of the image - * @return the byte representation of the image corresponding to the given - * identifier. - */ - public static byte[] getImageInBytes(String imageID) - { - InputStream in = SSHActivator.getResources(). - getImageInputStream(imageID); - - if (in == null) - return null; - byte[] image = null; - try - { - image = new byte[in.available()]; - - in.read(image); - } - catch (IOException e) - { - logger.error("Failed to load image:" + imageID, e); - } - - return image; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSH.java b/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSH.java deleted file mode 100644 index 8c38f60..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSH.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import net.java.sip.communicator.service.protocol.*; - -import org.osgi.framework.*; - -/** - * - * @author Shobhit Jindal - */ -public abstract class ProtocolProviderFactorySSH - extends ProtocolProviderFactory -{ - /** - * The name of a property representing the IDENTITY_FILE of the protocol for - * a ProtocolProviderFactory. - */ - public static final String IDENTITY_FILE = "IDENTITY_FILE"; - - /** - * The name of a property representing the KNOWN_HOSTS_FILE of the protocol - * for a ProtocolProviderFactory. - */ - public static final String KNOWN_HOSTS_FILE = "KNOWN_HOSTS_FILE"; - - protected ProtocolProviderFactorySSH(BundleContext bundleContext, - String protocolName) - { - super(bundleContext, protocolName); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSHImpl.java deleted file mode 100644 index 68e33bc..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderFactorySSHImpl.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -import org.osgi.framework.*; - -/** - * The SSH protocol provider factory creates instances of the SSH - * protocol provider service. One Service instance corresponds to one account. - * - * @author Shobhit Jindal - */ -public class ProtocolProviderFactorySSHImpl - extends ProtocolProviderFactorySSH -{ - - /** - * Creates an instance of the ProtocolProviderFactorySSHImpl. - */ - public ProtocolProviderFactorySSHImpl() - { - super(SSHActivator.getBundleContext(), ProtocolNames.SSH); - } - - /** - * Initializaed and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. - * - * @param userIDStr tha/a user identifier uniquely representing the newly - * created account within the protocol namespace. - * @param accountProperties a set of protocol (or implementation) - * specific properties defining the new account. - * @return the AccountID of the newly created account. - */ - @Override - public AccountID installAccount( - String userIDStr, - Map accountProperties) - { - BundleContext context = SSHActivator.getBundleContext(); - if (context == null) - throw new NullPointerException("The specified BundleContext was " + - "null"); - - if (userIDStr == null) - throw new NullPointerException("The specified AccountID was null"); - - if (accountProperties == null) - throw new NullPointerException("The specified property map was" + - " null"); - - accountProperties.put(USER_ID, userIDStr); - - AccountID accountID = new SSHAccountID(userIDStr, accountProperties); - - //make sure we haven't seen this account id before. - if (registeredAccounts.containsKey(accountID)) - throw new IllegalStateException( - "An account for id " + userIDStr + " was already" + - " installed!"); - - //first store the account and only then load it as the load generates - //an osgi event, the osgi event triggers (through the UI) a call to the - //ProtocolProviderService.register() method and it needs to acces - //the configuration service and check for a stored password. - this.storeAccount(accountID, false); - - accountID = loadAccount(accountProperties); - -/* ServiceReference ppServiceRef = context - .getServiceReference(ProtocolProviderService.class.getName()); - - ProtocolProviderService ppService = (ProtocolProviderService) - context.getService(ppServiceRef); - - OperationSetPersistentPresence operationSetPersistentPresence = - (OperationSetPersistentPresence) ppService.getOperationSet( - OperationSetPersistentPresence.class); - - try - { - // The below should never fail for SSH accounts - operationSetPersistentPresence.subscribe(userIDStr); - - } - catch(OperationFailedException ex) - { - ex.printStackTrace(); - } -*/ - return accountID; - } - - @Override - protected AccountID createAccountID(String userID, Map accountProperties) - { - return new SSHAccountID(userID, accountProperties); - } - - @Override - protected ProtocolProviderService createService(String userID, - AccountID accountID) - { - ProtocolProviderServiceSSHImpl service = - new ProtocolProviderServiceSSHImpl(); - - service.initialize(userID, accountID); - return service; - } - -// /** -// * Saves the password for the specified account after scrambling it a bit -// * so that it is not visible from first sight (Method remains highly -// * insecure). -// * -// * @param accountID the AccountID for the account whose password we're -// * storing. -// * @param passwd the password itself. -// * -// * @throws java.lang.IllegalArgumentException if no account corresponding -// * to accountID has been previously stored. -// */ -// public void storePassword(AccountID accountID, String passwd) -// throws IllegalArgumentException -// { -// super.storePassword(SSHActivator.getBundleContext(), -// accountID, -// String.valueOf(Base64.encode(passwd.getBytes()))); -// } -// -// /** -// * Returns the password last saved for the specified account. -// * -// * @param accountID the AccountID for the account whose password we're -// * looking for.. -// * -// * @return a String containing the password for the specified accountID. -// * -// * @throws java.lang.IllegalArgumentException if no account corresponding -// * to accountID has been previously stored. -// */ -// public String loadPassword(AccountID accountID) -// throws IllegalArgumentException -// { -// String password = super.loadPassword(SSHActivator.getBundleContext() -// , accountID ); -// return(String.valueOf(Base64.decode(password))); -// } - - @Override - public void modifyAccount( ProtocolProviderService protocolProvider, - Map accountProperties) - throws NullPointerException - { - // TODO Auto-generated method stub - - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderServiceSSHImpl.java b/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderServiceSSHImpl.java deleted file mode 100644 index a4b16e6..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ProtocolProviderServiceSSHImpl.java +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.Logger; - -import org.osgi.framework.*; - -import com.jcraft.jsch.*; - -/** - * A SSH implementation of the ProtocolProviderService. - * - * @author Shobhit Jindal - */ -public class ProtocolProviderServiceSSHImpl - extends AbstractProtocolProviderService -{ - private static final Logger logger - = Logger.getLogger(ProtocolProviderServiceSSHImpl.class); - - /** - * The name of this protocol. - */ - public static final String SSH_PROTOCOL_NAME = ProtocolNames.SSH; - -// /** -// * The identifier for SSH Stack -// * Java Secure Channel JSch -// */ -// JSch jsch = new JSch(); - - /** - * The test command given after each command to determine the reply length - * of the command - */ - //private final String testCommand = - // Resources.getString("testCommand"); - - /** - * A reference to the protocol provider of UIService - */ - private static ServiceReference ppUIServiceRef; - - /** - * Connection timeout to a remote server in milliseconds - */ - private static int connectionTimeout = 30000; - - /** - * A reference to UI Service - */ - private static UIService uiService; - - /** - * The id of the account that this protocol provider represents. - */ - private AccountID accountID = null; - - /** - * We use this to lock access to initialization. - */ - private final Object initializationLock = new Object(); - - private OperationSetBasicInstantMessagingSSHImpl basicInstantMessaging; - - private OperationSetFileTransferSSHImpl fileTranfer; - - /** - * Indicates whether or not the provider is initialized and ready for use. - */ - private boolean isInitialized = false; - - /** - * The logo corresponding to the ssh protocol. - */ - private ProtocolIconSSHImpl sshIcon - = new ProtocolIconSSHImpl(); - - /** - * The registration state of SSH Provider is taken to be registered by - * default as it doesn't correspond to the state on remote server - */ - private RegistrationState currentRegistrationState - = RegistrationState.REGISTERED; - - /** - * The default constructor for the SSH protocol provider. - */ - public ProtocolProviderServiceSSHImpl() - { - if (logger.isTraceEnabled()) - logger.trace("Creating a ssh provider."); - - try - { - // converting to milliseconds - connectionTimeout = Integer.parseInt(Resources.getString( - "connectionTimeout")) * 1000; - } - catch(NumberFormatException ex) - { - logger.error("Connection Timeout set to 30 seconds"); - } - } - - /** - * Initializes the service implementation, and puts it in a sate where it - * could interoperate with other services. It is strongly recomended that - * properties in this Map be mapped to property names as specified by - * AccountProperties. - * - * @param userID the user id of the ssh account we're currently - * initializing - * @param accountID the identifier of the account that this protocol - * provider represents. - * - * @see net.java.sip.communicator.service.protocol.AccountID - */ - protected void initialize( - String userID, - AccountID accountID) - { - synchronized(initializationLock) - { - this.accountID = accountID; - - //initialize the presence operationset - OperationSetPersistentPresenceSSHImpl persistentPresence = - new OperationSetPersistentPresenceSSHImpl(this); - - addSupportedOperationSet( - OperationSetPersistentPresence.class, - persistentPresence); - //register it once again for those that simply need presence and - //won't be smart enough to check for a persistent presence - //alternative - addSupportedOperationSet( - OperationSetPresence.class, - persistentPresence); - - //initialize the IM operation set - basicInstantMessaging = new - OperationSetBasicInstantMessagingSSHImpl( - this); - addSupportedOperationSet( - OperationSetBasicInstantMessaging.class, - basicInstantMessaging); - - //initialze the file transfer operation set - fileTranfer = new OperationSetFileTransferSSHImpl(this); - addSupportedOperationSet( - OperationSetFileTransfer.class, - fileTranfer); - - isInitialized = true; - } - } - - /** - * Determines whether a vaild session exists for the contact of remote - * machine. - * - * @param sshContact ID of SSH Contact - * - * @return true if the session is connected - * false otherwise - */ - public boolean isSessionValid(ContactSSH sshContact) - { - Session sshSession = sshContact.getSSHSession(); - if( sshSession != null) - if(sshSession.isConnected()) - return true; - - // remove reference to an unconnected SSH Session, if any - sshContact.setSSHSession(null); - return false; - } - - /** - * Determines whether the contact is connected to shell of remote machine - * as a precheck for any further operation - * - * @param sshContact ID of SSH Contact - * - * @return true if the contact is connected - * false if the contact is not connected - */ - public boolean isShellConnected(ContactSSH sshContact) - { - // a test command may also be run here - - if(isSessionValid(sshContact)) - { - return(sshContact.getShellChannel() != null); - } - - /* - * Above should be return(sshContact.getShellChannel() != null - * && sshContact.getShellChannel().isConnected()); - * - * but incorrect reply from stack for isConnected() - */ - - return false; - } - - /** - * Creates a shell channel to the remote machine - * a new jsch session is also created if the current one is invalid - * - * @param sshContact the contact of the remote machine - * @param firstMessage the first message - */ - public void connectShell( - final ContactSSH sshContact, - final Message firstMessage) - { - sshContact.setConnectionInProgress(true); - - final Thread newConnection = new Thread((new Runnable() - { - public void run() - { - OperationSetPersistentPresenceSSHImpl persistentPresence - = (OperationSetPersistentPresenceSSHImpl)sshContact - .getParentPresenceOperationSet(); - - persistentPresence.changeContactPresenceStatus( - sshContact, - SSHStatusEnum.CONNECTING); - - try - { - if(!isSessionValid(sshContact)) - createSSHSessionAndLogin(sshContact); - - createShellChannel(sshContact); - - //initializing the reader and writers of ssh contact - - persistentPresence.changeContactPresenceStatus( - sshContact, - SSHStatusEnum.CONNECTED); - - showWelcomeMessage(sshContact); - - sshContact.setMessageType(ContactSSH - .CONVERSATION_MESSAGE_RECEIVED); - - sshContact.setConnectionInProgress(false); - - Thread.sleep(1500); - - sshContact.setCommandSent(true); - - basicInstantMessaging.sendInstantMessage( - sshContact, - firstMessage); - } - // rigorous Exception Checking in future - catch (Exception ex) - { - persistentPresence.changeContactPresenceStatus( - sshContact, - SSHStatusEnum.NOT_AVAILABLE); - - ex.printStackTrace(); - } - finally - { - sshContact.setConnectionInProgress(false); - } - } - })); - - newConnection.start(); - } - - /** - * Creates a channel for shell type in the current session - * channel types = shell, sftp, exec(X forwarding), - * direct-tcpip(stream forwarding) etc - * - * @param sshContact ID of SSH Contact - * @throws IOException if the shell channel cannot be created - */ - public void createShellChannel(ContactSSH sshContact) - throws IOException - { - try - { - Channel shellChannel = sshContact.getSSHSession() - .openChannel("shell"); - - //initalizing the reader and writers of ssh contact - sshContact.initializeShellIO(shellChannel.getInputStream(), - shellChannel.getOutputStream()); - - ((ChannelShell)shellChannel).setPtyType( - sshContact.getSSHConfigurationForm().getTerminalType()); - - //initializing the shell - shellChannel.connect(1000); - - sshContact.setShellChannel(shellChannel); - - sshContact.sendLine("export PS1="); - } - catch (JSchException ex) - { - sshContact.setSSHSession(null); - throw new IOException("Unable to create shell channel to remote" + - " server"); - } - } - - /** - * Closes the Shell channel are associated IO Streams - * - * @param sshContact ID of SSH Contact - * @throws JSchException if something went wrong in JSch - * @throws IOException if I/O exception occurred - */ - public void closeShellChannel(ContactSSH sshContact) throws - JSchException, - IOException - { - sshContact.closeShellIO(); - sshContact.getShellChannel().disconnect(); - sshContact.setShellChannel(null); - } - - /** - * Creates a SSH Session with a remote machine and tries to login - * according to the details specified by Contact - * An appropriate message is shown to the end user in case the login fails - * - * @param sshContact ID of SSH Contact - * - * @throws JSchException if a JSch is unable to create a SSH Session with - * the remote machine - * @throws InterruptedException if the thread is interrupted before session - * connected or is timed out - * @throws OperationFailedException if not of above reasons :-) - */ - public void createSSHSessionAndLogin(ContactSSH sshContact) throws - JSchException, - OperationFailedException, - InterruptedException - { - if (logger.isInfoEnabled()) - logger.info("Creating a new SSH Session to " - + sshContact.getHostName()); - - // creating a new JSch Stack identifier for contact - JSch jsch = new JSch(); - - String knownHosts = - accountID.getAccountPropertyString("KNOWN_HOSTS_FILE"); - - if(!knownHosts.equals("Optional")) - jsch.setKnownHosts(knownHosts); - - String identitiyKey = - accountID.getAccountPropertyString("IDENTITY_FILE"); - - String userName = sshContact.getUserName(); - - // use the name of system user if the contact has not supplied SSH - // details - if(userName.equals("")) - userName = System.getProperty("user.name"); - - if(!identitiyKey.equals("Optional")) - jsch.addIdentity(identitiyKey); - - // creating a new session for the contact - Session session = jsch.getSession( - userName, - sshContact.getHostName(), - sshContact.getSSHConfigurationForm().getPort()); - - /** - * Creating and associating User Info with the session - * User Info passes authentication from sshContact to SSH Stack - */ - SSHUserInfo sshUserInfo = new SSHUserInfo(sshContact); - - session.setUserInfo(sshUserInfo); - - /** - * initializing the session - */ - session.connect(connectionTimeout); - - int count = 0; - - // wait for session to get connected - while(!session.isConnected() && count<=30000) - { - Thread.sleep(1000); - count += 1000; - if (logger.isTraceEnabled()) - logger.trace("SSH:" + sshContact.getHostName() - + ": Sleep zzz .. " ); - } - - // if timeout have exceeded - if(count>30000) - { - sshContact.setSSHSession(null); - JOptionPane.showMessageDialog( - null, - "SSH Connection attempt to " - + sshContact.getHostName() + " timed out"); - - // error codes are not defined yet - throw new OperationFailedException("SSH Connection attempt to " + - sshContact.getHostName() + " timed out", 2); - } - - sshContact.setJSch(jsch); - sshContact.setSSHSession(session); - - if (logger.isInfoEnabled()) - logger.info("A new SSH Session to " + sshContact.getHostName() - + " Created"); - } - - /** - * Closes the SSH Session associated with the contact - * - * @param sshContact ID of SSH Contact - */ - void closeSSHSession(ContactSSH sshContact) - { - sshContact.getSSHSession().disconnect(); - sshContact.setSSHSession(null); - } - - /** - * Presents the login welcome message to user - * - * @param sshContact ID of SSH Contact - * @throws IOException if I/O exception occurred - */ - public void showWelcomeMessage(ContactSSH sshContact) - throws IOException - { -/* //sending the command - sshContact.sendLine(testCommand); - - String reply = "", line = ""; - - // message is extracted until the test Command ie echoed back - while(line.indexOf(testCommand) == -1) - { - reply += line + "\n"; - line = sshContact.getLine(); - } - - uiService.getPopupDialog().showMessagePopupDialog - (reply,"Message from " + sshContact.getDisplayName(), - uiService.getPopupDialog().INFORMATION_MESSAGE); - - if(line.startsWith(testCommand)) - while(!sshContact.getLine().contains(testCommand)); - - //one line output of testCommand - sshContact.getLine(); -*/ - if (logger.isDebugEnabled()) - logger.debug("SSH: Welcome message shown"); - } - - /** - * Returns a reference to UIServce for accessing UI related services - * - * @return uiService a reference to UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the AccountID that uniquely identifies the account represented - * by this instance of the ProtocolProviderService. - * - * @return the id of the account represented by this provider. - */ - public AccountID getAccountID() - { - return accountID; - } - - /** - * Returns the short name of the protocol that the implementation of this - * provider is based upon (like SIP, Jabber, ICQ/AIM, or others for - * example). - * - * @return a String containing the short name of the protocol this - * service is implementing (most often that would be a name in - * ProtocolNames). - */ - public String getProtocolName() - { - return SSH_PROTOCOL_NAME; - } - - /** - * Returns the state of the registration of this protocol provider with - * the corresponding registration service. - * - * @return ProviderRegistrationState - */ - public RegistrationState getRegistrationState() - { - return currentRegistrationState; - } - - /** - * Starts the registration process. - * - * @param authority the security authority that will be used for - * resolving any security challenges that may be returned during the - * registration or at any moment while wer're registered. - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void register(SecurityAuthority authority) - throws OperationFailedException - { - RegistrationState oldState = currentRegistrationState; - currentRegistrationState = RegistrationState.REGISTERED; - - //get a reference to UI Service via its Service Reference - ppUIServiceRef = SSHActivator.getBundleContext() - .getServiceReference(UIService.class.getName()); - - uiService = (UIService)SSHActivator.getBundleContext() - .getService(ppUIServiceRef); - - fireRegistrationStateChanged( - oldState - , currentRegistrationState - , RegistrationStateChangeEvent.REASON_USER_REQUEST - , null); - - } - - /** - * Makes the service implementation close all open sockets and release - * any resources that it might have taken and prepare for - * shutdown/garbage collection. - */ - public void shutdown() - { - if(!isInitialized) - { - return; - } - if (logger.isTraceEnabled()) - logger.trace("Killing the SSH Protocol Provider."); - - if(isRegistered()) - { - try - { - //do the unregistration - unregister(); - } - catch (OperationFailedException ex) - { - //we're shutting down so we need to silence the exception here - logger.error( - "Failed to properly unregister before shutting down. " - + getAccountID() - , ex); - } - } - - isInitialized = false; - } - - /** - * Ends the registration of this protocol provider with the current - * registration service. - * - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void unregister() - throws OperationFailedException - { - RegistrationState oldState = currentRegistrationState; - currentRegistrationState = RegistrationState.UNREGISTERED; - - fireRegistrationStateChanged( - oldState - , currentRegistrationState - , RegistrationStateChangeEvent.REASON_USER_REQUEST - , null); - } - - /* - * (non-Javadoc) - * - * @see net.java.sip.communicator.service.protocol.ProtocolProviderService# - * isSignallingTransportSecure() - */ - public boolean isSignalingTransportSecure() - { - return false; - } - - /** - * Returns the "transport" protocol of this instance used to carry the - * control channel for the current protocol service. - * - * @return The "transport" protocol of this instance: TCP. - */ - public TransportProtocol getTransportProtocol() - { - return TransportProtocol.TCP; - } - - /** - * Returns the ssh protocol icon. - * @return the ssh protocol icon - */ - public ProtocolIcon getProtocolIcon() - { - return sshIcon; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/Resources.java b/src/net/java/sip/communicator/impl/protocol/ssh/Resources.java deleted file mode 100644 index 48b9b49..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/Resources.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import net.java.sip.communicator.service.resources.*; - -/** - * @author Shobhit Jindal - */ -public class Resources -{ - /** - * The SSH logo imageID. - */ - public static ImageID SSH_LOGO = new ImageID("protocolIconSsh"); - - /** - * Returns an string corresponding to the given key. - * - * @param key The key of the string. - * - * @return a string corresponding to the given key. - */ - public static String getString(String key) - { - return SSHActivator.getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImage(ImageID imageID) - { - return SSHActivator.getResources().getImageInBytes(imageID.getId()); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHAccountID.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHAccountID.java deleted file mode 100644 index 8f9dda7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHAccountID.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The SSH implementation of a sip-communicator account id. - * @author Shobhit Jindal - */ -public class SSHAccountID - extends AccountID -{ - /** - * Creates an account id from the specified id and account properties. - * - * @param userID the user identifier correspnding to thi account - * @param accountProperties any other properties necessary for the account. - */ - SSHAccountID(String userID, Map accountProperties) - { - super(userID - , accountProperties - , "SSH" - , "sip-communicator.org"); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHActivator.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHActivator.java deleted file mode 100644 index 7108020..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHActivator.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Loads the SSH provider factory and registers its services in the OSGI - * bundle context. - * - * @author Shobhit Jindal - */ -public class SSHActivator - implements BundleActivator -{ - private static final Logger logger - = Logger.getLogger(SSHActivator.class); - - /** - * A reference to the registration of our SSH protocol provider - * factory. - */ - private ServiceRegistration sshPpFactoryServReg = null; - - /** - * A reference to the SSH protocol provider factory. - */ - private static ProtocolProviderFactorySSHImpl - sshProviderFactory = null; - - /** - * The currently valid bundle context. - */ - private static BundleContext bundleContext = null; - - private static ResourceManagementService resourcesService; - - /** - * Called when this bundle is started. In here we'll export the - * ssh ProtocolProviderFactory implementation so that it could be - * possible to register accounts with it in SIP Communicator. - * - * @param context The execution context of the bundle being started. - * @throws Exception If this method throws an exception, this bundle is - * marked as stopped and the Framework will remove this bundle's - * listeners, unregister all services registered by this bundle, and - * release all services used by this bundle. - */ - public void start(BundleContext context) - throws Exception - { - bundleContext = context; - - Hashtable hashtable = new Hashtable(); - hashtable.put(ProtocolProviderFactory.PROTOCOL, "SSH"); - - sshProviderFactory = new ProtocolProviderFactorySSHImpl(); - - //reg the ssh provider factory. - sshPpFactoryServReg = context.registerService( - ProtocolProviderFactory.class.getName(), - sshProviderFactory, - hashtable); - - if (logger.isInfoEnabled()) - logger.info("SSH protocol implementation [STARTED]."); - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return bundleContext a reference to the BundleContext instance - * that we were started with. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Retrurns a reference to the protocol provider factory that we have - * registered. - * @return a reference to the ProtocolProviderFactoryJabberImpl - * instance that we have registered from this package. - */ - public static ProtocolProviderFactorySSHImpl - getProtocolProviderFactory() - { - return sshProviderFactory; - } - - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param context The execution context of the bundle being stopped. - * @throws Exception If this method throws an exception, the bundle is - * still marked as stopped, and the Framework will remove the bundle's - * listeners, unregister all services registered by the bundle, and - * release all services used by the bundle. - */ - public void stop(BundleContext context) - throws Exception - { - sshProviderFactory.stop(); - sshPpFactoryServReg.unregister(); - if (logger.isInfoEnabled()) - logger.info("SSH protocol implementation [STOPPED]."); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils.getService(bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHContactInfo.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHContactInfo.java deleted file mode 100644 index 47bb484..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHContactInfo.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.awt.*; -import java.awt.event.*; -import java.text.*; - -import javax.swing.*; -import javax.swing.text.*; - -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * @author Shobhit Jindal - */ -class SSHContactInfo - extends SIPCommDialog -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private ContactSSH sshContact; - - private JPanel mainPanel = new TransparentPanel(); - private JPanel machinePanel = new TransparentPanel(); - private JPanel detailNamesPanel = new TransparentPanel(); - private JPanel detailFieldsPanel = new TransparentPanel(); - private JPanel detailsPanel = new TransparentPanel(); - - private JCheckBox addDetailsCheckBox = new SIPCommCheckBox("Add Details"); - - private JButton doneButton = new JButton("Done"); - private JLabel machineID = new JLabel("Hostname / IP: "); - private JTextField machineIDField = new JTextField(); - private JLabel userName = new JLabel("User Name: "); - private JTextField userNameField = new JTextField(); - private JLabel password = new JLabel("Password: "); - private JTextField passwordField = new JPasswordField(); - private JLabel port = new JLabel("Port: "); - - private JFormattedTextField portField; - private JLabel secs = new JLabel("secs"); - private JLabel statusUpdate = new JLabel("Update Interval: "); - private JLabel terminalType = new JLabel("Terminal Type: "); - private JTextField terminalTypeField = new JTextField("SIP Communicator"); - private JSpinner updateTimer = new JSpinner(); - - private JPanel emptyPanel1 = new TransparentPanel(); - - private JPanel emptyPanel2 = new TransparentPanel(); - - private JPanel emptyPanel3 = new TransparentPanel(); - - private JPanel emptyPanel4 = new TransparentPanel(); - - private JPanel emptyPanel5 = new TransparentPanel(); - - private JPanel emptyPanel6 = new TransparentPanel(); - - private JPanel emptyPanel7 = new TransparentPanel(); - - private JPanel emptyPanel8 = new TransparentPanel(); - - private JPanel emptyPanel9 = new TransparentPanel(); - - private JPanel emptyPanel10 = new TransparentPanel(); - - private JPanel emptyPanel11 = new TransparentPanel(); - -// private ContactGroup contactGroup = null; - - /** - * Creates a new instance of SSHContactInfo - * - * @param sshContact the concerned contact - */ - public SSHContactInfo(ContactSSH sshContact) { - super(true); - - this.sshContact = sshContact; - initForm(); - - this.getContentPane().add(mainPanel); - - this.setSize(370, 325); - - this.setResizable(false); - - this.setTitle("SSH: Account Details of " + sshContact.getDisplayName()); - - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Dimension screenSize = toolkit.getScreenSize(); - - int x = (screenSize.width - this.getWidth()) / 2; - int y = (screenSize.height - this.getHeight()) / 2; - - this.setLocation(x,y); - -// ProtocolProviderServiceSSHImpl.getUIService().getConfigurationWindow(). -// addConfigurationForm(this); - } - - /** - * initialize the form. - */ - public void initForm() { - updateTimer.setValue(30); - MaskFormatter maskFormatter = new MaskFormatter(); - try { - maskFormatter.setMask("#####"); - } catch (ParseException ex) { - ex.printStackTrace(); - } - maskFormatter.setAllowsInvalid(false); - portField = new JFormattedTextField(maskFormatter); - portField.setValue(22); - - userNameField.setEnabled(false); - passwordField.setEditable(false); - portField.setEnabled(false); - terminalTypeField.setEnabled(false); - updateTimer.setEnabled(false); - - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - machinePanel.setLayout(new BoxLayout(machinePanel, BoxLayout.X_AXIS)); - detailNamesPanel.setLayout(new BoxLayout(detailNamesPanel, - BoxLayout.Y_AXIS)); - detailFieldsPanel.setLayout(new BoxLayout(detailFieldsPanel, - BoxLayout.Y_AXIS)); - detailsPanel.setLayout(new BoxLayout(detailsPanel, BoxLayout.X_AXIS)); - - machinePanel.add(machineID); - machinePanel.add(machineIDField); - - detailNamesPanel.add(userName); - detailNamesPanel.add(emptyPanel1); - detailNamesPanel.add(password); - detailNamesPanel.add(emptyPanel2); - detailNamesPanel.add(port); - detailNamesPanel.add(emptyPanel3); - detailNamesPanel.add(statusUpdate); - detailNamesPanel.add(emptyPanel4); - detailNamesPanel.add(terminalType); - - detailFieldsPanel.add(userNameField); - detailFieldsPanel.add(emptyPanel5); - detailFieldsPanel.add(passwordField); - detailFieldsPanel.add(emptyPanel6); - detailFieldsPanel.add(portField); - detailFieldsPanel.add(emptyPanel7); - detailFieldsPanel.add(updateTimer); - detailFieldsPanel.add(emptyPanel8); - detailFieldsPanel.add(terminalTypeField); - - detailsPanel.add(detailNamesPanel); - detailsPanel.add(detailFieldsPanel); - - detailsPanel.setBorder(BorderFactory.createTitledBorder("Details")); - - mainPanel.add(emptyPanel9); - mainPanel.add(machinePanel); - mainPanel.add(addDetailsCheckBox); - mainPanel.add(detailsPanel); - mainPanel.add(emptyPanel10); - mainPanel.add(doneButton); - mainPanel.add(emptyPanel11); - - addDetailsCheckBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent event) { - addDetailsCheckBox.setEnabled(false); - userNameField.setEnabled(true); - passwordField.setEditable(true); - portField.setEnabled(true); - terminalTypeField.setEnabled(true); - updateTimer.setEnabled(true); - - userNameField.grabFocus(); - } - }); - - doneButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent event) { - if(machineIDField.getText().equals("")) { - machineIDField.setText("Field needed"); - return; - } - - sshContact.savePersistentDetails(); - - //add contact to contact list - ((OperationSetPersistentPresenceSSHImpl)sshContact - .getParentPresenceOperationSet()) - .addContactToList( - sshContact.getParentContactGroup(), - sshContact); - - setVisible(false); - } - }); - } - - /** - * Return the ssh icon - * - * @return the ssh icon - */ - public byte[] getIcon() { - return Resources.getImage(Resources.SSH_LOGO); - } - -// -// public void setContactGroup(ContactGroup contactGroup) -// { -// this.contactGroup = contactGroup; -// } -// -// public ContactGroup getContactGroup() -// { -// return this.contactGroup; -// } - - /** - * Sets the UserName of the dialog - * - * @param userName to be associated - */ - public void setUserNameField(String userName) { - this.userNameField.setText(userName); - } - - /** - * Sets the Password of the dialog - * - * @param password to be associated - */ - public void setPasswordField(String password) { - this.passwordField.setText(password); - } - - /** - * Return the hostname - * - * @return the hostname - */ - public String getHostName() { - return this.machineIDField.getText(); - } - - /** - * Return the username - * - * @return the username - */ - public String getUserName() { - return this.userNameField.getText(); - } - - /** - * Return the password - * - * @return the password in a clear form - */ - public String getPassword() { - return this.passwordField.getText(); - } - - /** - * Return the terminal type - * - * @return the terminal type - */ - public String getTerminalType() { - return this.terminalTypeField.getText(); - } - - /** - * Return the port - * - * @return the port value - */ - public int getPort() { - return Integer.parseInt(this.portField.getText().trim()); - } - - /** - * Return the update interval - * - * @return the update interval - */ - public int getUpdateInterval() { - return Integer.parseInt(String.valueOf(this.updateTimer.getValue())); - } - - /** - * Sets the HostName of the dialog - * - * @param hostName to be associated - */ - public void setHostNameField(String hostName) { - this.machineIDField.setText(hostName); - } - - /** - * Sets the Terminal Type of the dialog - * - * @param termType to be associated - */ - public void setTerminalType(String termType) { - this.terminalTypeField.setText(termType); - } - - /** - * Sets the Update Interval of the dialog - * - * @param interval to be associated - */ - public void setUpdateInterval(int interval) { - this.updateTimer.setValue(interval); - } - - /** - * Sets the Port of the dialog - * - * @param port to be associated - */ - public void setPort(String port) { - this.portField.setText(port); - } - - @Override - protected void close(boolean isEscaped) - { - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHFileTransferDaemon.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHFileTransferDaemon.java deleted file mode 100644 index 3b522ed..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHFileTransferDaemon.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.io.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.Logger; - -import com.jcraft.jsch.*; - -/** - * @author Shobhit Jindal - */ -public class SSHFileTransferDaemon - extends Thread -{ - private static final Logger logger = - Logger.getLogger(SSHFileTransferDaemon .class); - - /** - * The contact of the remote machine - */ - private ContactSSH sshContact; - - /** - * The currently valid ssh protocol provider - */ - private ProtocolProviderServiceSSHImpl ppService; - - /** - * JSch Channel to be used for file transfer - */ - private Channel fileTransferChannel; - - /** - * The identifier for the Input Stream associated with SCP Channel - */ - private InputStream scpInputStream = null; - - /** - * The identifier for the Output Stream associated with SCP Channel - */ - private OutputStream scpOutputStream = null; - - /** - * Identifier of local file - */ - private String localPath; - - /** - * Identifier of remote file - */ - private String remotePath; - - /** - * File to be uploaded or saved - */ - private File file; - - /** - * The file input stream associated with the file to be uploaded - */ - private FileInputStream fileInputStream; - - /** - * The file output stream associated with the file to be uploaded - */ - private FileOutputStream fileOutputStream; - - /** - * The boolean which determines whether we are uploading or downloading - * files - */ - private boolean uploadFile; - - /** - * The currently valid ssh persistent presence operation set - */ - private OperationSetPersistentPresenceSSHImpl opSetPersPresence = null; - - /** - * The currently valid ssh instant messaging operation set - */ - private OperationSetBasicInstantMessagingSSHImpl instantMessaging = null; - - /** - * Creates a new instance of SSHFileTransferDaemon - * - * - * @param sshContact The contact of the remote machine - * @param ppService The current ssh protocol provider - */ - public SSHFileTransferDaemon( - ContactSSH sshContact, - ProtocolProviderServiceSSHImpl ppService) - { - super(); - this.sshContact = sshContact; - this.opSetPersPresence = (OperationSetPersistentPresenceSSHImpl) - ppService.getOperationSet(OperationSetPersistentPresence.class); - this.instantMessaging = (OperationSetBasicInstantMessagingSSHImpl) - ppService.getOperationSet( - OperationSetBasicInstantMessaging.class); - this.ppService = ppService; - } - - /** - * This method is called when file is to be transfered from local machine - * to remote machine - * - * @param remotePath - the identifier for the remote file - * @param localPath - the identifier for the local file - */ - public void uploadFile( - String remotePath, - String localPath) - { - this.uploadFile = true; - this.remotePath = remotePath; - this.localPath = localPath; - - file = new File(localPath); - - start(); - } - - /** - * This method is called when a file is to be downloaded from remote machine - * to local machine - * - * @param remotePath - the identifier for the remote file - * @param localPath - the identifier for the local file - */ - public void downloadFile( - String remotePath, - String localPath) - { - this.uploadFile = false; - this.remotePath = remotePath; - this.localPath = localPath; - - file = new File(localPath); - - start(); - } - - /** - * Background thread for the file transfer - */ - @Override - public void run() - { - //oldStatus to be resumed earlier - PresenceStatus oldStatus = sshContact.getPresenceStatus(); - - opSetPersPresence.changeContactPresenceStatus( - sshContact, - SSHStatusEnum.CONNECTING); - - try - { - //create a new JSch session if current is invalid - if( !ppService.isSessionValid(sshContact)) - ppService.createSSHSessionAndLogin(sshContact); - - fileTransferChannel = sshContact.getSSHSession() - .openChannel("exec"); - String command; - - // -p = Preserves modification times, access times, and modes from - // the original file - if(uploadFile) - command = "scp -p -t " + remotePath; - else - command = "scp -f " + remotePath; - - //the command to be executed on the remote terminal - ((ChannelExec)fileTransferChannel).setCommand(command); - - scpInputStream = fileTransferChannel.getInputStream(); - scpOutputStream = fileTransferChannel.getOutputStream(); - - fileTransferChannel.connect(); - - //file transfer is setup - opSetPersPresence.changeContactPresenceStatus( - sshContact, - SSHStatusEnum.FILE_TRANSFER); - - if(uploadFile) - { - instantMessaging.deliverMessage( - instantMessaging.createMessage( - "Uploading " + file.getName() + " to server"), - sshContact); - - upload(); - } - else - { - instantMessaging.deliverMessage( - instantMessaging.createMessage( - "Downloading " + file.getName() + " from server"), - sshContact); - - download(); - } - - } - catch(Exception ex) - { - //presently errors(any type) are directly logged directly in chat - instantMessaging.deliverMessage( - instantMessaging.createMessage(ex.getMessage()), - sshContact); - - logger.error(ex.getMessage()); - - try - { - if(fileInputStream!=null) - { - fileInputStream.close(); - } - - if(fileOutputStream!=null) - { - fileOutputStream.close(); - } - } - catch(Exception e) - {} - } - - // restore old status - opSetPersPresence.changeContactPresenceStatus( - sshContact, - oldStatus); - } - - /** - * Check for error in reading stream of remote machine - * - * @return 0 for success, 1 for error, 2 for fatal error, -1 otherwise - * @throws IOException when the network goes down - */ - private int checkAck(InputStream inputStream) - throws IOException - { - int result = inputStream.read(); - - // read error message - if(result==1 || result==2) - { - StringBuffer buffer = new StringBuffer(); - - int ch; - - do - { - //read a line of message - ch = inputStream.read(); - buffer.append((char)ch); - - }while(ch != '\n'); - - ProtocolProviderServiceSSHImpl - .getUIService() - .getPopupDialog() - .showMessagePopupDialog( - buffer.toString(), - "File Transfer Error: " - + sshContact.getDisplayName(), - PopupDialog.ERROR_MESSAGE); - - logger.error(buffer.toString()); - } - - return result; - } - - /** - * Uploads the file to the remote server - * - * @throws IOException when the network goes down - * @throws OperationFailedException when server behaves unexpectedly - */ - private void upload() - throws IOException, - OperationFailedException - { - fileInputStream = new FileInputStream(file); - - byte[] buffer = new byte[1024]; - int result, bytesRead; - - if( (result = checkAck(scpInputStream)) !=0) - throw new OperationFailedException("Error in Ack", result); - - // send "C0644 filesize filename", where filename should not include '/' - long filesize= file.length(); - String command = "C0644 " + filesize + " "; - -// if(lfile.lastIndexOf('/')>0) -// { -// command+=lfile.substring(lfile.lastIndexOf('/')+1); -// } -// else -// { -// command+=lfile; -// } - - command += file.getName() + "\n"; - if (logger.isTraceEnabled()) - logger.trace(command); - scpOutputStream.write(command.getBytes()); - scpOutputStream.flush(); - - if( (result = checkAck(scpInputStream)) !=0) - throw new OperationFailedException("Error in Ack", result); - - while(true) - { - bytesRead = fileInputStream.read(buffer, 0, buffer.length); - if(bytesRead <= 0) - break; - - scpOutputStream.write(buffer, 0, bytesRead); //out.flush(); - } - fileInputStream.close(); - fileInputStream = null; - - // send '\0' - buffer[0]=0; scpOutputStream.write(buffer, 0, 1); - scpOutputStream.flush(); - - if( (result = checkAck(scpInputStream)) !=0) - throw new OperationFailedException("Error in Ack", result); - - scpInputStream.close(); - scpOutputStream.close(); - - fileTransferChannel.disconnect(); - - instantMessaging.deliverMessage( - instantMessaging.createMessage(file.getName() - + " uploaded to Server"), - sshContact); - } - - /** - * Downloads a file from the remote machine - * - * @throws IOException when the network goes down - * @throws OperationFailedException when server behaves unexpectedly - */ - private void download() - throws IOException, - OperationFailedException - { - fileOutputStream = new FileOutputStream(file); - - int result; - - byte[] buffer = new byte[1024]; - - // send '\0' - buffer[0]=0; - - scpOutputStream.write(buffer, 0, 1); - scpOutputStream.flush(); - - int ch = checkAck(scpInputStream); - - if(ch!='C') - { - throw new OperationFailedException("Invalid reply from server", 12); - } - - // read '0644 ' - scpInputStream.read(buffer, 0, 5); - - long filesize=0L; - while(true) - { - if(scpInputStream.read(buffer, 0, 1) < 0) - { - // error - break; - } - if(buffer[0]==' ')break; - filesize=filesize*10L+buffer[0]-'0'; - } - - String file=null; - for(int i=0;true;i++) - { - scpInputStream.read(buffer, i, 1); - if(buffer[i]==(byte)0x0a) - { - file=new String(buffer, 0, i); - break; - } - } - - //System.out.println("filesize="+filesize+", file="+file); - - // send '\0' - buffer[0]=0; - scpOutputStream.write(buffer, 0, 1); - scpOutputStream.flush(); - - // read a content of lfile - int foo; - while(true) - { - if(buffer.length 0) - - do - { - // store the responses in a buffer - storeMessage(replyBuffer); - - Thread.sleep(250); - - bytesAvailable = shellInputStream.available(); - - }while(bytesAvailable > 0 && bufferCount<16384); - - message = replyBuffer.toString(); - - if(sshContact.isCommandSent()) - { - // if the response is as a result of a command sent - sshContact.setMessageType( - ContactSSH.CONVERSATION_MESSAGE_RECEIVED); - - message = message.substring(message.indexOf('\n') + 1); - - sshContact.setCommandSent(false); - } - else - { - // server sent an asynchronous message to the terminal - // display it as a system message - sshContact.setMessageType( - ContactSSH.SYSTEM_MESSAGE_RECEIVED); - - //popup disabled -// JOptionPane.showMessageDialog( -// null, -// message, -// "Message from " + sshContact.getDisplayName(), -// JOptionPane.INFORMATION_MESSAGE); - } - - instantMessaging.deliverMessage( - instantMessaging.createMessage(message), - sshContact); - - replyBuffer.delete(0, replyBuffer.length()); - - }while(isActive); - } - catch(Exception ex) - { - ex.printStackTrace(); - } - } - - /** - * Stores the response from server in a temporary buffer - * the bytes available are determined before the function is called - * - * @param replyBuffer to store the response from server - * - * @throws IOException if the network goes down - */ - private void storeMessage(StringBuffer replyBuffer) throws IOException - { - do - { - buf = (char)shellInputStream.read(); - -// System.out.println(String.valueOf(buf)+ " " + (int)buf); - - replyBuffer.append(String.valueOf(buf)); - -// logger.debug(shellReader.readLine()); - - bufferCount++; - - bytesAvailable--; - - }while(bytesAvailable>0 && bufferCount<32700); - } - - public void isActive(boolean isActive) - { - this.isActive = isActive; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHStatusEnum.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHStatusEnum.java deleted file mode 100644 index 0877399..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHStatusEnum.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.ssh; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * An implementation of PresenceStatus that enumerates all states that - * a SSH contact can fall into. - * - * @author Shobhit Jindal - */ -public class SSHStatusEnum - extends PresenceStatus -{ - - /** - * Indicates an Offline status or status with 0 connectivity. - */ - public static final SSHStatusEnum OFFLINE - = new SSHStatusEnum( - 0, - "Offline", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.OFFLINE_STATUS_ICON")); - - /** - * The Not Available status. Indicates that the user has connectivity - * but might not be able to immediately act (i.e. even less immediately - * than when in an Away status ;-P ) upon initiation of communication. - * - */ - public static final SSHStatusEnum NOT_AVAILABLE - = new SSHStatusEnum( - 35, - "Not Available", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.NA_STATUS_ICON")); - - /** - * The Connecting status. Indicate that the user is connecting to remote - * server - */ - public static final SSHStatusEnum CONNECTING - = new SSHStatusEnum( - 55, - "Connecting", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.CONNECTING_ICON")); - - /** - * The Online status. Indicate that the user is able and willing to - * communicate. - */ - public static final SSHStatusEnum ONLINE - = new SSHStatusEnum( - 65, - "Online", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.SSH_16x16")); - - - /** - * The Connecting status. Indicate that the user is connecting to remote - * server - */ - public static final SSHStatusEnum CONNECTED - = new SSHStatusEnum( - 70, - "Connecting", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.CONNECTED_ICON")); - - /** - * The File Transfer status. Indicate that the user is transfering a file - * to/from a remote server - */ - public static final SSHStatusEnum FILE_TRANSFER - = new SSHStatusEnum( - 75, - "Transfering File", - ProtocolIconSSHImpl - .getImageInBytes("service.protocol.ssh.FILE_TRANSFER_ICON")); - - /** - * Initialize the list of supported status states. - */ - private static List supportedStatusSet = new LinkedList(); - static - { - supportedStatusSet.add(OFFLINE); -// supportedStatusSet.add(NOT_AVAILABLE); - supportedStatusSet.add(ONLINE); -// supportedStatusSet.add(CONNECTING); - } - - /** - * Creates an instance of SSHPresneceStatus with the - * specified parameters. - * @param status the connectivity level of the new presence status instance - * @param statusName the name of the presence status. - * @param statusIcon the icon associated with this status - */ - private SSHStatusEnum(int status, - String statusName, - byte[] statusIcon) - { - super(status, statusName, statusIcon); - } - - /** - * Returns an iterator over all status instances supproted by the ssh - * provider. - * @return an Iterator over all status instances supported by the - * ssh provider. - */ - static Iterator supportedStatusSet() - { - return supportedStatusSet.iterator(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/SSHUserInfo.java b/src/net/java/sip/communicator/impl/protocol/ssh/SSHUserInfo.java deleted file mode 100644 index 082b05f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/SSHUserInfo.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.impl.protocol.ssh; - -import javax.swing.*; - -import com.jcraft.jsch.*; - -/** - * SSHUserInfo passes authentication details to JSch SSH Stack - * - * @author Shobhit Jindal - */ -class SSHUserInfo - implements UserInfo, - UIKeyboardInteractive -{ - /** - * The Contact of the remote machine - */ - private ContactSSH sshContact; - - /** - * Identifier for failure of authentication - * more explanation below in promptPassword function - */ - private boolean failedOnce = false; - - /** - * Password field for requesting auth details from user - */ - JTextField passwordField=new JPasswordField(20); - - /** - * Creates a UserInfo instance - * - * @param sshContact the contact concerned - */ - SSHUserInfo(ContactSSH sshContact) - { - this.sshContact = sshContact; - } - - /** - * Returns the password of account associated with this contact - * - * @return the password of account associated with this contact - */ - public String getPassword() - { - return sshContact.getPassword(); - } - - /** - * Prompt for accepting the cipher information of the remote server - * - * @param str the string to display - * - * @return the user's answer - */ - public boolean promptYesNo(String str) - { - Object[] options={ "yes", "no" }; - int foo=JOptionPane.showOptionDialog(null, - str, - "Warning", - JOptionPane.DEFAULT_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, options, options[0]); - return foo==0; - } - - /** - * Passphrase authentication presently not implemented - * - * @return null - */ - public String getPassphrase() - { return null; } - - /** - * Passphrase authentication presently not implemented - * - * @return true - */ - public boolean promptPassphrase(String message) - { return true; } - - /** - * Asks user to re-enter password information in case of an auth failure - * - * @param message the message to display - * - * @return the user's answer - */ - public boolean promptPassword(String message) - { - /** - * Auth always fails for the first time for Redhat based machines. - * Trying again with the same password - */ - if(!failedOnce) - { - failedOnce = true; - return true; - } - - Object[] ob={passwordField}; - int result=JOptionPane.showConfirmDialog(null, ob, "Auth Failed: " - + message, - JOptionPane.OK_CANCEL_OPTION); - - if(result==JOptionPane.OK_OPTION) - { - sshContact.setPassword(passwordField.getText()); - return true; - } - - return false; - } - - /** - * Shows a message from server - * - * @param message The message to display - */ - public void showMessage(String message) - { - JOptionPane.showMessageDialog(null, message); - } - - /** - * Keyboard Interactive Auth - not implemented - */ - public String[] promptKeyboardInteractive( - String destination, - String name, - String instruction, - String[] prompt, - boolean[] echo) - { - String response[] = new String[prompt.length]; - response[0] = sshContact.getPassword(); - return response; - } - - -} diff --git a/src/net/java/sip/communicator/impl/protocol/ssh/ssh.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/ssh/ssh.provider.manifest.mf deleted file mode 100644 index eb9472f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/ssh/ssh.provider.manifest.mf +++ /dev/null @@ -1,20 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.impl.protocol.ssh.SSHActivator -Bundle-Name: SSH Protocol Provider -Bundle-Description: A bundle providing support for the SSH protocol. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.protocol.ssh -Import-Package: org.osgi.framework, - javax.crypto, - javax.crypto.interfaces, - javax.crypto.spec, - javax.swing, - javax.swing.border, - javax.swing.text, - org.jitsi.service.configuration, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/sshaccregwizz/FirstWizardPage.java deleted file mode 100644 index f553815..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/FirstWizardPage.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sshaccregwizz; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.impl.protocol.ssh.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * The FirstWizardPage is the page, where user could enter the user ID - * and the password of the account. - * - * @author Shobhit Jindal - */ -public class FirstWizardPage - extends TransparentPanel - implements WizardPage, DocumentListener -{ - private static final long serialVersionUID = 8576006544813706541L; - - public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier"; - - private JPanel accountPanel = new TransparentPanel(new BorderLayout(10, 10)); - - private JPanel labelsPanel = new TransparentPanel(); - - private JPanel valuesPanel = new TransparentPanel(); - - private JLabel accountID - = new JLabel(Resources.getString("plugin.sshaccregwizz.USERNAME")); - - private JLabel identityFile - = new JLabel(Resources.getString("plugin.sshaccregwizz.IDENTITY_FILE")); - - private JLabel knownHostsFile - = new JLabel(Resources.getString("plugin.sshaccregwizz.KNOWN_HOSTS")); - - private JPanel emptyPanel1 = new TransparentPanel(); - - private JPanel emptyPanel2 = new TransparentPanel(); - - private JPanel emptyPanel3 = new TransparentPanel(); - - private JPanel emptyPanel4 = new TransparentPanel(); - - private JPanel emptyPanel5 = new TransparentPanel(); - - private JPanel emptyPanel6 = new TransparentPanel(); - - private JPanel emptyPanel7 = new TransparentPanel(); - - private JPanel emptyPanel8 = new TransparentPanel(); - - private JPanel emptyPanel9 = new TransparentPanel(); - - private JTextField userIDField = new TrimTextField(); - - private JTextField identityFileField = new JTextField( - Resources.getString("plugin.sshaccregwizz.OPTIONAL")); - - private JButton identityFileButton = new JButton( - Resources.getString("service.gui.BROWSE")); - - private SipCommFileChooser identityFileChooser; - - private JPanel identityFilePanel = new TransparentPanel(); - - private JTextField knownHostsFileField = new JTextField( - Resources.getString("plugin.sshaccregwizz.KNOWN_HOSTS")); - - private JButton knownHostsFileButton = new JButton( - Resources.getString("service.gui.BROWSE")); - - private SipCommFileChooser knownHostsFileChooser; - - private JPanel knownHostsFilePanel = new TransparentPanel(); - - private JPanel mainPanel = new TransparentPanel(); - - private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER; - - private SSHAccountRegistration registration = null; - - private WizardContainer wizardContainer; - - private boolean isCommitted = false; - - /** - * Creates an instance of FirstWizardPage. - * @param registration the SSHAccountRegistration, where - * all data through the wizard are stored - * @param wizardContainer the wizardContainer, where this page will - * be added - */ - public FirstWizardPage(SSHAccountRegistration registration, - WizardContainer wizardContainer) - { - - super(new BorderLayout()); - - this.wizardContainer = wizardContainer; - - this.registration = registration; - - this.setPreferredSize(new Dimension(300, 150)); - - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - - identityFileField.setEditable(false); - - knownHostsFileField.setEditable(false); - - //identityFileChooser.setFileHidingEnabled(false); - - //knownHostsFileChooser.setFileHidingEnabled(false); - - this.init(); - - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.labelsPanel.setLayout(new BoxLayout(labelsPanel, - BoxLayout.Y_AXIS)); - - this.valuesPanel.setLayout(new BoxLayout(valuesPanel, - BoxLayout.Y_AXIS)); - - this.identityFilePanel.setLayout(new BoxLayout(identityFilePanel, - BoxLayout.X_AXIS)); - - this.knownHostsFilePanel.setLayout(new BoxLayout(knownHostsFilePanel, - BoxLayout.X_AXIS)); - } - - /** - * Initializes all panels, buttons, etc. - */ - private void init() - { - this.mainPanel.setOpaque(false); - this.labelsPanel.setOpaque(false); - this.valuesPanel.setOpaque(false); - this.accountPanel.setOpaque(false); - this.identityFilePanel.setOpaque(false); - this.knownHostsFilePanel.setOpaque(false); - this.emptyPanel1.setOpaque(false); - this.emptyPanel2.setOpaque(false); - this.emptyPanel3.setOpaque(false); - this.emptyPanel4.setOpaque(false); - this.emptyPanel5.setOpaque(false); - this.emptyPanel6.setOpaque(false); - this.emptyPanel7.setOpaque(false); - this.emptyPanel8.setOpaque(false); - this.emptyPanel9.setOpaque(false); - - this.userIDField.getDocument().addDocumentListener(this); - - /* - * Following empty panels cover the space needed between key labels - * WRT Height 2 key lables = 1 text field - */ - this.emptyPanel1.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel2.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel3.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel4.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel5.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel6.setMaximumSize(new Dimension(40, 35)); - this.emptyPanel7.setMaximumSize(new Dimension(40, 35)); - - identityFilePanel.add(identityFileField); - identityFilePanel.add(identityFileButton); - - knownHostsFilePanel.add(knownHostsFileField); - knownHostsFilePanel.add(knownHostsFileButton); - - labelsPanel.add(emptyPanel1); - labelsPanel.add(accountID); - labelsPanel.add(emptyPanel2); - labelsPanel.add(emptyPanel3); - labelsPanel.add(identityFile); - labelsPanel.add(emptyPanel4); - labelsPanel.add(emptyPanel5); - labelsPanel.add(knownHostsFile); - labelsPanel.add(emptyPanel6); - - valuesPanel.add(userIDField); - valuesPanel.add(emptyPanel7); - valuesPanel.add(identityFilePanel); - valuesPanel.add(emptyPanel8); - valuesPanel.add(knownHostsFilePanel); - labelsPanel.add(emptyPanel9); - - accountPanel.add(labelsPanel, BorderLayout.WEST); - accountPanel.add(valuesPanel, BorderLayout.CENTER); - - identityFileButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent event) - { - identityFileChooser = GenericFileDialog.create( - null, "Select Identify File", - SipCommFileChooser.LOAD_FILE_OPERATION); - File f = identityFileChooser.getFileFromDialog(); - - if(f != null) - identityFileField.setText(f.getAbsolutePath()); - } - } - ); - - knownHostsFileButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent event) - { - knownHostsFileChooser = GenericFileDialog.create( - null, "Select SSH Known Hosts File", - SipCommFileChooser.LOAD_FILE_OPERATION); - File f = knownHostsFileChooser.getFileFromDialog(); - - if(f != null) - knownHostsFileField.setText(f.getAbsolutePath()); - } - } - ); - - accountPanel.setBorder(BorderFactory - .createTitledBorder(Resources.getString( - "plugin.sshaccregwizz.ACCOUNT_DETAILS"))); - - this.add(accountPanel, BorderLayout.NORTH); - } - - /** - * Fills the Account ID, Identity File and Known Hosts File fields in this - * panel with the data coming from the given protocolProvider. - * - * @param protocolProvider The ProtocolProviderService to load the - * data from. - */ - public void loadAccount(ProtocolProviderService protocolProvider) - { - if (!(protocolProvider instanceof ProtocolProviderServiceSSHImpl)) - throw new ClassCastException("protocolProvider"); - - AccountID accountID = protocolProvider.getAccountID(); - - String identityFile = - accountID - .getAccountPropertyString(ProtocolProviderFactorySSH.IDENTITY_FILE); - - String knownHostsFile = - accountID - .getAccountPropertyString(ProtocolProviderFactorySSH.KNOWN_HOSTS_FILE); - - this.userIDField.setText(accountID.getUserID()); - - this.identityFileField.setText(identityFile); - - this.knownHostsFileField.setText(knownHostsFile); - } - - /** - * Implements the WizardPage.getIdentifier to return - * this page identifier. - * - * @return the Identifier of the first page in this wizard. - */ - public Object getIdentifier() - { - return FIRST_PAGE_IDENTIFIER; - } - - /** - * Implements the WizardPage.getNextPageIdentifier to return - * the next page identifier - the summary page. - * - * @return the identifier of the page following this one. - */ - public Object getNextPageIdentifier() - { - return nextPageIdentifier; - } - - /** - * Implements the WizardPage.getBackPageIdentifier to return - * the back identifier. In this case it's null because this is the first - * wizard page. - * - * @return the identifier of the previous wizard page - */ - public Object getBackPageIdentifier() - { - return null; - } - - /** - * Implements the WizardPage.getWizardForm to return - * this panel. - * - * @return the component to be displayed in this wizard page. - */ - public Object getWizardForm() - { - return this; - } - - /** - * Before this page is displayed enables or disables the "Next" wizard - * button according to whether the UserID field is empty. - */ - public void pageShowing() - { - this.setNextButtonAccordingToUserID(); - } - - /** - * Saves the user input when the "Next" wizard buttons is clicked. - */ - public void commitPage() - { - String userID = userIDField.getText(); - - if(userID == null || userID.trim().length() == 0) - throw new IllegalStateException("No user ID provided."); - - registration.setUserID(userID); - registration.setIdentityFile(identityFileField.getText()); - registration.setKnownHostsFile(knownHostsFileField.getText()); - - nextPageIdentifier = SUMMARY_PAGE_IDENTIFIER; - - isCommitted = true; - } - - /** - * Enables or disables the "Next" wizard button according to whether the - * User ID field is empty. - */ - private void setNextButtonAccordingToUserID() - { - if (userIDField.getText() == null || userIDField.getText() - .equals("")) - { - wizardContainer.setNextFinishButtonEnabled(false); - } - else - { - wizardContainer.setNextFinishButtonEnabled(true); - } - } - - /** - * Handles the DocumentEvent triggered when user types in the - * User ID field. Enables or disables the "Next" wizard button according to - * whether the User ID field is empty. - * - * @param event the event containing the update. - */ - public void insertUpdate(DocumentEvent event) - { - this.setNextButtonAccordingToUserID(); - } - - /** - * Handles the DocumentEvent triggered when user deletes letters - * from the UserID field. Enables or disables the "Next" wizard button - * according to whether the UserID field is empty. - * - * @param event the event containing the update. - */ - public void removeUpdate(DocumentEvent event) - { - this.setNextButtonAccordingToUserID(); - } - - public void changedUpdate(DocumentEvent event) - { - } - - public void pageHiding() - { - } - - public void pageShown() - { - } - - public void pageBack() - { - } - - public Object getSimpleForm() - { - return accountPanel; - } - - public boolean isCommitted() - { - return isCommitted; - } -} diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/Resources.java b/src/net/java/sip/communicator/plugin/sshaccregwizz/Resources.java deleted file mode 100644 index 3c2f462..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/Resources.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sshaccregwizz; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author Shobhit Jindal - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - public static ImageID SSH_LOGO - = new ImageID("service.protocol.ssh.SSH_16x16"); - - public static ImageID PAGE_IMAGE - = new ImageID("service.protocol.ssh.SSH_64x64"); - - /** - * Returns an internationalized string corresponding to the given key. - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImage(ImageID imageID) - { - return getResources().getImageInBytes(imageID.getId()); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(SSHAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccRegWizzActivator.java deleted file mode 100644 index 459fb39..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccRegWizzActivator.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sshaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Registers the SSHAccountRegistrationWizard in the UI Service. - * - * @author Shobhit Jindal - */ -public class SSHAccRegWizzActivator - implements BundleActivator -{ - private static final Logger logger = - Logger.getLogger(SSHAccRegWizzActivator.class); - - /** - * A currently valid bundle context. - */ - public static BundleContext bundleContext; - - private static WizardContainer wizardContainer; - - private static SSHAccountRegistrationWizard sshWizard; - - private static UIService uiService; - - /** - * Starts this bundle. - * @param bc the currently valid BundleContext. - */ - public void start(BundleContext bc) - { - if (logger.isInfoEnabled()) - logger.info("Loading ssh account wizard."); - - bundleContext = bc; - - ServiceReference uiServiceRef = bundleContext - .getServiceReference(UIService.class.getName()); - - uiService = (UIService) bundleContext - .getService(uiServiceRef); - - wizardContainer = uiService.getAccountRegWizardContainer(); - - sshWizard - = new SSHAccountRegistrationWizard(wizardContainer); - - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.SSH); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - sshWizard, - containerFilter); - - if (logger.isInfoEnabled()) - logger.info("SSH account registration wizard [STARTED]."); - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param bundleContext The execution context of the bundle being stopped. - */ - public void stop(BundleContext bundleContext) throws Exception - { - } - - /** - * Returns the ProtocolProviderFactory for the SSH protocol. - * @return the ProtocolProviderFactory for the SSH protocol - */ - public static ProtocolProviderFactory getSSHProtocolProviderFactory() - { - ServiceReference[] serRefs = null; - String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL + "=SSH)"; - - try - { - serRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), - osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error(ex); - } - - return - (serRefs == null) - ? null - : (ProtocolProviderFactory) - bundleContext.getService(serRefs[0]); - } - - /** - * Returns the bundleContext that we received when we were started. - * - * @return a currently valid instance of a bundleContext. - */ - public BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } -} diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistration.java b/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistration.java deleted file mode 100644 index 023ffee..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistration.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.plugin.sshaccregwizz; - -/** - * The SSHAccountRegistration is used to store all user input data - * through the SSHAccountRegistrationWizard. - * - * @author Shobhit Jindal - */ -public class SSHAccountRegistration -{ - private String accountID; - - /** - * Stored public keys[SSH] of remote server - */ - private String knownHostsFile; - - /** - * Identity file is a private[default] key of the user which is one - * of the methods of authentication - */ - private String identityFile; - - /** - * Returns the Account ID of the ssh registration account. - * @return accountID - */ - public String getAccountID() - { - return accountID; - } - - /** - * Sets the Account ID of the ssh registration account. - * - * @param accountID the accountID of the ssh registration account. - */ - public void setUserID(String accountID) - { - this.accountID = accountID; - } - - /** - * Returns the Known Hosts of the ssh registration account. - * - * @return knownHostsFile - */ - public String getKnownHostsFile() - { - return knownHostsFile; - } - - /** - * Sets the Known Hosts of the ssh registration account. - * - * @param knownHostsFile - */ - public void setKnownHostsFile(String knownHostsFile) - { - this.knownHostsFile = knownHostsFile; - } - - /** - * Returns the Identity File of the ssh registration account. - * - * @return identityFile - */ - public String getIdentityFile() - { - return identityFile; - } - - /** - * Sets the Machine Port of the ssh registration account. - * - * @param machinePort - */ - public void setIdentityFile(String machinePort) - { - this.identityFile = machinePort; - } -} - diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistrationWizard.java deleted file mode 100644 index 77c398b..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/SSHAccountRegistrationWizard.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.java.sip.communicator.plugin.sshaccregwizz; - -import java.awt.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.ssh.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The SSHAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the SSH protocol. It allows - * the user to create and configure a new SSH account. - * - * @author Shobhit Jindal - */ -public class SSHAccountRegistrationWizard - extends DesktopAccountRegistrationWizard -{ - private final Logger logger - = Logger.getLogger(SSHAccountRegistrationWizard.class); - - /** - * The first page of the ssh account registration wizard. - */ - private FirstWizardPage firstWizardPage; - - /** - * The object that we use to store details on an account that we will be - * creating. - */ - private SSHAccountRegistration registration - = new SSHAccountRegistration(); - - private ProtocolProviderService protocolProvider; - - /** - * Creates an instance of SSHAccountRegistrationWizard. - * @param wizardContainer the wizard container, where this wizard - * is added - */ - public SSHAccountRegistrationWizard(WizardContainer wizardContainer) - { - setWizardContainer(wizardContainer); - - wizardContainer.setFinishButtonText( - Resources.getString("service.gui.SIGN_IN")); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return Resources.getImage(Resources.SSH_LOGO); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage - * method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Resources.getImage(Resources.PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString("plugin.sshaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources.getString("plugin.sshaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - java.util.List pages = new ArrayList(); - firstWizardPage - = new FirstWizardPage(registration, getWizardContainer()); - - pages.add(firstWizardPage); - - return pages.iterator(); - } - - /** - * Returns the set of data that user has entered through this wizard. - * @return Iterator - */ - @Override - public Iterator> getSummary() { - Hashtable summaryTable - = new Hashtable(); - - /* - * Hashtable arranges the entries alphabetically so the order - * of appearance is - * - Computer Name / IP - * - Port - * - User ID - */ - summaryTable.put("Account ID", registration.getAccountID()); - summaryTable.put("Known Hosts", registration.getKnownHostsFile()); - summaryTable.put("Identity", registration.getIdentityFile()); - - return summaryTable.entrySet().iterator(); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin() - throws OperationFailedException - { - firstWizardPage.commitPage(); - - return signin(registration.getAccountID(), null); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @param userName the user name to sign in with - * @param password the password to sign in with - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin(String userName, String password) - throws OperationFailedException - { - ProtocolProviderFactory factory - = SSHAccRegWizzActivator.getSSHProtocolProviderFactory(); - - return this.installAccount( factory, - userName); - } - - /** - * Creates an account for the given Account ID, Identity File and Known - * Hosts File - * - * @param providerFactory the ProtocolProviderFactory which will create - * the account - * @param user the user identifier - * @return the ProtocolProviderService for the new account. - */ - public ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, - String user) - throws OperationFailedException - { - Hashtable accountProperties - = new Hashtable(); - - accountProperties.put(ProtocolProviderFactory.ACCOUNT_ICON_PATH, - "resources/images/protocol/ssh/ssh32x32.png"); - - accountProperties.put( - ProtocolProviderFactory.NO_PASSWORD_REQUIRED, - new Boolean(true).toString()); - - accountProperties.put(ProtocolProviderFactorySSHImpl.IDENTITY_FILE, - registration.getIdentityFile()); - - accountProperties.put(ProtocolProviderFactorySSHImpl.KNOWN_HOSTS_FILE, - String.valueOf(registration.getKnownHostsFile())); - - try - { - AccountID accountID = providerFactory.installAccount( - user, accountProperties); - - ServiceReference serRef = providerFactory - .getProviderForAccount(accountID); - - protocolProvider = (ProtocolProviderService) - SSHAccRegWizzActivator.bundleContext - .getService(serRef); - } - catch (IllegalStateException exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Account already exists.", - OperationFailedException.IDENTIFICATION_CONFLICT); - } - catch (Exception exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Failed to add account", - OperationFailedException.GENERAL_ERROR); - } - - return protocolProvider; - } - - /** - * Fills the UserID and Password fields in this panel with the data comming - * from the given protocolProvider. - * @param protocolProvider The ProtocolProviderService to load the - * data from. - */ - @Override - public void loadAccount(ProtocolProviderService protocolProvider) - { - this.protocolProvider = protocolProvider; - - this.firstWizardPage.loadAccount(protocolProvider); - - setModification(true); - } - - /** - * Returns the size of this wizard. - * @return the size of this wizard - */ - @Override - public Dimension getSize() - { - return new Dimension(600, 500); - } - - /** - * Returns the identifier of the first account registration wizard page. - * This method is meant to be used by the wizard container to determine, - * which is the first page to show to the user. - * - * @return the identifier of the first account registration wizard page - */ - @Override - public Object getFirstPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - @Override - public Object getLastPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return null; - } - - /** - * Indicates whether this wizard enables the simple "sign in" form shown - * when the user opens the application for the first time. The simple - * "sign in" form allows user to configure her account in one click, just - * specifying her username and password and leaving any other configuration - * as by default. - * @return true if the simple "Sign in" form is enabled or - * false otherwise. - */ - @Override - public boolean isSimpleFormEnabled() - { - return false; - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - firstWizardPage = new FirstWizardPage(registration, getWizardContainer()); - return firstWizardPage.getSimpleForm(); - } -} diff --git a/src/net/java/sip/communicator/plugin/sshaccregwizz/sshaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/sshaccregwizz/sshaccregwizz.manifest.mf deleted file mode 100644 index c48b853..0000000 --- a/src/net/java/sip/communicator/plugin/sshaccregwizz/sshaccregwizz.manifest.mf +++ /dev/null @@ -1,32 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.sshaccregwizz.SSHAccRegWizzActivator -Bundle-Name: SSH account registration wizard -Bundle-Description: SSH account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.sshaccregwizz -Import-Package: org.osgi.framework, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - javax.swing, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.accessibility, - javax.swing.plaf, - javax.swing.plaf.metal, - javax.swing.plaf.basic, - javax.imageio, - javax.swing.filechooser, - javax.swing.tree, - javax.swing.undo, - javax.swing.border -- cgit v1.1 From 6ebeb9189f578eee78d3a930a2bbb67bdfe9b0e6 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:25:05 +0200 Subject: Remove unused hexdump library --- .classpath | 1 - build.xml | 1 - 2 files changed, 2 deletions(-) diff --git a/.classpath b/.classpath index 25f00a5..41c12ba 100755 --- a/.classpath +++ b/.classpath @@ -27,7 +27,6 @@ - diff --git a/build.xml b/build.xml index b363fb5..e1cedc2 100644 --- a/build.xml +++ b/build.xml @@ -2787,7 +2787,6 @@ org.bouncycastle.util"/> prefix="net/java/sip/communicator/service/sysactivity" /> - -- cgit v1.1 From 6025f550337161468e295e30f72aeb50feee2f95 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:25:27 +0200 Subject: Remove outdated IntelliJ project files --- jitsi.eml | 192 -------------------------------------- jitsi.iml | 14 --- jitsi.ipr | 314 -------------------------------------------------------------- 3 files changed, 520 deletions(-) delete mode 100755 jitsi.eml delete mode 100644 jitsi.iml delete mode 100644 jitsi.ipr diff --git a/jitsi.eml b/jitsi.eml deleted file mode 100755 index 7a448a0..0000000 --- a/jitsi.eml +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jitsi.iml b/jitsi.iml deleted file mode 100644 index ca72718..0000000 --- a/jitsi.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/jitsi.ipr b/jitsi.ipr deleted file mode 100644 index 91fd90e..0000000 --- a/jitsi.ipr +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - http://www.w3.org/1999/xhtml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.1 From 0a8554fde0ce069129267fef1b9d1bce5de2cf3c Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:26:15 +0200 Subject: Remove removed jdic leftover --- lib/native/windows/IeEmbed.exe | Bin 61440 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/native/windows/IeEmbed.exe diff --git a/lib/native/windows/IeEmbed.exe b/lib/native/windows/IeEmbed.exe deleted file mode 100644 index 1e83d21..0000000 Binary files a/lib/native/windows/IeEmbed.exe and /dev/null differ -- cgit v1.1 From 8eaa64562c7c75e6bb7dae422132dc98ab2d96ea Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:27:27 +0200 Subject: Simplify unit test reporting Xalan is part of the JRE, no need to distribute it. --- build.xml | 27 ++++++--------------------- lib/installer-exclude/xalan-2.6.0.jar.ant | Bin 2633763 -> 0 bytes 2 files changed, 6 insertions(+), 21 deletions(-) delete mode 100755 lib/installer-exclude/xalan-2.6.0.jar.ant diff --git a/build.xml b/build.xml index e1cedc2..93df63d 100644 --- a/build.xml +++ b/build.xml @@ -673,13 +673,12 @@ see its "Build Successful" output line as users might confuse it for a general build success while this might not be the case.--> - - - + + + + + + @@ -696,20 +695,6 @@ - - - - - - - - - - - diff --git a/lib/installer-exclude/xalan-2.6.0.jar.ant b/lib/installer-exclude/xalan-2.6.0.jar.ant deleted file mode 100755 index c307040..0000000 Binary files a/lib/installer-exclude/xalan-2.6.0.jar.ant and /dev/null differ -- cgit v1.1 From 6bc41324be7700b407e5805cc1174ea34aeb8d52 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:27:44 +0200 Subject: Remover former dev.java.net website --- www/alm-process/snippets/page.xml | 2 -- www/images/pixel.gif | Bin 43 -> 0 bytes www/images/sc_logo136x169.jpg | Bin 7271 -> 0 bytes www/images/sc_logo136x169.png | Bin 12664 -> 0 bytes www/images/sc_logo139x208.white.png | Bin 14906 -> 0 bytes www/images/sc_logo50x62.jpg | Bin 3510 -> 0 bytes www/images/sc_logo50x62.png | Bin 3602 -> 0 bytes www/images/sip-communicator.jpg | Bin 25052 -> 0 bytes www/images/sip-communicator.logo.jpg | Bin 3903 -> 0 bytes www/images/sip-communicator.logo.png | Bin 18199 -> 0 bytes www/index-jn.html | 2 -- www/index.html | 14 -------------- www/role-approval.policy | 20 -------------------- www/sc_logo16x16.png | Bin 791 -> 0 bytes 14 files changed, 38 deletions(-) delete mode 100644 www/alm-process/snippets/page.xml delete mode 100644 www/images/pixel.gif delete mode 100644 www/images/sc_logo136x169.jpg delete mode 100644 www/images/sc_logo136x169.png delete mode 100644 www/images/sc_logo139x208.white.png delete mode 100644 www/images/sc_logo50x62.jpg delete mode 100644 www/images/sc_logo50x62.png delete mode 100644 www/images/sip-communicator.jpg delete mode 100644 www/images/sip-communicator.logo.jpg delete mode 100644 www/images/sip-communicator.logo.png delete mode 100644 www/index-jn.html delete mode 100644 www/index.html delete mode 100644 www/role-approval.policy delete mode 100644 www/sc_logo16x16.png diff --git a/www/alm-process/snippets/page.xml b/www/alm-process/snippets/page.xml deleted file mode 100644 index 725def6..0000000 --- a/www/alm-process/snippets/page.xml +++ /dev/null @@ -1,2 +0,0 @@ - -index.htmlSubprojects diff --git a/www/images/pixel.gif b/www/images/pixel.gif deleted file mode 100644 index e565824..0000000 Binary files a/www/images/pixel.gif and /dev/null differ diff --git a/www/images/sc_logo136x169.jpg b/www/images/sc_logo136x169.jpg deleted file mode 100644 index c2373c7..0000000 Binary files a/www/images/sc_logo136x169.jpg and /dev/null differ diff --git a/www/images/sc_logo136x169.png b/www/images/sc_logo136x169.png deleted file mode 100644 index 10bd72a..0000000 Binary files a/www/images/sc_logo136x169.png and /dev/null differ diff --git a/www/images/sc_logo139x208.white.png b/www/images/sc_logo139x208.white.png deleted file mode 100644 index 28acc45..0000000 Binary files a/www/images/sc_logo139x208.white.png and /dev/null differ diff --git a/www/images/sc_logo50x62.jpg b/www/images/sc_logo50x62.jpg deleted file mode 100644 index 1da6246..0000000 Binary files a/www/images/sc_logo50x62.jpg and /dev/null differ diff --git a/www/images/sc_logo50x62.png b/www/images/sc_logo50x62.png deleted file mode 100644 index 0a393de..0000000 Binary files a/www/images/sc_logo50x62.png and /dev/null differ diff --git a/www/images/sip-communicator.jpg b/www/images/sip-communicator.jpg deleted file mode 100644 index fd88b68..0000000 Binary files a/www/images/sip-communicator.jpg and /dev/null differ diff --git a/www/images/sip-communicator.logo.jpg b/www/images/sip-communicator.logo.jpg deleted file mode 100644 index 0b9e450..0000000 Binary files a/www/images/sip-communicator.logo.jpg and /dev/null differ diff --git a/www/images/sip-communicator.logo.png b/www/images/sip-communicator.logo.png deleted file mode 100644 index f2ae776..0000000 Binary files a/www/images/sip-communicator.logo.png and /dev/null differ diff --git a/www/index-jn.html b/www/index-jn.html deleted file mode 100644 index 37b5586..0000000 --- a/www/index-jn.html +++ /dev/null @@ -1,2 +0,0 @@ - -

    sip-communicator.org
    SIP Communicator
    Open Source VoIP & IM


    SIP Communicator is an audio/video Internet phone and instant messenger that support some of the most popular instant messaging and telephony protocols such as SIP, Jabber, AIM/ICQ, MSN and soon others like Yahoo and IRC.

    SIP Communicator is completely Open Source / Free Software, and is freely available under the terms of the GNU Lesser General Public License.

    RESOURCES: The SIP Communicator FAQ can usually answer most questions. You can also ask on the users mailing list, or at the irc channel #sip-communicator at irc.freenode.net.

    Note: Right now SIP Communicator is still a work in progress and as such is still unstable. If you would like to help or follow project progress check the Project Roadmap or join our Mailing Lists. You can also have a look at the SIP Communicator screenshots

    Thanks for your patience and continuing support!
    The SIP Communicator team

    diff --git a/www/index.html b/www/index.html deleted file mode 100644 index 4897c3e..0000000 --- a/www/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - Jitsi - The most advanced open source communicator - - - -

    - -

    - - diff --git a/www/role-approval.policy b/www/role-approval.policy deleted file mode 100644 index 8395eb5..0000000 --- a/www/role-approval.policy +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - diff --git a/www/sc_logo16x16.png b/www/sc_logo16x16.png deleted file mode 100644 index 6c8ba4d..0000000 Binary files a/www/sc_logo16x16.png and /dev/null differ -- cgit v1.1 From feee8eda79f401efab3df9edf44896ac586f4582 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:35:35 +0200 Subject: Remove profiler4j It doesn't work anymore and there are other, non-invasive tools available. --- .classpath | 1 - build.xml | 104 +-------------------- lib/installer-exclude/jcommon-1.0.0.jar | Bin 294514 -> 0 bytes lib/installer-exclude/jdom.jar | Bin 153253 -> 0 bytes lib/installer-exclude/jfreechart-1.0.1.jar | Bin 1075691 -> 0 bytes lib/installer-exclude/p4j-exclusions.txt | 26 ------ lib/installer-exclude/profiler4j-1.0-beta3-SC.jar | Bin 603634 -> 0 bytes .../plugin/profiler4j/ProfilerActivator.java | 78 ---------------- .../communicator/plugin/profiler4j/Resources.java | 58 ------------ .../plugin/profiler4j/SettingsWindowMenuEntry.java | 72 -------------- .../plugin/profiler4j/profiler4j.manifest.mf | 24 ----- 11 files changed, 4 insertions(+), 359 deletions(-) delete mode 100644 lib/installer-exclude/jcommon-1.0.0.jar delete mode 100644 lib/installer-exclude/jdom.jar delete mode 100644 lib/installer-exclude/jfreechart-1.0.1.jar delete mode 100644 lib/installer-exclude/p4j-exclusions.txt delete mode 100644 lib/installer-exclude/profiler4j-1.0-beta3-SC.jar delete mode 100644 src/net/java/sip/communicator/plugin/profiler4j/ProfilerActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/profiler4j/Resources.java delete mode 100644 src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java delete mode 100644 src/net/java/sip/communicator/plugin/profiler4j/profiler4j.manifest.mf diff --git a/.classpath b/.classpath index 41c12ba..6de35ee 100755 --- a/.classpath +++ b/.classpath @@ -60,7 +60,6 @@ - diff --git a/build.xml b/build.xml index 93df63d..6aa28ed 100644 --- a/build.xml +++ b/build.xml @@ -206,10 +206,6 @@ - - - - @@ -811,20 +807,14 @@ - - - - - + @@ -918,93 +908,22 @@ - - - - -
    - - - - - - - - - - - - - - This target can only run inside the NetBeans IDE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2185,21 +2104,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - toolsMenuFilter = - new Hashtable(); - toolsMenuFilter.put(Container.CONTAINER_ID, - Container.CONTAINER_TOOLS_MENU.getID()); - - menuRegistration = bc.registerService( - PluginComponentFactory.class.getName(), - new PluginComponentFactory(Container.CONTAINER_TOOLS_MENU) - { - @Override - protected PluginComponent getPluginInstance() - { - return new SettingsWindowMenuEntry( - Container.CONTAINER_TOOLS_MENU, this); - } - }, - toolsMenuFilter); - - if (logger.isInfoEnabled()) - logger.info("PROFILER4J [REGISTERED]"); - - } - - public void stop(BundleContext bc) throws Exception { - if (menuRegistration != null) - { - menuRegistration.unregister(); - if (logger.isInfoEnabled()) - logger.info("PROFILER4J [UNREGISTERED]"); - } - } - -} diff --git a/src/net/java/sip/communicator/plugin/profiler4j/Resources.java b/src/net/java/sip/communicator/plugin/profiler4j/Resources.java deleted file mode 100644 index c69a8a5..0000000 --- a/src/net/java/sip/communicator/plugin/profiler4j/Resources.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.profiler4j; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Messages class manages the access to the internationalization properties - * files. - * - * @author Vladimir Skarupelov; - */ -public class Resources -{ - private static ResourceManagementService resourcesService = null; - - /** - * Returns an internationalized string corresponding to the given key. - * - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(ProfilerActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java b/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java deleted file mode 100644 index 1e59786..0000000 --- a/src/net/java/sip/communicator/plugin/profiler4j/SettingsWindowMenuEntry.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.profiler4j; - -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.service.gui.*; -import net.sf.profiler4j.console.*; - -/** - * Menu entry for the profiler plug-in - * - * @author Vladimir Skarupelov - */ -public class SettingsWindowMenuEntry - extends AbstractPluginComponent -{ - private static final String PROFILER_NAME = "plugin.profiler.PLUGIN_NAME"; - private JMenuItem settingsMenuEntry; - - public SettingsWindowMenuEntry(Container container, - PluginComponentFactory parentFactory) - { - super(container, parentFactory); - - settingsMenuEntry = new JMenuItem(Resources.getString( PROFILER_NAME )); - settingsMenuEntry.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - Prefs prefs = new Prefs(); - - System.setProperty("swing.aatext", - String.valueOf(prefs.isAntialiasing())); - - final Console app = new Console(prefs); - app.connect(); - MainFrame f = new MainFrame(app); - app.setMainFrame(f); - f.pack(); - f.setVisible(true); - } - }); - } - - public Object getComponent() - { - return settingsMenuEntry; - } - - public String getName() - { - return Resources.getString( PROFILER_NAME ); - } -} diff --git a/src/net/java/sip/communicator/plugin/profiler4j/profiler4j.manifest.mf b/src/net/java/sip/communicator/plugin/profiler4j/profiler4j.manifest.mf deleted file mode 100644 index 9e3ebf4..0000000 --- a/src/net/java/sip/communicator/plugin/profiler4j/profiler4j.manifest.mf +++ /dev/null @@ -1,24 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.profiler4j.ProfilerActivator -Bundle-Name: Integrated profiler plugin -Bundle-Description: A bundle that provides profile cpu and memory of the running app. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.profiler4j -Import-Package: org.apache.commons.logging, - org.osgi.framework, - org.xml.sax, - org.xml.sax.ext, - org.xml.sax.helpers, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.gui, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.util, - javax.swing, - javax.swing.border, - javax.swing.event, - javax.swing.filechooser, - javax.swing.table, - javax.swing.text, - javax.swing.tree, - javax.xml.parsers -- cgit v1.1 From 4d6e58c20066632c2593f52c40a6f1b5279c6115 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 19:45:11 +0200 Subject: Remove jfontchooser It wasn't used anywhere anymore. --- .classpath | 1 - build.xml | 11 +--------- lib/felix.client.run.properties | 1 - lib/felix.unit.test.properties | 1 - lib/installer-exclude/jfontchooser-1.0.5.jar | Bin 16703 -> 0 bytes lib/installer-exclude/jfontchooser.manifest.mf | 10 --------- nbproject/project.xml | 2 +- resources/install/build.xml | 23 --------------------- resources/install/debian/README.embedded-libraries | 4 ---- .../sip/communicator/impl/gui/swing.ui.manifest.mf | 1 - 10 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 lib/installer-exclude/jfontchooser-1.0.5.jar delete mode 100644 lib/installer-exclude/jfontchooser.manifest.mf diff --git a/.classpath b/.classpath index 6de35ee..605ad0c 100755 --- a/.classpath +++ b/.classpath @@ -39,7 +39,6 @@
    - diff --git a/build.xml b/build.xml index 6aa28ed..d205e16 100644 --- a/build.xml +++ b/build.xml @@ -977,7 +977,7 @@ bundle-plugin-blf, bundle-plugin-contactinfo,bundle-plugin-chatalerter, bundle-keybindings, bundle-plugin-keybindingChooser,bundle-plugin-globalproxyconfig, - bundle-jfontchooserlib,bundle-update,bundle-plugin-update, + bundle-update,bundle-plugin-update, bundle-plugin-simpleaccreg,bundle-plugin-generalconfig, bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service, bundle-argdelegation,bundle-zrtp4j,bundle-json, @@ -2221,15 +2221,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index e36bf54..59951c3 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -108,7 +108,6 @@ felix.auto.start.40= \ reference:file:sc-bundles/jna.jar \ reference:file:sc-bundles/jna-platform.jar \ reference:file:sc-bundles/provdisc.jar \ - reference:file:sc-bundles/jfontchooserlib.jar \ reference:file:sc-bundles/netaddr.jar \ reference:file:sc-bundles/sysactivitynotifications.jar \ reference:file:sc-bundles/browserlauncher.jar \ diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 5db3a83..8c7cfa4 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -109,7 +109,6 @@ felix.auto.start.40= \ reference:file:sc-bundles/argdelegation-service.jar \ reference:file:sc-bundles/resourcemanager.jar \ reference:file:sc-bundles/defaultresources.jar \ - reference:file:sc-bundles/jfontchooserlib.jar \ reference:file:sc-bundles/version-impl.jar \ reference:file:sc-bundles/keybindings.jar \ reference:file:sc-bundles/jna.jar \ diff --git a/lib/installer-exclude/jfontchooser-1.0.5.jar b/lib/installer-exclude/jfontchooser-1.0.5.jar deleted file mode 100644 index 769c8f1..0000000 Binary files a/lib/installer-exclude/jfontchooser-1.0.5.jar and /dev/null differ diff --git a/lib/installer-exclude/jfontchooser.manifest.mf b/lib/installer-exclude/jfontchooser.manifest.mf deleted file mode 100644 index 6ad2b73..0000000 --- a/lib/installer-exclude/jfontchooser.manifest.mf +++ /dev/null @@ -1,10 +0,0 @@ -Bundle-Name: JFontChooser -Bundle-Description: A library containing a Java Font Chooser -Bundle-Vendor: sip-communicator.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: say.swing -Import-Package: javax.swing, - javax.swing.border, - javax.swing.event, - javax.swing.text -Export-Package: say.swing diff --git a/nbproject/project.xml b/nbproject/project.xml index 939c825..ba9c55e 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jfontchooser-1.0.5.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 diff --git a/resources/install/build.xml b/resources/install/build.xml index 52ff7b5..9de80cf 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -2763,10 +2763,6 @@ - - - - - - - - - - - - - Date: Sat, 4 Jun 2016 19:52:54 +0200 Subject: Remove zeroconf protocol --- build.xml | 20 - .../impl/protocol/zeroconf/BonjourService.java | 706 ----- .../impl/protocol/zeroconf/ClientThread.java | 499 ---- .../zeroconf/ContactGroupZeroconfImpl.java | 595 ---- .../protocol/zeroconf/ContactZeroconfImpl.java | 468 --- .../protocol/zeroconf/MessageZeroconfImpl.java | 234 -- ...rationSetBasicInstantMessagingZeroconfImpl.java | 192 -- ...OperationSetPersistentPresenceZeroconfImpl.java | 852 ------ ...perationSetTypingNotificationsZeroconfImpl.java | 83 - .../zeroconf/ProtocolIconZeroconfImpl.java | 189 -- .../ProtocolProviderFactoryZeroconfImpl.java | 120 - .../ProtocolProviderServiceZeroconfImpl.java | 302 -- .../impl/protocol/zeroconf/ZeroconfAccountID.java | 96 - .../impl/protocol/zeroconf/ZeroconfActivator.java | 132 - .../impl/protocol/zeroconf/ZeroconfStatusEnum.java | 136 - .../impl/protocol/zeroconf/jmdns/DNSCache.java | 294 -- .../impl/protocol/zeroconf/jmdns/DNSConstants.java | 160 - .../impl/protocol/zeroconf/jmdns/DNSEntry.java | 183 -- .../impl/protocol/zeroconf/jmdns/DNSIncoming.java | 524 ---- .../impl/protocol/zeroconf/jmdns/DNSListener.java | 39 - .../impl/protocol/zeroconf/jmdns/DNSOutgoing.java | 405 --- .../impl/protocol/zeroconf/jmdns/DNSQuestion.java | 68 - .../impl/protocol/zeroconf/jmdns/DNSRecord.java | 796 ----- .../impl/protocol/zeroconf/jmdns/DNSState.java | 139 - .../impl/protocol/zeroconf/jmdns/HostInfo.java | 173 -- .../impl/protocol/zeroconf/jmdns/JmDNS.java | 3048 -------------------- .../impl/protocol/zeroconf/jmdns/ServiceEvent.java | 124 - .../impl/protocol/zeroconf/jmdns/ServiceInfo.java | 785 ----- .../protocol/zeroconf/jmdns/ServiceListener.java | 57 - .../zeroconf/jmdns/ServiceTypeListener.java | 37 - .../zeroconf/zeroconf.provider.manifest.mf | 12 - .../plugin/zeroconfaccregwizz/FirstWizardPage.java | 368 --- .../plugin/zeroconfaccregwizz/Resources.java | 74 - .../ZeroconfAccRegWizzActivator.java | 147 - .../ZeroconfAccountRegistration.java | 130 - .../ZeroconfAccountRegistrationWizard.java | 392 --- .../zeroconfaccregwizz.manifest.mf | 32 - 37 files changed, 12611 deletions(-) delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/BonjourService.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ClientThread.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ContactGroupZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ContactZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/MessageZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetBasicInstantMessagingZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetPersistentPresenceZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetTypingNotificationsZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolIconZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderFactoryZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderServiceZeroconfImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfAccountID.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfActivator.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfStatusEnum.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSCache.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSConstants.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSEntry.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSIncoming.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSListener.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSOutgoing.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSQuestion.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSRecord.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSState.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/HostInfo.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/JmDNS.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceEvent.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceInfo.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceListener.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceTypeListener.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/zeroconf/zeroconf.provider.manifest.mf delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/FirstWizardPage.java delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/Resources.java delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistration.java delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/zeroconfaccregwizz/zeroconfaccregwizz.manifest.mf diff --git a/build.xml b/build.xml index d205e16..a86f850 100644 --- a/build.xml +++ b/build.xml @@ -1934,26 +1934,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - - - - - diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/BonjourService.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/BonjourService.java deleted file mode 100644 index 8258da7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/BonjourService.java +++ /dev/null @@ -1,706 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.io.*; -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.impl.protocol.zeroconf.jmdns.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Class dealing with JmDNS and treating all the - * incoming connections on the bonjour port - * @author Christian Vincenot - */ -public class BonjourService extends Thread - implements ServiceListener, - DNSListener -{ - private static final Logger logger = - Logger.getLogger(BonjourService.class); - - private int port = 5298; - private ServerSocket sock = null; - private String id = null; - private JmDNS jmdns=null; - private final Map props = new Hashtable(); - private ServiceInfo service = null; - private boolean dead = false; - - private final List contacts - = new Vector(); - - private ProtocolProviderServiceZeroconfImpl pps; - OperationSetPersistentPresenceZeroconfImpl opSetPersPresence; - - private ZeroconfAccountID acc; - - /* Should maybe better get the status directly from OperationSetPresence */ - private PresenceStatus status = ZeroconfStatusEnum.OFFLINE; - - /** - * Returns the corresponding ProtocolProviderService - * @return corresponding ProtocolProviderService - */ - public ProtocolProviderServiceZeroconfImpl getPPS() - { - return pps; - } - - /** - * Returns the id of this service. - * @return returns the id of this service. - */ - String getID() - { - return id; - } - - /** - * Creates a new instance of the Bonjour service thread - * @param port TCP Port number on which to try to start the Bonjour service - * @param pps ProtocolProviderService instance - * which is creating this BonjourService - */ - public BonjourService(int port, - ProtocolProviderServiceZeroconfImpl pps) - { - this.acc = (ZeroconfAccountID) pps.getAccountID(); - this.port = port; - this.id = acc.getUserID(); - this.pps = pps; - - opSetPersPresence = - (OperationSetPersistentPresenceZeroconfImpl) pps - .getOperationSet(OperationSetPersistentPresence.class); - - // Gaim - props.put("1st", (acc.getFirst() == null)? "":acc.getFirst()); - props.put("email", (acc.getMail() == null)? "":acc.getMail()); - props.put("jid", this.id); - props.put("last", (acc.getLast() == null)?"":acc.getLast()); - props.put("msg", opSetPersPresence.getCurrentStatusMessage()); - props.put("status", "avail"); - - //iChat - props.put("phsh","000"); - //props.put("status","avail"); - //props.put("port.p2pj", "5298"); - props.put("vc", "C!"); - //props.put("1st", "John"); - props.put("txtvers","1"); - - //XEP-0174 (Final paper) - props.put("ext",""); - props.put("nick", (acc.getFirst() == null)? this.id:acc.getFirst()); - props.put("ver", "1"); - props.put("node", "SIP Communicator"); - - //Ours - props.put("client", "SIP Communicator"); - - changeStatus(opSetPersPresence.getPresenceStatus()); - - sock = createSocket(port); - if (sock == null) - return; - - port = sock.getLocalPort(); - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: ServerSocket bound to port "+port); - - props.put("port.p2pj", Integer.toString(port)); - this.setDaemon(true); - this.start(); - } - - /* TODO: Better exception checking to avoid sudden exit and bonjour - * service shutdown */ - - /** - * Walk? - */ - @Override - public void run() - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Bonjour Service Thread up and running!"); - - /* Put jmDNS in DEBUD Mode : - * Following verbosity levels can be chosen : - * "INFO" , "WARNING", "SEVERE", "ALL", "FINE", "FINER", "FINEST", etc - */ - //System.setProperty("jmdns.debug", "0"); - - while (dead == false) - { - if (sock == null || sock.isClosed()) - { - sock = createSocket(port); - /* What should we do now? TEMPORARY: shutdown()*/ - if (sock == null) shutdown(); - port = sock.getLocalPort(); - props.put("port.p2pj", Integer.toString(port)); - //TODO: update JmDNS in case the port had to be changed! - } - try - { - Socket connection = sock.accept(); - ContactZeroconfImpl contact = getContact(null, - connection.getInetAddress()); - /*if (status.equals(ZeroconfStatusEnum.OFFLINE) - || status.equals(ZeroconfStatusEnum.INVISIBLE) */ - if (dead == true) break; - - if ((contact == null) - || (contact.getClientThread() != null)) - { - if (contact == null) - logger.error("ZEROCONF: Connexion from " - + "unknown contact [" - + connection.getInetAddress() - +"]. REJECTING!"); - else if (contact.getClientThread() == null) - logger.error("ZEROCONF: Redundant chat " - + "channel [" - + contact - +"]. REJECTING!"); - connection.close(); - } - else new ClientThread(connection, this); - } - catch(Exception e) - { - logger.error(e); - } - } - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Going Offline - " - +"BonjourService Thread exiting!"); - } - - /** - * Might be used for shutdown... - */ - public void shutdown() - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Shutdown!"); - - dead = true; - try - { sock.close(); } - catch (Exception ex) - { logger.error(ex); } - - changeStatus(ZeroconfStatusEnum.OFFLINE); - if(jmdns != null) - jmdns.close(); - } - - private ServerSocket createSocket(int port) - { - ServerSocket sock=null; - try - { - sock = new ServerSocket(port); - } - catch(Exception e) - { - logger.error("ZEROCONF: Couldn't bind socket to port " - +port+"! Switching to an other port..."); - try - { - sock = new ServerSocket(0); - } - catch (IOException ex) - { - logger.error("ZEROCONF: FATAL ERROR => " - +"Couldn't bind to a port!!", ex); - } - } - - return sock; - } - - /** - * Changes the status of the local user. - * @param stat New presence status - */ - public void changeStatus(PresenceStatus stat) - { - /* [old_status == new_status ?] => NOP */ - if (stat.equals(status)) - return; - - /* [new_status == OFFLINE ?] => clean up everything */ - if (stat.equals(ZeroconfStatusEnum.OFFLINE)) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Going OFFLINE"); - //jmdns.unregisterAllServices(); - jmdns.removeServiceListener("_presence._tcp.local.", this); - jmdns.close(); - jmdns=null; - //dead = true; - - // Erase all contacts by putting them OFFLINE - opSetPersPresence.changePresenceStatusForAllContacts( - opSetPersPresence.getServerStoredContactListRoot(), stat); - - try - { - sleep(1000); - } catch (InterruptedException ex) - { - logger.error(ex); - } - } - - /* [old_status == OFFLINE ?] => register service */ - else if (status.equals(ZeroconfStatusEnum.OFFLINE)) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Getting out of OFFLINE state"); - props.put("status", stat.getStatusName()); - service = new ServiceInfo("_presence._tcp.local.", id, - port, 0, 0, props); - - try - { - jmdns = new JmDNS(); - jmdns.registerServiceType("_presence._tcp.local."); - jmdns.addServiceListener("_presence._tcp.local.", this); - jmdns.registerService(service); - - /* In case the ID had to be changed */ - id = service.getName(); - } - catch (Exception ex) - { logger.error(ex); } - - //dead = false; - - /* Normal status change */ - } - else - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF : Changing status"); - - props.put("status", stat.getStatusName()); - - /* FIXME: Not totally race condition free since the 3 calls aren't - * atomic, but that's not really critical since there's little - * change chance of concurrent local contact change, and this - * wouldn't have big consequences. - */ - ServiceInfo info = - jmdns.getLocalService(id.toLowerCase()+"._presence._tcp.local."); - if (info == null) - logger.error("ZEROCONF/JMDNS: PROBLEM GETTING " - +"LOCAL SERVICEINFO !!"); - - byte[] old = info.getTextBytes(); - info.setProps(props); - jmdns.updateInfos(info, old); - } - - status = stat; - } - - private class AddThread extends Thread - { - private String type, name; - public AddThread(String type, String name) - { - this.setDaemon(true); - this.type = type; - this.name = name; - this.start(); - } - - @Override - public void run() - { - ServiceInfo service = null; - while ((service == null) && (dead == false) - && !status.equals(ZeroconfStatusEnum.OFFLINE)) - { - service = jmdns.getServiceInfo(type, name, 10000); - if (service == null) - logger.error("BONJOUR: ERROR - Service Info of " - + name +" not found in cache!!"); - try - { - sleep(2); - } - catch (InterruptedException ex) - { - logger.error(ex); - } - } - if ((dead == false) && !status.equals(ZeroconfStatusEnum.OFFLINE)) - jmdns.requestServiceInfo(type, name); - //} else handleResolvedService(name, type, service); - } - } - - /* Service Listener Implementation */ - - /** - * A service has been added. - * - * @param event The ServiceEvent providing the name and fully qualified type - * of the service. - */ - public void serviceAdded(ServiceEvent event) - { - /* WARNING: DONT PUT ANY BLOCKING CALLS OR FLAWED LOOPS IN THIS METHOD. - * JmDNS calls this method without creating a new thread, so if this - * method doesn't return, jmDNS will hang !! - */ - - String name = event.getName(); - String type = event.getType(); - - if (name.equals(id)) - return; - - if (logger.isDebugEnabled()) - logger.debug("BONJOUR: "+name - +"["+type+"] detected! Trying to get information..."); - try - { - sleep(2); - } - catch (InterruptedException ex) - { - logger.error(ex); - } - - jmdns.printServices(); - - new AddThread(type, name); - } - - - - /** - * A service has been removed. - * - * @param event The ServiceEvent providing the name and fully qualified type - * of the service. - */ - public void serviceRemoved(ServiceEvent event) - { - String name = event.getName(); - if (name.equals(id)) - return; - - ContactZeroconfImpl contact = getContact(name, null); - - if(contact == null) - return; - - opSetPersPresence.changePresenceStatusForContact(contact, - ZeroconfStatusEnum.OFFLINE); - if (logger.isDebugEnabled()) - logger.debug("BONJOUR: Received announcement that " - +name+" went offline!"); - - } - - /** - * A service has been resolved. Its details are now available in the - * ServiceInfo record. - * - * @param event The ServiceEvent providing the name, the fully qualified - * type of the service, and the service info record, - * or null if the service could not be resolved. - */ - public void serviceResolved(ServiceEvent event) - { - String contactID = event.getName(); - String type = event.getType(); - ServiceInfo info = event.getInfo(); - - if (logger.isDebugEnabled()) - logger.debug("BONJOUR: Information about " - +contactID+" discovered"); - - handleResolvedService(contactID, type, info); - } - - private void handleResolvedService(String contactID, - String type, - ServiceInfo info) - { - if (contactID.equals(id)) - return; - - if (info.getAddress().toString().length() > 15) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Temporarily ignoring IPv6 addresses!"); - return; - } - - ContactZeroconfImpl newFriend; - - synchronized(this) - { - if (getContact(contactID, info.getAddress()) != null) - { - if (logger.isDebugEnabled()) - logger.debug("Contact " - +contactID+" already in contact list! Skipping."); - return; - }; - if (logger.isDebugEnabled()) - logger.debug("ZEROCNF: ContactID " + contactID + - " Address " + info.getAddress()); - - if (logger.isDebugEnabled()) - logger.debug(" Address=>"+info.getAddress() - +":"+info.getPort()); - - for (Iterator names = info.getPropertyNames(); - names.hasNext();) - { - String prop = names.next(); - if (logger.isDebugEnabled()) - logger.debug(" "+prop+"=>" - +info.getPropertyString(prop)); - } - - /* Creating the contact */ - String name = info.getPropertyString("1st"); - if (info.getPropertyString("last") != null) - name += " "+ info.getPropertyString("last"); - - int port = Integer.valueOf( - info.getPropertyString("port.p2pj")).intValue(); - - if (port < 1) - { - logger.error("ZEROCONF: Flawed contact announced himself" - +"without necessary parameters : "+contactID); - return; - } - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Detected client "+name); - - newFriend = - opSetPersPresence.createVolatileContact( - contactID, this, name, - info.getAddress(), port); - } - /* Try to detect which client type it is */ - int clientType = ContactZeroconfImpl.XMPP; - if (info.getPropertyString("client") != null - && info.getPropertyString("client"). - compareToIgnoreCase("SIP Communicator") == 0) - clientType = ContactZeroconfImpl.SIPCOM; - - else if ((info.getPropertyString("jid") != null) - && (info.getPropertyString("node") == null)) - clientType = ContactZeroconfImpl.GAIM; - - else if (info.getPropertyString("jid") == null) - clientType = ContactZeroconfImpl.ICHAT; - - newFriend.setClientType(clientType); - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: CLIENT TYPE "+clientType); - - ZeroconfStatusEnum status = - ZeroconfStatusEnum.statusOf(info.getPropertyString("status")); - opSetPersPresence. - changePresenceStatusForContact(newFriend, - status == null?ZeroconfStatusEnum.ONLINE:status); - - // Listening for changes - jmdns.addListener(this, new DNSQuestion(info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_UNIQUE)); - } - - /** - * Callback called by JmDNS to inform the - * BonjourService of a potential status change of some contacts. - * @param jmdns JmDNS instance responsible for this - * @param now Timestamp - * @param record DNSRecord which changed - */ - public synchronized void updateRecord( JmDNS jmdns, - long now, - DNSRecord record) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF/JMDNS: Received record update for "+record); - - int clazz = record.getClazz(); - int type = record.getType(); - - /* Check the info returned by JmDNS since we can't really trust its - * filtering. */ - if (!(((type & DNSConstants.TYPE_TXT) != 0) && - ((clazz & DNSConstants.CLASS_IN) != 0) && - record.isUnique() && - record.getName().endsWith("_presence._tcp.local."))) - return; - - String name = record.getName().replaceAll("._presence._tcp.local.",""); - ContactZeroconfImpl contact; - - synchronized(this) - { - contact = getContact(name, null); - - if (contact == null) { //return; - logger.error("ZEROCONF: BUG in jmDNS => Received update without " - +"previous contact annoucement. Trying to add contact"); - new AddThread("_presence._tcp.local.", name); - return; - } - } - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: "+ name - + " changed status. Requesting fresh data!"); - - /* Since a record was updated, we can be sure that we can do a blocking - * getServiceInfo without risk. (Still, we use the method with timeout - * to avoid bad surprises). If some problems of status change refresh - * appear, we'll have to fall back on the method with callback as we've - * done for "ServiceAdded". - */ - - ServiceInfo info = jmdns.getServiceInfo("_presence._tcp.local.", name, - 1000); - if (info == null) - { - logger.error("ZEROCONF/JMDNS: Problem!! The service " - +"information was not in cache. See comment in " - +"BonjourService.java:updateRecord !!"); - return; - } - - /* Let's change what we can : status, message, etc */ - ZeroconfStatusEnum status = - ZeroconfStatusEnum.statusOf(info.getPropertyString("status")); - - opSetPersPresence. - changePresenceStatusForContact(contact, - status == null ? ZeroconfStatusEnum.ONLINE:status); - - } - - /** - * Returns an Iterator over all contacts. - * - * @return a java.util.Iterator over all contacts - */ - public Iterator contacts() - { - return contacts.iterator(); - } - - /** - * Adds a contact to the locally stored list of contacts - * @param contact Zeroconf Contact to add to the local list - */ - public void addContact(ContactZeroconfImpl contact) - { - if (contact == null) - throw new IllegalArgumentException("contact"); - - synchronized(contacts) - { - contacts.add(contact); - } - } - /** - * Returns the Contact with the specified identifier or IP address. - * - * @param id the identifier of the Contact we are - * looking for. - * @param ip the IP address of the Contact we are looking for. - * @return the Contact with the specified id or address. - */ - public ContactZeroconfImpl getContact(String id, InetAddress ip) - { - if (id == null && ip == null) return null; - - synchronized(contacts) - { - Iterator contactsIter = contacts(); - - while (contactsIter.hasNext()) - { - ContactZeroconfImpl contact = contactsIter.next(); - //System.out.println("ZEROCNF: Comparing "+id+ " "+ip+ - //" with "+ contact.getAddress()+ " " + contact.getIpAddress()); - if (((contact.getAddress().equals(id)) || (id == null)) - && ((contact.getIpAddress().equals(ip)) || (ip == null))) - return contact; - - } - } - //System.out.println("ZEROCNF: ERROR - " + - //"Couldn't find contact to get ["+id+" / "+ip+"]"); - return null; - } - - /** - * Removes the Contact with the specified identifier or IP address. - * - * - * @param id the identifier of the Contact we are - * looking for. - * @param ip the IP address of the Contact we are looking for. - */ - public void removeContact(String id, InetAddress ip) - { - synchronized(contacts) - { - Iterator contactsIter = contacts(); - while (contactsIter.hasNext()) - { - ContactZeroconfImpl contact = contactsIter.next(); - if (((contact.getAddress().equals(id)) || (id == null)) - &&((contact.getIpAddress().equals(ip)) || (ip == null))) - { - if (contact.getClientThread() != null) - contact.getClientThread().cleanThread(); - contacts.remove(contact); - return; - } - }; - } - logger.error( - "ZEROCONF: ERROR - Couldn't find contact to delete ["+id+" / "+ip+"]"); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ClientThread.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ClientThread.java deleted file mode 100644 index 4367eed..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ClientThread.java +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.io.*; -import java.net.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Class creating a thread responsible for handling the chat - * with the remote user on the other end of the socket - * - * @author Christian Vincenot - */ -public class ClientThread - extends Thread -{ - private static final Logger logger = Logger.getLogger(ClientThread.class); - - private OperationSetBasicInstantMessagingZeroconfImpl opSetBasicIM; - private OperationSetTypingNotificationsZeroconfImpl opSetTyping; - private Socket sock; - private InetAddress remoteIPAddress; - private OutputStream out; - private DataInputStream in; - private BonjourService bonjourService; - private ContactZeroconfImpl contact=null; - private boolean streamState = false; - - private String messagesQueue=null; - - /** - * Sets the contact with which we're chatting in this ClientThread - * @param contact Zeroconf contact with which we're chatting - */ - protected void setContact(ContactZeroconfImpl contact) - { - this.contact = contact; - } - - /** - * Set the stream as opened. This means that the - * conversation with the client is really opened - * from now on (the XML greetings are over) - */ - protected void setStreamOpen() - { - synchronized(this) - { - this.streamState = true; - } - } - - /** - * Says if the stream between the local user and the remote user - * is in an opened state (greetings are over and we can chat) - * @return Returns true if the stream is "opened" (ie, ready for chat) - */ - protected boolean isStreamOpened() - { - synchronized(this) - { - return this.streamState; - } - } - - /** - * Creates a new instance of ClientThread reponsible - * for handling the conversation with the remote user. - * @param sock Socket created for chatting - * @param bonjourService BonjourService which spawned this ClientThread - */ - public ClientThread(Socket sock, BonjourService bonjourService) - { - this.sock = sock; - this.remoteIPAddress = sock.getInetAddress(); - this.bonjourService = bonjourService; - this.opSetBasicIM = - (OperationSetBasicInstantMessagingZeroconfImpl) bonjourService - .getPPS().getOperationSet( - OperationSetBasicInstantMessaging.class); - - this.opSetTyping = - (OperationSetTypingNotificationsZeroconfImpl) bonjourService - .getPPS() - .getOperationSet(OperationSetTypingNotifications.class); - this.setDaemon(true); - - try - { - out = sock.getOutputStream(); - in = new DataInputStream(sock.getInputStream()); - } - catch (IOException e) - { - logger.error("Creating ClientThread: Couldn't get I/O for " - +"the connection", e); - //System.exit(1); - return; - } - - this.start(); - } - - /* - * Read a message from the socket. - * TODO: clean the code a bit and optimize it. - */ - private String readMessage() - { - String line; - byte[] bytes = new byte[10]; - - try - { - int i=0; - - while (i < 9) - { - i += in.read(bytes,0,9-i); - } - - line = new String(bytes); - bytes = new byte[1]; - if ((line.getBytes())[0] == '\n') - line = line.substring(1); - - if (line.startsWith("")) - || (line.endsWith("stream>"))) - return line; - } - } - else - { - while (true) - { - bytes[0] = in.readByte(); - line += new String(bytes); - if ( ">".compareTo(new String(bytes)) == 0 ) - return line; - } - } - } - catch (IOException e) - { - logger.error("Couldn't get I/O for the connection", e); - //System.exit(1); - } - - return null; - } - - /* - * Parse the payload and extract the information. - * TODO: If needed, fill in the remaining fields of MessageZeroconfImpl - * like the baloon icon color, color/size/font of the text. - */ - private MessageZeroconfImpl parseMessage(String str) - { - if (str.startsWith("")) - return new MessageZeroconfImpl - (null, null, MessageZeroconfImpl.STREAM_CLOSE); - - if ((str.indexOf("") > 0) && (str.indexOf("") < 0)) - return new MessageZeroconfImpl - (null, null, MessageZeroconfImpl.DELIVERED); - - if (!str.startsWith(".. - */ - - if ((str.indexOf("") < 0) || (str.indexOf("") < 0)) - return new MessageZeroconfImpl - (null, null, MessageZeroconfImpl.UNDEF); - - String temp = - str.substring(str.indexOf("")+6, str.indexOf("")); - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: received message ["+temp+"]"); - - int messageType = MessageZeroconfImpl.MESSAGE; - - if ((str.indexOf("") >= 0) && (str.indexOf("") >= 0)) - messageType = MessageZeroconfImpl.TYPING; - - MessageZeroconfImpl msg = - new MessageZeroconfImpl( - temp, - null, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, - messageType); - - return msg; - } - - private int handleMessage(MessageZeroconfImpl msg) - { - - switch(msg.getType()) - { - /* STREAM INIT */ - case MessageZeroconfImpl.STREAM_OPEN: - if (contact == null) - contact = bonjourService.getContact(null, remoteIPAddress); - if (!isStreamOpened()) - { - sendHello(); - setStreamOpen(); - } - if (messagesQueue != null) - { - write(messagesQueue); - messagesQueue = null; - } - break; - - /* ACK */ - case MessageZeroconfImpl.DELIVERED : break; - - /* NORMAL MESSAGE */ - case MessageZeroconfImpl.MESSAGE: - if (!isStreamOpened()) - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: client on the other side " - +"isn't polite (sending messages without " - +"saying hello :P"); - if (contact == null) - //TODO: Parse contact id to double-check - contact = bonjourService.getContact(null, remoteIPAddress); - - /* TODO: If we want to implement invisible status, we'll have to - * make this test less restrictive to handle messages from - * unannounced clients. - */ - if (contact == null) - { - logger.error("ZEROCONF: ERROR - Couldn't identify " - +"contact. Closing socket."); - return -1; - } - else if (contact.getClientThread() == null) - contact.setClientThread(this); - - opSetBasicIM.fireMessageReceived(msg, contact); - - opSetTyping.fireTypingNotificationsEvent(contact, - OperationSetTypingNotificationsZeroconfImpl.STATE_STOPPED); - break; - - case MessageZeroconfImpl.TYPING: - if (!isStreamOpened()) - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: client on the other side " - +"isn't polite (sending messages without " - +"saying hello :P"); - if (contact == null) - //TODO: Parse contact id to double-check - contact = bonjourService.getContact(null, remoteIPAddress); - opSetTyping.fireTypingNotificationsEvent(contact, - OperationSetTypingNotificationsZeroconfImpl.STATE_TYPING); - - /* TODO: code a private runnable class to be used as timeout - * to set the typing state to STATE_PAUSED when a few seconds - * without news have passed. - */ - - break; - - case MessageZeroconfImpl.STREAM_CLOSE: - sendBye(); - contact.setClientThread(null); - return 1; - - case MessageZeroconfImpl.UNDEF: - logger.error("ZEROCONF: received strange message. SKIPPING!"); - break; - } - - //System.out.println("RECEIVED MESSAGE "+ msg.getContent()+ - //" from "+contact.getAddress() + "!!!!!!!!!!!!!!"); - return 0; - } - - - private void write(String string) - { - //System.out.println("Writing " + string + "!!!!!!!!!"); - byte[] bytes = string.getBytes(); - try - { - out.write(bytes); - out.flush(); - } - catch (IOException e) - { - logger.error("Couldn't get I/O for the connection"); - if (contact != null) - { - contact.setClientThread(null); - } - - try - { - sock.close(); - } - catch (IOException ex) - { - logger.error(ex); - } - - } - } - - /** - * Say hello :) - */ - protected void sendHello() - { - switch(contact.getClientType()) - { - case ContactZeroconfImpl.GAIM: - case ContactZeroconfImpl.ICHAT: - case ContactZeroconfImpl.SIPCOM: - write(""); - write(""); - break; - case ContactZeroconfImpl.XMPP: - write("\n"); - break; - } - - /* Legacy: OLD XMPP (XEP-0174 Draft) */ - //write(""); - } - - private void sendBye() - { - write("\n"); - } - - private String toXHTML(MessageZeroconfImpl msg) - { - switch(contact.getClientType()) - { - case ContactZeroconfImpl.XMPP: - return new String("" - + ""+msg.getContent()+"" - + "\n"); - - case ContactZeroconfImpl.SIPCOM: - - case ContactZeroconfImpl.ICHAT: - return new String( - "" - + ""+msg.getContent()+"" - + "" - + "" - + "" - + msg.getContent() - + "" - + "" - + "" - + "" - + "" - + "" - + "" - + (msg.getType()==MessageZeroconfImpl.TYPING?"":"") - + "" - + ""); - - case ContactZeroconfImpl.GAIM: - default: - return new String( - ""+msg.getContent()+"" - + "" - + msg.getContent() - + "" - + (msg.getType()==MessageZeroconfImpl.TYPING?"":"") - + "\n"); - } - } - - - /** - * Send a message to the remote user - * @param msg Message to send - */ - public void sendMessage(MessageZeroconfImpl msg) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Sending messag [" - +msg.getContent()+"] to " - + contact.getDisplayName()); - if (!isStreamOpened()) - { - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Stream not opened... " - +"will send the message later"); - messagesQueue += toXHTML(msg); - } - else write(toXHTML(msg)); - } - - /** - * Walk? - */ - @Override - public void run() - { - if (logger.isDebugEnabled()) - logger.debug("Bonjour: NEW CONNEXION from " - + sock.getInetAddress().getCanonicalHostName() - +" / "+sock.getInetAddress().getHostAddress()); - String input; - MessageZeroconfImpl msg=null; - - - input = readMessage(); - msg = parseMessage(input); - - while (handleMessage(msg) == 0 && !sock.isClosed()) - { - input = readMessage(); - msg = parseMessage(input); - } - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF : OUT OF LOOP !! Closed chat."); - cleanThread(); - } - - /** - * Clean-up the thread to exit - */ - public void cleanThread() - { - /* I wonder if that's ok... */ - if (sock != null && sock.isClosed() == false) - { - sendBye(); - try - { - sock.close(); - } - catch (IOException ex) - { - logger.error(ex); - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactGroupZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactGroupZeroconfImpl.java deleted file mode 100644 index 568e087..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactGroupZeroconfImpl.java +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * A simple, straightforward implementation of a zeroconf ContactGroup. Since - * the Zeroconf protocol, we simply store all group details - * in class fields. You should know that when implementing a real protocol, - * the contact group implementation would rather encapsulate group objects from - * the protocol stack and group property values should be returned by consulting - * the encapsulated object. - * - * @author Christian Vincenot - * @author Maxime Catelin - * @author Jonathan Martin - */ -public class ContactGroupZeroconfImpl - implements ContactGroup -{ - - /** - * The name of this Zeroconf contact group. - */ - private String groupName = null; - - /** - * The list of this group's members. - */ - private Vector contacts = new Vector(); - - /** - * The list of sub groups belonging to this group. - */ - private Vector subGroups = new Vector(); - - /** - * The group that this group belongs to (or null if this is the root group). - */ - private ContactGroupZeroconfImpl parentGroup = null; - - /** - * Determines whether this group is really in the contact list or whether - * it is here only temporarily and will be gone next time we restart. - */ - private boolean isPersistent = false; - - /** - * The protocol provider that created us. - */ - private ProtocolProviderServiceZeroconfImpl parentProvider = null; - - /** - * Determines whether this group has been resolved on the server. - * Unresolved groups are groups that were available on previous runs and - * that the meta contact list has stored. During all next runs, when - * bootstrapping, the meta contact list would create these groups as - * unresolved. Once a protocol provider implementation confirms that the - * groups are still on the server, it would issue an event indicating that - * the groups are now resolved. - */ - private boolean isResolved = true; - - /** - * An id uniquely identifying the group. For many protocols this could be - * the group name itself. - */ - private String uid = null; - private static final String UID_SUFFIX = ".uid"; - - /** - * Creates a ContactGroupZeroconfImpl with the specified name. - * - * @param groupName the name of the group. - * @param parentProvider the protocol provider that created this group. - */ - public ContactGroupZeroconfImpl( - String groupName, - ProtocolProviderServiceZeroconfImpl parentProvider) - { - this.groupName = groupName; - this.uid = groupName + UID_SUFFIX; - this.parentProvider = parentProvider; - } - - /** - * Determines whether the group may contain subgroups or not. - * - * @return always true in this implementation. - */ - public boolean canContainSubgroups() - { - return true; - } - - /** - * Returns the protocol provider that this group belongs to. - * @return a regerence to the ProtocolProviderService instance that this - * ContactGroup belongs to. - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Returns an Iterator over all contacts, member of this - * ContactGroup. - * - * @return a java.util.Iterator over all contacts inside this - * ContactGroup - */ - public Iterator contacts() - { - return contacts.iterator(); - } - - /** - * Adds the specified contact to this group. - * @param contactToAdd the ContactZeroconfImpl to add to this group. - */ - public void addContact(ContactZeroconfImpl contactToAdd) - { - this.contacts.add(contactToAdd); - contactToAdd.setParentGroup(this); - } - - /** - * Returns the number of Contact members of this - * ContactGroup - * - * @return an int indicating the number of Contacts, members of - * this ContactGroup. - */ - public int countContacts() - { - return contacts.size(); - } - - /** - * Returns the number of subgroups contained by this - * ContactGroup. - * - * @return the number of subGroups currently added to this group. - */ - public int countSubgroups() - { - return subGroups.size(); - } - - /** - * Adds the specified contact group to the contained by this group. - * @param subgroup the ContactGroupZeroconfImpl to add as a - * subgroup to this group. - */ - public void addSubgroup(ContactGroupZeroconfImpl subgroup) - { - this.subGroups.add(subgroup); - subgroup.setParentGroup(this); - } - - /** - * Sets the group that is the new parent of this group - * @param parent ContactGroupZeroconfImpl - */ - void setParentGroup(ContactGroupZeroconfImpl parent) - { - this.parentGroup = parent; - } - - /** - * Returns the contact group that currently contains this group or null if - * this is the root contact group. - * @return the contact group that currently contains this group or null if - * this is the root contact group. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Removes the specified contact group from the this group's subgroups. - * @param subgroup the ContactGroupZeroconfImpl subgroup to remove. - */ - public void removeSubGroup(ContactGroupZeroconfImpl subgroup) - { - this.subGroups.remove(subgroup); - subgroup.setParentGroup(null); - } - - /** - * Returns the group that is parent of the specified zeroconfGroup or null - * if no parent was found. - * @param zeroconfGroup the group whose parent we're looking for. - * @return the ContactGroupZeroconfImpl instance that zeroconfGroup - * belongs to or null if no parent was found. - */ - public ContactGroupZeroconfImpl findGroupParent( - ContactGroupZeroconfImpl zeroconfGroup) - { - if ( subGroups.contains(zeroconfGroup) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupZeroconfImpl subgroup - = (ContactGroupZeroconfImpl) subGroupsIter.next(); - - ContactGroupZeroconfImpl parent - = subgroup.findGroupParent(zeroconfGroup); - - if(parent != null) - return parent; - } - return null; - } - - /** - * Returns the group that is parent of the specified zeroconfContact or - * null if no parent was found. - * - * @param zeroconfContact the contact whose parent we're looking for. - * @return the ContactGroupZeroconfImpl instance that zeroconfContact - * belongs to or null if no parent was found. - */ - public ContactGroupZeroconfImpl findContactParent( - ContactZeroconfImpl zeroconfContact) - { - if ( contacts.contains(zeroconfContact) ) - return this; - - Iterator subGroupsIter = subgroups(); - while (subGroupsIter.hasNext()) - { - ContactGroupZeroconfImpl subgroup - = (ContactGroupZeroconfImpl) subGroupsIter.next(); - - ContactGroupZeroconfImpl parent - = subgroup.findContactParent(zeroconfContact); - - if(parent != null) - return parent; - } - return null; - } - - - - /** - * Returns the Contact with the specified address or identifier. - * - * @param id the addres or identifier of the Contact we are - * looking for. - * @return the Contact with the specified id or address. - */ - public Contact getContact(String id) - { - Iterator contactsIter = contacts(); - while (contactsIter.hasNext()) - { - ContactZeroconfImpl contact = - (ContactZeroconfImpl)contactsIter.next(); - - if (contact.getAddress().equals(id)) - return contact; - - } - return null; - } - - /** - * Returns the subgroup with the specified index. - * - * @param index the index of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(int index) - { - return subGroups.get(index); - } - - /** - * Returns the subgroup with the specified name. - * - * @param groupName the name of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(String groupName) - { - Iterator groupsIter = subgroups(); - while (groupsIter.hasNext()) - { - ContactGroupZeroconfImpl contactGroup - = (ContactGroupZeroconfImpl) groupsIter.next(); - if (contactGroup.getGroupName().equals(groupName)) - return contactGroup; - - } - return null; - - } - - /** - * Returns the name of this group. - * - * @return a String containing the name of this group. - */ - public String getGroupName() - { - return this.groupName; - } - - /** - * Sets this group a new name. - * @param newGrpName a String containing the new name of this group. - */ - public void setGroupName(String newGrpName) - { - this.groupName = newGrpName; - } - - /** - * Returns an iterator over the sub groups that this - * ContactGroup contains. - * - * @return a java.util.Iterator over the ContactGroup children - * of this group (i.e. subgroups). - */ - public Iterator subgroups() - { - return subGroups.iterator(); - } - - /** - * Removes the specified contact from this group. - * @param contact the ContactZeroconfImpl to remove from this group - */ - public void removeContact(ContactZeroconfImpl contact) - { - this.contacts.remove(contact); - } - - /** - * Returns the contact with the specified id or null if no such contact - * exists. - * @param id the id of the contact we're looking for. - * @return ContactZeroconfImpl - */ - public ContactZeroconfImpl findContactByID(String id) - { - //first go through the contacts that are direct children. - Iterator contactsIter = contacts(); - - while(contactsIter.hasNext()) - { - ContactZeroconfImpl mContact = - (ContactZeroconfImpl)contactsIter.next(); - - if( mContact.getAddress().equals(id) ) - return mContact; - } - - //if we didn't find it here, let's try in the subougroups - Iterator groupsIter = subgroups(); - - while( groupsIter.hasNext() ) - { - ContactGroupZeroconfImpl mGroup = - (ContactGroupZeroconfImpl)groupsIter.next(); - - ContactZeroconfImpl mContact = mGroup.findContactByID(id); - - if (mContact != null) - return mContact; - } - - return null; - } - - - /** - * Returns a String representation of this group and the contacts it - * contains (may turn out to be a relatively long string). - * @return a String representing this group and its child contacts. - */ - @Override - public String toString() - { - - StringBuffer buff = new StringBuffer(getGroupName()); - buff.append(".subGroups=" + countSubgroups() + ":\n"); - - Iterator subGroups = subgroups(); - while (subGroups.hasNext()) - { - ContactGroupZeroconfImpl group = - (ContactGroupZeroconfImpl)subGroups.next(); - buff.append(group.toString()); - if (subGroups.hasNext()) - buff.append("\n"); - } - - buff.append("\nChildContacts="+countContacts()+":["); - - Iterator contacts = contacts(); - while (contacts.hasNext()) - { - ContactZeroconfImpl contact = (ContactZeroconfImpl) contacts.next(); - buff.append(contact.toString()); - if(contacts.hasNext()) - buff.append(", "); - } - return buff.append("]").toString(); - } - - /** - * Specifies whether or not this contact group is being stored by the server. - * Non persistent contact groups are common in the case of simple, - * non-persistent presence operation sets. They could however also be seen - * in persistent presence operation sets when for example we have received - * an event from someone not on our contact list and the contact that we - * associated with that user is placed in a non persistent group. Non - * persistent contact groups are volatile even when coming from a persistent - * presence op. set. They would only exist until the application is closed - * and will not be there next time it is loaded. - * - * @param isPersistent true if the contact group is to be persistent and - * false otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Makes the group resolved or unresolved. - * - * @param resolved true to make the group resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns a String that uniquely represnets the group inside - * the current protocol. The string MUST be persistent (it must not change - * across connections or runs of the application). In many cases (Jabber, - * ICQ) the string may match the name of the group as these protocols - * only allow a single level of contact groups and there is no danger of - * having the same name twice in the same contact list. Other protocols - * (no examples come to mind but that doesn't bother me ;) ) may be - * supporting mutilple levels of grooups so it might be possible for group - * A and group B to both contain groups named C. In such cases the - * implementation must find a way to return a unique identifier in this - * method and this UID should never change for a given group. - * - * @return a String representing this group in a unique and persistent - * way. - */ - public String getUID() - { - return uid; - } - - /** - * Ugly but tricky conversion method. - * @param uid the uid we'd like to get a name from - * @return the name of the group with the specified uid. - */ - static String createNameFromUID(String uid) - { - return uid.substring(0, uid.length() - (UID_SUFFIX.length())); - } - - /** - * Indicates whether some other object is "equal to" this one which in terms - * of contact groups translates to having the equal names and matching - * subgroups and child contacts. The resolved status of contactgroups and - * contacts is deliberately ignored so that groups and/or contacts would - * be assumed equal even if it differs. - *

    - * @param obj the reference object with which to compare. - * @return true if this contact group has the equal child - * contacts and subgroups to those of the obj argument. - */ - @Override - public boolean equals(Object obj) - { - if(obj == null - || !(obj instanceof ContactGroupZeroconfImpl)) - return false; - - ContactGroupZeroconfImpl zeroconfGroup - = (ContactGroupZeroconfImpl)obj; - - if(!zeroconfGroup.getGroupName().equals(getGroupName()) || - !zeroconfGroup.getUID().equals(getUID()) || - zeroconfGroup.countContacts() != countContacts() || - zeroconfGroup.countSubgroups() != countSubgroups()) - return false; - - //traverse child contacts - Iterator theirContacts = zeroconfGroup.contacts(); - - while(theirContacts.hasNext()) - { - ContactZeroconfImpl theirContact - = (ContactZeroconfImpl)theirContacts.next(); - - ContactZeroconfImpl ourContact - = (ContactZeroconfImpl)getContact(theirContact.getAddress()); - - if(ourContact == null - || !ourContact.equals(theirContact)) - return false; - } - - //traverse subgroups - Iterator theirSubgroups = zeroconfGroup.subgroups(); - - while(theirSubgroups.hasNext()) - { - ContactGroupZeroconfImpl theirSubgroup - = (ContactGroupZeroconfImpl)theirSubgroups.next(); - - ContactGroupZeroconfImpl ourSubgroup - = (ContactGroupZeroconfImpl)getGroup( - theirSubgroup.getGroupName()); - - if(ourSubgroup == null - || !ourSubgroup.equals(theirSubgroup)) - return false; - } - - return true; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactZeroconfImpl.java deleted file mode 100644 index c22cf29..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ContactZeroconfImpl.java +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.net.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * A simple, straightforward implementation of a zeroconf Contact. Since - * the Zeroconf protocol is not a real one, we simply store all contact details - * in class fields. You should know that when implementing a real protocol, - * the contact implementation would rather encapsulate contact objects from - * the protocol stack and group property values should be returned after - * consulting the encapsulated object. - * - * @author Christian Vincenot - * @author Maxime Catelin - * @author Jonathan Martin - */ -public class ContactZeroconfImpl - extends AbstractContact -{ - private static final Logger logger - = Logger.getLogger(ContactZeroconfImpl.class); - - - /** - * The id of the contact. - */ - private String contactID = null; - - /** - * The ClientThread attached to this contact if we're already chatting - * with him. - */ - private ClientThread thread = null; - - /* - * Type of Client. - */ - /** - * Gaim/Pidgin client type - */ - public static final int GAIM = 1; - /** - * iChat client type - */ - public static final int ICHAT = 2; - /** - * XMPP - XEP-0174 client type - */ - public static final int XMPP = 3; - /** - * Another SIP Communicator client - */ - public static final int SIPCOM = 4; - private int clientType = XMPP; - - - /** - * The provider that created us. - */ - private ProtocolProviderServiceZeroconfImpl parentProvider = null; - - - /* - * The Bonjour Service who discovered this contact. - * TODO: This could probably be avoided using only the - * Protocol Provider. - */ - private BonjourService bonjourService; - - /** - * The group that belong to. - */ - private ContactGroupZeroconfImpl parentGroup = null; - - /** - * The presence status of the contact. - */ - private PresenceStatus presenceStatus = ZeroconfStatusEnum.OFFLINE; - - /** - * Determines whether this contact is persistent, - * i.e. member of the contact list or whether it is here only temporarily. - * Chris: should be set to false here - */ - private boolean isPersistent = false; - - /** - * Determines whether the contact has been resolved (i.e. we have a - * confirmation that it is still on the server contact list). - */ - private boolean isResolved = true; - - /** - * IP Address - */ - private InetAddress ipAddress; - - /** - * Port on which Bonjour is listening. - */ - private int port; - - /** - * Name announced by Bonjour. - */ - private String name; - - /** - * Contact personal message - */ - private String message; - - - /** - * Creates an instance of a meta contact with the specified string used - * as a name and identifier. - * @param bonjourId ID of the contact - * @param bonjourService BonjourService responsible for handling chat with - * this contact - * @param name Display name of this contact - * @param ipAddress IP address of this contact - * @param port Port declared by this contact for direct point-to-point chat - * @param parentProvider the provider that created us. - */ - public ContactZeroconfImpl( - String bonjourId, - ProtocolProviderServiceZeroconfImpl parentProvider, - BonjourService bonjourService, - String name, - InetAddress ipAddress, - int port) - { - this.contactID = bonjourId; - this.parentProvider = parentProvider; - this.bonjourService = bonjourService; - this.name = name; - this.ipAddress = ipAddress; - this.port = port; - bonjourService.addContact(this); - } - - /** - * This method is only called when the contact is added to a new - * ContactGroupZeroconfImpl by the - * ContactGroupZeroconfImpl itself. - * - * @param newParentGroup the ContactGroupZeroconfImpl that is now - * parent of this ContactZeroconfImpl - */ - void setParentGroup(ContactGroupZeroconfImpl newParentGroup) - { - this.parentGroup = newParentGroup; - } - - /** - * Return the BonjourService - * @return BonjourService - */ - public BonjourService getBonjourService() - { - return bonjourService; - } - - /** - * Return the ClientThread responsible for handling with this contact - * @return ClientThread corresponding to the chat with this contact or null - * if no chat was started - */ - protected ClientThread getClientThread() - { - return thread; - } - - /** - * Set the ClientThread responsible for handling with this contact - * @param thread ClientThread corresponding to the chat with this contact - * or null if the chat is over - */ - protected void setClientThread(ClientThread thread) - { - this.thread = thread; - } - - /** - * Return the type of client - * @return Type of client used by this contact - */ - public int getClientType() - { - return clientType; - } - - /** - * Sets the type of client - * @param clientType Type of client used by this contact - */ - public void setClientType(int clientType) - { - this.clientType = clientType; - } - - /** - * Returns a String that can be used for identifying the contact. - * - * @return a String id representing and uniquely identifying the contact. - */ - public String getAddress() - { - return contactID; - } - - /** - * Returns a String that could be used by any user interacting modules - * for referring to this contact. - * - * @return a String that can be used for referring to this contact when - * interacting with the user. - */ - public String getDisplayName() - { - return name; - } - - /** - * Returns the IP address declared by this Contact - * @return IP address declared by this Contact - */ - public InetAddress getIpAddress() - { - return ipAddress; - } - - /** - * Returns the TCP port declared by this Contact for direct chat - * @return the TCP port declared by this Contact for direct chat - */ - public int getPort() - { - return port; - } - - - /** - * Returns the status/private message displayed by this contact - * @return the status/private message displayed by this contact - */ - public String getMessage() - { - return message; - } - - /** - * Sets the status/private message displayed by this contact - * @param message the status/private message displayed by this contact - */ - public void setMessage(String message) - { - this.message = message; - } - - - /** - * Returns a byte array containing an image (most often a photo or an - * avatar) that the contact uses as a representation. - * - * @return byte[] an image representing the contact. - */ - public byte[] getImage() - { - return null; - } - - /** - * Returns the status of the contact. - * - * @return always ZeroconfStatusEnum. - */ - public PresenceStatus getPresenceStatus() - { - return this.presenceStatus; - } - - /** - * Sets zeroconfPresenceStatus as the PresenceStatus that this - * contact is currently in. - * @param zeroconfPresenceStatus the ZeroconfPresenceStatus - * currently valid for this contact. - */ - public void setPresenceStatus(PresenceStatus zeroconfPresenceStatus) - { - this.presenceStatus = zeroconfPresenceStatus; - - if (zeroconfPresenceStatus == ZeroconfStatusEnum.OFFLINE) { - try - { - bonjourService.opSetPersPresence.unsubscribe(this); - } - catch (Exception ex) - { - logger.error(ex); - } - } - } - - /** - * Returns a reference to the protocol provider that created the contact. - * - * @return a refererence to an instance of the ProtocolProviderService - */ - public ProtocolProviderService getProtocolProvider() - { - return parentProvider; - } - - /** - * Determines whether or not this contact represents our own identity. - * - * @return true in case this is a contact that represents ourselves and - * false otherwise. - */ - public boolean isLocal() - { - return false; - } - - /** - * Returns the group that contains this contact. - * @return a reference to the ContactGroupZeroconfImpl that - * contains this contact. - */ - public ContactGroup getParentContactGroup() - { - return this.parentGroup; - } - - /** - * Returns a string representation of this contact, containing most of its - * representative details. - * - * @return a string representation of this contact. - */ - @Override - public String toString() - { - StringBuffer buff - = new StringBuffer("ContactZeroconfImpl[ DisplayName=") - .append(getDisplayName()).append("]"); - - return buff.toString(); - } - - /** - * Determines whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @return true if the contact is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Specifies whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * - * @param isPersistent true if the contact is persistent and false - * otherwise. - */ - public void setPersistent(boolean isPersistent) - { - this.isPersistent = isPersistent; - } - - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Makes the contact resolved or unresolved. - * - * @param resolved true to make the contact resolved; false to - * make it unresolved - */ - public void setResolved(boolean resolved) - { - this.isResolved = resolved; - } - - /** - * Returns the persistent presence operation set that this contact belongs - * to. - * - * @return the OperationSetPersistentPresenceZeroconfImpl that - * this contact belongs to. - */ - public OperationSetPersistentPresenceZeroconfImpl - getParentPresenceOperationSet() - { - return (OperationSetPersistentPresenceZeroconfImpl)parentProvider - .getOperationSet(OperationSetPersistentPresence.class); - } - - /** - * Return the current status message of this contact. - * - * @return null as the protocol has currently no support of status messages - */ - public String getStatusMessage() - { - return null; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/MessageZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/MessageZeroconfImpl.java deleted file mode 100644 index 3621edc..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/MessageZeroconfImpl.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Very simple message implementation for the Zeroconf protocol. - * - * @author Christian Vincenot - * @author Maxime Catelin - * @author Jonathan Martin - * @author Lubomir Marinov - */ -public class MessageZeroconfImpl - extends AbstractMessage -{ - - /** - * Message Type. - */ - private int type; - - /** - * Message type indicating that a stream is being created - */ - public static final int STREAM_OPEN = 0x1; - - /** - * Normal chat message - */ - public static final int MESSAGE = 0x2; - - /** - * Typing notification - */ - public static final int TYPING = 0x3; - - /** - * Message indicating that the stream is being closed - */ - public static final int STREAM_CLOSE = 0x4; - - /** - * Message indicating that the previsous message was delivered successfully - */ - public static final int DELIVERED = 0x5; - - /** - * Undefined message - */ - public static final int UNDEF = 0x6; - - /* - * The Baloon Icon color. (we probably won't ever use it) - */ - private int baloonColor = 0x7BB5EE; - - /* - * The Text Color. - */ - private int textColor = 0x000000; - - /* - * The font of the message. - */ - private String textFont = "Helvetica"; - - /* - * The size of the caracters composing the message. - */ - private int textSize = 12; - - /* - * The source contact id announced in the message. TODO: Could be set & - * checked to identify more precisely the contact in case several users - * would be sharing the same IP. - */ - private String contactID; - - /** - * Creates a message instance according to the specified parameters. - * - * @param content the message body - * @param contentEncoding message encoding or null for UTF8 - * @param contentType of the message - * @param type Type of message - */ - public MessageZeroconfImpl(String content, String contentEncoding, - String contentType, int type) - { - super(content, contentType, contentEncoding, null); - - this.type = type; - } - - /** - * Creates a message instance according to the specified parameters. - * - * @param type Type of message - * @param content the message body - * @param contentEncoding message encoding or null for UTF8 - */ - public MessageZeroconfImpl(String content, String contentEncoding, int type) - { - this(content, contentEncoding, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, type); - } - - /** - * Returns the type of message. Always text/plain for Zeroconf, so null. - * - * @return null - */ - public int getType() - { - return type; - } - - /** - * Gets the baloon color declared in messages sent by iChat-like clients - * - * @return baloon color - */ - public int getBaloonColor() - { - return baloonColor; - } - - /** - * Sets the baloon color declared in messages sent by iChat-like clients - * - * @param baloonColor baloon color - */ - public void setBaloonColor(int baloonColor) - { - this.baloonColor = baloonColor; - } - - /** - * Returns the text color - * - * @return Text color - */ - public int getTextColor() - { - return textColor; - } - - /** - * Sets the text color - * - * @param textColor Text color - */ - public void setTextColor(int textColor) - { - this.textColor = textColor; - } - - /** - * Returns the text font - * - * @return Text font - */ - public String getTextFont() - { - return textFont; - } - - /** - * Sets the text color - * - * @param textFont Text font - */ - public void setTextFont(String textFont) - { - this.textFont = textFont; - } - - /** - * Returns the text size - * - * @return Text size - */ - public int getTextSize() - { - return textSize; - } - - /** - * Sets the text size - * - * @param textSize Text size - */ - public void setTextSize(int textSize) - { - this.textSize = textSize; - } - - /** - * Returns the contact's ID - * - * @return String representing the contact's ID - */ - public String getContactID() - { - return contactID; - } - - /** - * Sets the contact's ID - * - * @param contactID String representing the contact's ID - */ - public void setContactID(String contactID) - { - this.contactID = contactID; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetBasicInstantMessagingZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetBasicInstantMessagingZeroconfImpl.java deleted file mode 100644 index d49118b..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetBasicInstantMessagingZeroconfImpl.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.io.*; -import java.net.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * Instant messaging functionalities for the Zeroconf protocol. - * - * @author Christian Vincenot - * - */ -public class OperationSetBasicInstantMessagingZeroconfImpl - extends AbstractOperationSetBasicInstantMessaging -{ - private static final Logger logger - = Logger.getLogger(OperationSetBasicInstantMessagingZeroconfImpl.class); - - /** - * The currently valid persistent presence operation set.. - */ - private final OperationSetPersistentPresenceZeroconfImpl opSetPersPresence; - - /** - * The protocol provider that created us. - */ - private final ProtocolProviderServiceZeroconfImpl parentProvider; - - /** - * Creates an instance of this operation set keeping a reference to the - * parent protocol provider and presence operation set. - * - * @param provider The provider instance that creates us. - * @param opSetPersPresence the currently valid - * OperationSetPersistentPresenceZeroconfImpl instance. - */ - public OperationSetBasicInstantMessagingZeroconfImpl( - ProtocolProviderServiceZeroconfImpl provider, - OperationSetPersistentPresenceZeroconfImpl opSetPersPresence) - { - this.opSetPersPresence = opSetPersPresence; - this.parentProvider = provider; - } - - @Override - public Message createMessage(String content, String contentType, - String encoding, String subject) - { - return new MessageZeroconfImpl(content, encoding, contentType, - MessageZeroconfImpl.MESSAGE); - } - - /** - * Sends the message to the destination indicated by the - * to contact. - * - * @param to the Contact to send message to - * @param message the Message to send. - * @throws IllegalStateException if the underlying Zeroconf stack is not - * registered and initialized. - * @throws IllegalArgumentException if to is not an instance - * belonging to the underlying implementation. - */ - public void sendInstantMessage(Contact to, Message message) throws - IllegalStateException, IllegalArgumentException - { - if( !(to instanceof ContactZeroconfImpl) ) - throw new IllegalArgumentException( - "The specified contact is not a Zeroconf contact." - + to); - - MessageZeroconfImpl msg = - (MessageZeroconfImpl)createMessage(message.getContent()); - - deliverMessage(msg, (ContactZeroconfImpl)to); - } - - /** - * In case the to the to Contact corresponds to another zeroconf - * protocol provider registered with SIP Communicator, we deliver - * the message to them, in case the to Contact represents us, we - * fire a MessageReceivedEvent, and if to is simply - * a contact in our contact list, then we simply echo the message. - * - * @param message the Message the message to deliver. - * @param to the Contact that we should deliver the message to. - */ - private void deliverMessage(Message message, ContactZeroconfImpl to) - { - ClientThread thread = to.getClientThread(); - try - { - if (thread == null) - { - Socket sock; - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF: Creating a chat connexion to " - +to.getIpAddress()+":"+to.getPort()); - sock = new Socket(to.getIpAddress(), to.getPort()); - thread = new ClientThread(sock, to.getBonjourService()); - thread.setStreamOpen(); - thread.setContact(to); - to.setClientThread(thread); - thread.sendHello(); - if (to.getClientType() == ContactZeroconfImpl.GAIM) - { - try - { - Thread.sleep(300); - } - catch (InterruptedException ex) - { - logger.error(ex); - } - } - } - - //System.out.println("ZEROCONF: Message content => "+ - //message.getContent()); - thread.sendMessage((MessageZeroconfImpl) message); - - fireMessageDelivered(message, to); - } - catch (IOException ex) - { - logger.error(ex); - } - } - - /** - * Notifies all registered message listeners that a message has been - * received. - * - * @param message the Message that has been received. - * @param from the Contact that message was received from. - */ - @Override - public void fireMessageReceived(Message message, Contact from) - { - super.fireMessageReceived(message, from); - } - - /** - * Determines whether the protocol provider (or the protocol itself) support - * sending and receiving offline messages. Most often this method would - * return true for protocols that support offline messages and false for - * those that don't. It is however possible for a protocol to support these - * messages and yet have a particular account that does not (i.e. feature - * not enabled on the protocol server). In cases like this it is possible - * for this method to return true even when offline messaging is not - * supported, and then have the sendMessage method throw an - * OperationFailedException with code - OFFLINE_MESSAGES_NOT_SUPPORTED. - * - * @return true if the protocol supports offline messages and - * false otherwise. - */ - public boolean isOfflineMessagingSupported() - { - return true; - } - - /** - * Determines whether the protocol supports the supplied content type - * - * @param contentType the type we want to check - * @return true if the protocol supports it and - * false otherwise. - */ - public boolean isContentTypeSupported(String contentType) - { - return contentType.equals(DEFAULT_MIME_TYPE); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetPersistentPresenceZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetPersistentPresenceZeroconfImpl.java deleted file mode 100644 index 412512e..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetPersistentPresenceZeroconfImpl.java +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * A Zeroconf implementation of a persistent presence operation set. In order - * to simulate server persistence, this operation set would simply accept all - * unresolved contacts and resolve them immediately. A real world protocol - * implementation would save it on a server using methods provided by the - * protocol stack. - * - * @author Christian Vincenot - * @author Maxime Catelin - * @author Jonathan Martin - */ -public class OperationSetPersistentPresenceZeroconfImpl - extends AbstractOperationSetPersistentPresence -{ - private static final Logger logger = - Logger.getLogger(OperationSetPersistentPresenceZeroconfImpl.class); - - /** - * The root of the zeroconf contact list. - */ - private ContactGroupZeroconfImpl contactListRoot = null; - - /** - * The currently active status message. - */ - private String statusMessage = "The truth is out there..."; - - /** - * Our default presence status. - */ - private PresenceStatus presenceStatus = ZeroconfStatusEnum.OFFLINE; - - /** - * The AuthorizationHandler instance that we'd have to transmit - * authorization requests to for approval. - */ - private AuthorizationHandler authorizationHandler = null; - - /** - * Creates an instance of this operation set keeping a reference to the - * specified parent provider. - * @param provider the ProtocolProviderServiceZeroconfImpl instance that - * created us. - */ - public OperationSetPersistentPresenceZeroconfImpl( - ProtocolProviderServiceZeroconfImpl provider) - { - super(provider); - - contactListRoot = new ContactGroupZeroconfImpl("RootGroup", provider); - - //add our unregistration listener - parentProvider.addRegistrationStateChangeListener( - new UnregistrationListener()); - } - - /** - * Creates a group with the specified name and parent in the server - * stored contact list. - * - * @param parent the group where the new group should be created - * @param groupName the name of the new group to create. - */ - public void createServerStoredContactGroup(ContactGroup parent, - String groupName) - { - ContactGroupZeroconfImpl newGroup - = new ContactGroupZeroconfImpl(groupName, parentProvider); - - ((ContactGroupZeroconfImpl)parent).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - /** - * A Zeroconf Provider method to use for fast filling of a contact list. - * - * @param contactGroup the group to add - */ - public void addZeroconfGroup(ContactGroupZeroconfImpl contactGroup) - { - contactListRoot.addSubgroup(contactGroup); - } - - /** - * A Zeroconf Provider method to use for fast filling of a contact list. - * This method would add both the group and fire an event. - * - * @param parent the group where contactGroup should be added. - * @param contactGroup the group to add - */ - public void addZeroconfGroupAndFireEvent( - ContactGroupZeroconfImpl parent - , ContactGroupZeroconfImpl contactGroup) - { - parent.addSubgroup(contactGroup); - - this.fireServerStoredGroupEvent( - contactGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - - /** - * Returns a reference to the contact with the specified ID in case we - * have a subscription for it and null otherwise/ - * - * @param contactID a String identifier of the contact which we're - * seeking a reference of. - * @return a reference to the Contact with the specified - * contactID or null if we don't have a subscription for the - * that identifier. - */ - public Contact findContactByID(String contactID) - { - return contactListRoot.findContactByID(contactID); - } - - /** - * Sets the specified status message. - * @param statusMessage a String containing the new status message. - */ - public void setStatusMessage(String statusMessage) - { - this.statusMessage = statusMessage; - } - - /** - * Returns the status message that was last set through - * setCurrentStatusMessage. - * - * @return the last status message that we have requested and the aim - * server has confirmed. - */ - public String getCurrentStatusMessage() - { - return statusMessage; - } - - /** - * Returns a PresenceStatus instance representing the state this provider - * is currently in. - * - * @return the PresenceStatus last published by this provider. - */ - public PresenceStatus getPresenceStatus() - { - return presenceStatus; - } - - /** - * Returns the root group of the server stored contact list. - * - * @return the root ContactGroup for the ContactList stored by this - * service. - */ - public ContactGroup getServerStoredContactListRoot() - { - return contactListRoot; - } - - /** - * Returns the set of PresenceStatus objects that a user of this service - * may request the provider to enter. - * - * @return Iterator a PresenceStatus array containing "enterable" status - * instances. - */ - public Iterator getSupportedStatusSet() - { - return ZeroconfStatusEnum.supportedStatusSet(); - } - - /** - * Removes the specified contact from its current parent and places it - * under newParent. - * - * @param contactToMove the Contact to move - * @param newParent the ContactGroup where Contact - * would be placed. - */ - public void moveContactToGroup(Contact contactToMove, - ContactGroup newParent) - { - ContactZeroconfImpl zeroconfContact - = (ContactZeroconfImpl)contactToMove; - - ContactGroupZeroconfImpl parentZeroconfGroup - = findContactParent(zeroconfContact); - - parentZeroconfGroup.removeContact(zeroconfContact); - - //if this is a volatile contact then we haven't really subscribed to - //them so we'd need to do so here - if(!zeroconfContact.isPersistent()) - { - //first tell everyone that the volatile contact was removed - fireSubscriptionEvent(zeroconfContact - , parentZeroconfGroup - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - - try - { - //now subscribe - this.subscribe(newParent, contactToMove.getAddress()); - - //now tell everyone that we've added the contact - fireSubscriptionEvent(zeroconfContact - , newParent - , SubscriptionEvent.SUBSCRIPTION_CREATED); - } - catch (Exception ex) - { - logger.error("Failed to move contact " - + zeroconfContact.getAddress() - , ex); - } - } - else - { - ( (ContactGroupZeroconfImpl) newParent) - .addContact(zeroconfContact); - - fireSubscriptionMovedEvent(contactToMove - , parentZeroconfGroup - , newParent); - } - } - - /** - * Requests the provider to enter into a status corresponding to the - * specified paramters. - * - * @param status the PresenceStatus as returned by - * getRequestableStatusSet - * @param statusMessage the message that should be set as the reason to - * enter that status - * @throws IllegalArgumentException if the status requested is not a - * valid PresenceStatus supported by this provider. - * @throws IllegalStateException if the provider is not currently - * registered. - * @throws OperationFailedException with code NETWORK_FAILURE if - * publishing the status fails due to a network error. - */ - public void publishPresenceStatus(PresenceStatus status, - String statusMessage) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - PresenceStatus oldPresenceStatus = this.presenceStatus; - this.presenceStatus = status; - this.statusMessage = statusMessage; - - //ICI: changer le statut du plugin Zeroconf!! - parentProvider.getBonjourService().changeStatus(status); - - this.fireProviderStatusChangeEvent(oldPresenceStatus); - - } - - /** - * Get the PresenceStatus for a particular contact. - * - * @param contactIdentifier the identifier of the contact whose status - * we're interested in. - * @return PresenceStatus the PresenceStatus of the specified - * contact - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * retrieving the status fails due to errors experienced during - * network communication - */ - public PresenceStatus queryContactStatus(String contactIdentifier) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - return findContactByID(contactIdentifier).getPresenceStatus(); - } - - /** - * Sets the presence status of contact to newStatus. - * - * @param contact the ContactZeroconfImpl whose status we'd like - * to set. - * @param newStatus the new status we'd like to set to contact. - */ - public void changePresenceStatusForContact(ContactZeroconfImpl contact, - PresenceStatus newStatus) - { - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, findContactParent(contact), oldStatus); - } - - /** - * Sets the presence status of all contacts in our contact list - * (except those that correspond to another provider registered with SC) - * to newStatus. - * - * @param newStatus the new status we'd like to set to contact. - * @param parent the group in which we'd have to update the status of all - * direct and indirect child contacts. - */ - protected void changePresenceStatusForAllContacts(ContactGroup parent, - PresenceStatus newStatus) - { - //first set the status for contacts in this group - Iterator childContacts = parent.contacts(); - - while(childContacts.hasNext()) - { - ContactZeroconfImpl contact - = (ContactZeroconfImpl)childContacts.next(); - - if(findProviderForZeroconfUserID(contact.getAddress()) != null) - { - //this is a contact corresponding to another SIP Communicator - //provider so we won't change it's status here. - continue; - } - PresenceStatus oldStatus = contact.getPresenceStatus(); - contact.setPresenceStatus(newStatus); - - fireContactPresenceStatusChangeEvent( - contact, parent, oldStatus); - } - - //now call this method recursively for all subgroups - Iterator subgroups = parent.subgroups(); - - while(subgroups.hasNext()) - { - ContactGroup subgroup = subgroups.next(); - changePresenceStatusForAllContacts(subgroup, newStatus); - } - } - - /** - * Returns the group that is parent of the specified zeroconfGroup or null - * if no parent was found. - * @param zeroconfGroup the group whose parent we're looking for. - * @return the ContactGroupZeroconfImpl instance that zeroconfGroup - * belongs to or null if no parent was found. - */ - public ContactGroupZeroconfImpl findGroupParent( - ContactGroupZeroconfImpl zeroconfGroup) - { - return contactListRoot.findGroupParent(zeroconfGroup); - } - - /** - * Returns the group that is parent of the specified zeroconfContact or - * null if no parent was found. - * @param zeroconfContact the contact whose parent we're looking for. - * @return the ContactGroupZeroconfImpl instance that zeroconfContact - * belongs to or null if no parent was found. - */ - public ContactGroupZeroconfImpl findContactParent( - ContactZeroconfImpl zeroconfContact) - { - return (ContactGroupZeroconfImpl)zeroconfContact - .getParentContactGroup(); - } - - - /** - * Removes the specified group from the server stored contact list. - * - * @param group the group to remove. - * - * @throws IllegalArgumentException if group was not found in this - * protocol's contact list. - */ - public void removeServerStoredContactGroup(ContactGroup group) - throws IllegalArgumentException - { - ContactGroupZeroconfImpl zeroconfGroup - = (ContactGroupZeroconfImpl)group; - - ContactGroupZeroconfImpl parent = findGroupParent(zeroconfGroup); - - if(parent == null){ - throw new IllegalArgumentException( - "group " + group - + " does not seem to belong to this protocol's contact list."); - } - - parent.removeSubGroup(zeroconfGroup); - - this.fireServerStoredGroupEvent( - zeroconfGroup, ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - } - - /** - * Renames the specified group from the server stored contact list. - * - * @param group the group to rename. - * @param newName the new name of the group. - */ - public void renameServerStoredContactGroup(ContactGroup group, - String newName) - { - ((ContactGroupZeroconfImpl)group).setGroupName(newName); - - this.fireServerStoredGroupEvent( - group, - ServerStoredGroupEvent.GROUP_RENAMED_EVENT); - } - - /** - * Handler for incoming authorization requests. - * - * @param handler an instance of an AuthorizationHandler for - * authorization requests coming from other users requesting - * permission add us to their contact list. - */ - public void setAuthorizationHandler(AuthorizationHandler handler) - { - this.authorizationHandler = handler; - } - - /** - * Persistently adds a subscription for the presence status of the - * contact corresponding to the specified contactIdentifier and indicates - * that it should be added to the specified group of the server stored - * contact list. - * - * @param parent the parent group of the server stored contact list - * where the contact should be added.

    - * @param contactIdentifier the contact whose status updates we are - * subscribing for. - * @throws IllegalArgumentException if contact or - * parent are not a contact known to the underlying protocol - * provider. - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(ContactGroup parent, String contactIdentifier) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - /* ContactZeroconfImpl contact = new ContactZeroconfImpl( - contactIdentifier, - parentProvider, - null, null, null, 0); - - ((ContactGroupZeroconfImpl)parent).addContact(contact); - - fireSubscriptionEvent(contact, - parent, - SubscriptionEvent.SUBSCRIPTION_CREATED); - //if the newly added contact corresponds to another provider - set their - //status accordingly - ProtocolProviderServiceZeroconfImpl gibProvider - = findProviderForZeroconfUserID(contactIdentifier); - if(gibProvider != null) - { - OperationSetPersistentPresence opSetPresence - = (OperationSetPersistentPresence)gibProvider.getOperationSet( - OperationSetPersistentPresence.class); - - changePresenceStatusForContact( - contact - , (ZeroconfStatusEnum)opSetPresence.getPresenceStatus()); - } - else - { - //otherwise - since we are not a real protocol, we set the contact - //presence status ourselves - changePresenceStatusForContact(contact, getPresenceStatus()); - } - - //notify presence listeners for the status change. - fireContactPresenceStatusChangeEvent(contact - , parent - , ZeroconfStatusEnum.OFFLINE); - */} - - - - /** - * Adds a subscription for the presence status of the contact - * corresponding to the specified contactIdentifier. - * - * @param contactIdentifier the identifier of the contact whose status - * updates we are subscribing for.

    - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(String contactIdentifier) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - subscribe(contactListRoot, contactIdentifier); - } - - /** - * Removes a subscription for the presence status of the specified - * contact. - * - * @param contact the contact whose status updates we are unsubscribing - * from. - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * unsubscribing fails due to errors experienced during network - * communication - */ - public void unsubscribe(Contact contact) - throws IllegalArgumentException, - IllegalStateException, - OperationFailedException - { - String name = contact.getAddress(); - - ContactGroupZeroconfImpl parentGroup - = (ContactGroupZeroconfImpl)((ContactZeroconfImpl)contact) - .getParentContactGroup(); - - //parentGroup.removeContact((ContactZeroconfImpl)contact); - - BonjourService service = - ((ProtocolProviderServiceZeroconfImpl)contact.getProtocolProvider()) - .getBonjourService(); - //TODO: better check with IP - service.removeContact(name,null); - - fireSubscriptionEvent(contact, - ((ContactZeroconfImpl)contact).getParentContactGroup() - , SubscriptionEvent.SUBSCRIPTION_REMOVED); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData) - { - return createUnresolvedContact(address - , persistentData - , getServerStoredContactListRoot()); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created Contact - * against the server. The protocol provider may will later try and resolve - * the contact. When this happens the corresponding event would notify - * interested subscription listeners. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @param parent the group where the unresolved contact is - * supposed to belong to. - * - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData, - ContactGroup parent) - { - return null; - } - - /** - * Looks for a zeroconf protocol provider registered for a user id matching - * zeroconfUserID. - * - * @param zeroconfUserID the ID of the Zeroconf user whose corresponding - * protocol provider we'd like to find. - * @return ProtocolProviderServiceZeroconfImpl a zeroconf protocol - * provider registered for a user with id zeroconfUserID or null - * if there is no such protocol provider. - */ - public ProtocolProviderServiceZeroconfImpl - findProviderForZeroconfUserID(String zeroconfUserID) - { - BundleContext bc = ZeroconfActivator.getBundleContext(); - - String osgiQuery = "(&" + - "(" + ProtocolProviderFactory.PROTOCOL + - "=" + ProtocolNames.ZEROCONF + ")" + - "(" + ProtocolProviderFactory.USER_ID + - "=" + zeroconfUserID + "))"; - - ServiceReference[] refs = null; - try - { - refs = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - osgiQuery); - } - catch (InvalidSyntaxException ex) - { - logger.error("Failed to execute the following osgi query: " - + osgiQuery - , ex); - } - - if(refs != null && refs.length > 0) - { - return (ProtocolProviderServiceZeroconfImpl)bc.getService(refs[0]); - } - - return null; - } - - /** - * Creates and returns a unresolved contact group from the specified - * address and persistentData. The method will not try - * to establish a network connection and resolve the newly created - * ContactGroup against the server or the contact itself. The - * protocol provider will later resolve the contact group. When this happens - * the corresponding event would notify interested subscription listeners. - * - * @param groupUID an identifier, returned by ContactGroup's getGroupUID, - * that the protocol provider may use in order to create the group. - * @param persistentData a String returned ContactGroups's - * getPersistentData() method during a previous run and that has been - * persistently stored locally. - * @param parentGroup the group under which the new group is to be created - * or null if this is group directly underneath the root. - * @return the unresolved ContactGroup created from the specified - * uid and persistentData - */ - public ContactGroup createUnresolvedContactGroup(String groupUID, - String persistentData, ContactGroup parentGroup) - { - ContactGroupZeroconfImpl newGroup - = new ContactGroupZeroconfImpl( - ContactGroupZeroconfImpl.createNameFromUID(groupUID) - , parentProvider); - newGroup.setResolved(false); - - //if parent is null then we're adding under root. - if(parentGroup == null) - parentGroup = getServerStoredContactListRoot(); - - ((ContactGroupZeroconfImpl)parentGroup).addSubgroup(newGroup); - - this.fireServerStoredGroupEvent( - newGroup, ServerStoredGroupEvent.GROUP_CREATED_EVENT); - - return newGroup; - } - - private class UnregistrationListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenver - * a change in the registration state of the corresponding provider had - * occurred. The method is particularly interested in events stating - * that the zeroconf provider has unregistered so that it would fire - * status change events for all contacts in our buddy list. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - - if (logger.isDebugEnabled()) - logger.debug("ZEROCONF : The Zeroconf provider changed state from: " - + evt.getOldState() - + " to: " + evt.getNewState()); - - //send event notifications saying that all our buddies are - //offline. The Zeroconf protocol does not implement top level buddies - //nor subgroups for top level groups so a simple nested loop - //would be enough. - Iterator groupsIter - = getServerStoredContactListRoot().subgroups(); - while (groupsIter.hasNext()) - { - ContactGroup group = groupsIter.next(); - Iterator contactsIter = group.contacts(); - - while (contactsIter.hasNext()) - { - ContactZeroconfImpl contact - = (ContactZeroconfImpl) contactsIter.next(); - - PresenceStatus oldContactStatus - = contact.getPresenceStatus(); - - /* We set contacts to OFFLINE and send an event so that external listeners - * can be aware that the contacts are reachable anymore. Dunno if that's - * a good idea. Can be erased if not. Contacts clean is directly done by the - * contact status change handler. - */ - if (!oldContactStatus.isOnline()) - { - //contact.setPresenceStatus(ZeroconfStatusEnum.OFFLINE); - fireContactPresenceStatusChangeEvent( - contact - , contact.getParentContactGroup() - , oldContactStatus); - } - } - } - } - } - - /** - * Returns the volatile group or null if this group has not yet been - * created. - * - * @return a volatile group existing in our contact list or null - * if such a group has not yet been created. - */ - public ContactGroupZeroconfImpl getNonPersistentGroup() - { - for (int i = 0; - i < getServerStoredContactListRoot().countSubgroups(); - i++) - { - ContactGroupZeroconfImpl gr = - (ContactGroupZeroconfImpl)getServerStoredContactListRoot() - .getGroup(i); - - if(!gr.isPersistent()) - return gr; - } - - return null; - } - - - /** - * Creates a non persistent contact for the specified address. This would - * also create (if necessary) a group for volatile contacts that would not - * be added to the server stored contact list. This method would have no - * effect on the server stored contact list. - * @return the newly created volatile contact. - * @param bonjourService BonjourService responsible for the chat with this contact - * @param name Display name of the contact - * @param ip IP address of the contact - * @param port Port declared by the contact for direct chat - * @param contactAddress the address of the volatile contact we'd like to - * create. - */ - public ContactZeroconfImpl createVolatileContact(String contactAddress, - BonjourService bonjourService, - String name, - InetAddress ip, - int port) - { - //First create the new volatile contact; - ContactZeroconfImpl newVolatileContact - = new ContactZeroconfImpl(contactAddress, - this.parentProvider, bonjourService, name, ip, port); - newVolatileContact.setPersistent(false); - - - //Check whether a volatile group already exists and if not create - //one - ContactGroupZeroconfImpl theVolatileGroup = getNonPersistentGroup(); - - - //if the parent volatile group is null then we create it - if (theVolatileGroup == null) - { - theVolatileGroup = new ContactGroupZeroconfImpl( - "Bonjour" - , parentProvider); - theVolatileGroup.setResolved(false); - theVolatileGroup.setPersistent(false); - - this.contactListRoot.addSubgroup(theVolatileGroup); - - fireServerStoredGroupEvent(theVolatileGroup - , ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - - //now add the volatile contact instide it - theVolatileGroup.addContact(newVolatileContact); - fireSubscriptionEvent(newVolatileContact - , theVolatileGroup - , SubscriptionEvent.SUBSCRIPTION_CREATED); - - return newVolatileContact; - } - - public Contact getLocalContact() - { - return null; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetTypingNotificationsZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetTypingNotificationsZeroconfImpl.java deleted file mode 100644 index db397b8..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/OperationSetTypingNotificationsZeroconfImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import net.java.sip.communicator.service.protocol.*; - -/** - * Implements typing notifications for the Zeroconf protocol. The operation - * set would simply mirror all outgoing typing notifications and make them - * appear as incoming events generated by the contact that we are currently - * writing a message to. - * - * @author Christian Vincenot - * @author Maxime Catelin - * @author Jonathan Martin - */ -public class OperationSetTypingNotificationsZeroconfImpl - extends AbstractOperationSetTypingNotifications -{ - - /** - * Creates a new instance of this operation set and keeps the parent - * provider as a reference. - * - * @param provider a ref to the ProtocolProviderServiceImpl - * that created us and that we'll use for retrieving the underlying aim - * connection. - */ - OperationSetTypingNotificationsZeroconfImpl( - ProtocolProviderServiceZeroconfImpl provider) - { - super(provider); - } - - /** - * Sends a notification to notifiedContatct that we have entered - * typingState. - * - * @param notifiedContact the Contact to notify - * @param typingState the typing state that we have entered. - * - * @throws java.lang.IllegalStateException if the underlying stack is - * not registered and initialized. - * @throws java.lang.IllegalArgumentException if notifiedContact is - * not an instance belonging to the underlying implementation. - */ - public void sendTypingNotification(Contact notifiedContact, int typingState) - throws IllegalStateException, IllegalArgumentException - { - if( !(notifiedContact instanceof ContactZeroconfImpl) ) - throw new IllegalArgumentException( - "The specified contact is not a Zeroconf contact." - + notifiedContact); - - ContactZeroconfImpl to = (ContactZeroconfImpl)notifiedContact; - - ClientThread thread = to.getClientThread(); - if (thread == null) return;/*throw new IllegalStateException( - "No communication channel opened to chat with this contact");*/ - - if (typingState != STATE_TYPING) - return; - - MessageZeroconfImpl message = - new MessageZeroconfImpl("",null, MessageZeroconfImpl.TYPING); - thread.sendMessage(message); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolIconZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolIconZeroconfImpl.java deleted file mode 100644 index 4c6ce07..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolIconZeroconfImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Represents the Zeroconf protocol icon. Implements the ProtocolIcon - * interface in order to provide a Zeroconf logo image in two different sizes. - * - * @author Christian Vincenot - * @author Jonathan Martin - */ -public class ProtocolIconZeroconfImpl - implements ProtocolIcon -{ - private static Logger logger - = Logger.getLogger(ProtocolIconZeroconfImpl.class); - - private static ResourceManagementService resourcesService; - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconsTable - = new Hashtable(); - static - { - iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, - getImageInBytes("service.protocol.zeroconf.ZEROCONF_16x16")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_32x32, - getImageInBytes("service.protocol.zeroconf.ZEROCONF_32x32")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, - getImageInBytes("service.protocol.zeroconf.ZEROCONF_48x48")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_64x64, - getImageInBytes("service.protocol.zeroconf.ZEROCONF_64x64")); - } - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconPathsTable - = new Hashtable(); - static - { - iconPathsTable.put(ProtocolIcon.ICON_SIZE_16x16, - getResources().getImagePath( - "service.protocol.zeroconf.ZEROCONF_16x16")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_32x32, - getResources().getImagePath( - "service.protocol.zeroconf.ZEROCONF_32x32")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_48x48, - getResources().getImagePath( - "service.protocol.zeroconf.ZEROCONF_48x48")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_64x64, - getResources().getImagePath( - "service.protocol.zeroconf.ZEROCONF_64x64")); - } - - /** - * Implements the ProtocolIcon.getSupportedSizes() method. Returns - * an iterator to a set containing the supported icon sizes. - * @return an iterator to a set containing the supported icon sizes - */ - public Iterator getSupportedSizes() - { - return iconsTable.keySet().iterator(); - } - - /** - * Returns TRUE if a icon with the given size is supported, FALSE-otherwise. - * @param iconSize Icon size - * @return True if this size is supported, false otherwise - */ - public boolean isSizeSupported(String iconSize) - { - return iconsTable.containsKey(iconSize); - } - - /** - * Returns the icon image in the given size. - * @param iconSize the icon size; one of ICON_SIZE_XXX constants - * @return Icon image - */ - public byte[] getIcon(String iconSize) - { - return iconsTable.get(iconSize); - } - - /** - * Returns a path to the icon with the given size. - * @param iconSize the size of the icon we're looking for - * @return the path to the icon with the given size - */ - public String getIconPath(String iconSize) - { - return iconPathsTable.get(iconSize); - } - - /** - * Returns the icon image used to represent the protocol connecting state. - * @return the icon image used to represent the protocol connecting state - */ - public byte[] getConnectingIcon() - { - return getImageInBytes("zeroconfOnlineIcon"); - } - - /** - * Returns the byte representation of the image corresponding to the given - * identifier. - * - * @param imageID the identifier of the image - * @return the byte representation of the image corresponding to the given - * identifier. - */ - public static byte[] getImageInBytes(String imageID) - { - InputStream in = getResources(). - getImageInputStream(imageID); - - if (in == null) - return null; - byte[] image = null; - try - { - image = new byte[in.available()]; - - in.read(image); - } - catch (IOException e) - { - logger.error("Failed to load image:" + imageID, e); - } - - return image; - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - { - ServiceReference serviceReference = ZeroconfActivator.bundleContext - .getServiceReference(ResourceManagementService.class.getName()); - - if(serviceReference == null) - return null; - - resourcesService - = (ResourceManagementService)ZeroconfActivator.bundleContext - .getService(serviceReference); - } - - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderFactoryZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderFactoryZeroconfImpl.java deleted file mode 100644 index e68033f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderFactoryZeroconfImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -import org.osgi.framework.*; - -/** - * The Zeroconf protocol provider factory creates instances of the Zeroconf - * protocol provider service. One Service instance corresponds to one account. - * - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ProtocolProviderFactoryZeroconfImpl - extends ProtocolProviderFactory -{ - - /** - * Creates an instance of the ProtocolProviderFactoryZeroconfImpl. - */ - public ProtocolProviderFactoryZeroconfImpl() - { - super(ZeroconfActivator.getBundleContext(), ProtocolNames.ZEROCONF); - } - - /** - * Initializaed and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. - * - * @param userIDStr tha/a user identifier uniquely representing the newly - * created account within the protocol namespace. - * @param accountProperties a set of protocol (or implementation) - * specific properties defining the new account. - * @return the AccountID of the newly created account. - */ - @Override - public AccountID installAccount( String userIDStr, - Map accountProperties) - { - BundleContext context - = ZeroconfActivator.getBundleContext(); - if (context == null) - throw new NullPointerException( - "The specified BundleContext was null"); - - if (userIDStr == null) - throw new NullPointerException( - "The specified AccountID was null"); - - if (accountProperties == null) - throw new NullPointerException( - "The specified property map was null"); - - accountProperties.put(USER_ID, userIDStr); - - AccountID accountID = - new ZeroconfAccountID(userIDStr, accountProperties); - - //make sure we haven't seen this account id before. - if (registeredAccounts.containsKey(accountID)) - throw new IllegalStateException( - "An account for id " + userIDStr + " was already installed!"); - - //first store the account and only then load it as the load generates - //an osgi event, the osgi event triggers (through the UI) a call to the - //ProtocolProviderService.register() method and it needs to access - //the configuration service and check for a stored password. - this.storeAccount(accountID, false); - - accountID = loadAccount(accountProperties); - - return accountID; - } - - @Override - protected AccountID createAccountID(String userID, Map accountProperties) - { - return new ZeroconfAccountID(userID, accountProperties); - } - - @Override - protected ProtocolProviderService createService(String userID, - AccountID accountID) - { - ProtocolProviderServiceZeroconfImpl service = - new ProtocolProviderServiceZeroconfImpl(); - - service.initialize(userID, accountID); - return service; - } - - @Override - public void modifyAccount( ProtocolProviderService protocolProvider, - Map accountProperties) - throws NullPointerException - { - // TODO Auto-generated method stub - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderServiceZeroconfImpl.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderServiceZeroconfImpl.java deleted file mode 100644 index 7fe916f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ProtocolProviderServiceZeroconfImpl.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -/** - * An implementation of the protocol provider service over the Zeroconf protocol - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ProtocolProviderServiceZeroconfImpl - extends AbstractProtocolProviderService -{ - /** - * The logger for this class. - */ - private static final Logger logger = - Logger.getLogger(ProtocolProviderServiceZeroconfImpl.class); - - /** - * We use this to lock access to initialization. - */ - private final Object initializationLock = new Object(); - - /** - * The id of the account that this protocol provider represents. - */ - private AccountID accountID = null; - - /** - * Indicates whether or not the provider is initialized and ready for use. - */ - private boolean isInitialized = false; - - /** - * The logo corresponding to the zeroconf protocol. - */ - private final ProtocolIconZeroconfImpl zeroconfIcon - = new ProtocolIconZeroconfImpl(); - - /** - * The registration state that we are currently in. Note that in a real - * world protocol implementation this field won't exist and the registration - * state would be retrieved from the protocol stack. - */ - private RegistrationState currentRegistrationState - = RegistrationState.UNREGISTERED; - - /** - * The BonjourService corresponding to this ProtocolProviderService - */ - - private BonjourService bonjourService; - - /** - * The default constructor for the Zeroconf protocol provider. - */ - public ProtocolProviderServiceZeroconfImpl() - { - if (logger.isTraceEnabled()) - logger.trace("Creating a zeroconf provider."); - } - - /** - * Returns the AccountID that uniquely identifies the account represented - * by this instance of the ProtocolProviderService. - * - * @return the id of the account represented by this provider. - */ - public AccountID getAccountID() - { - return accountID; - } - - /** - * Returns the Bonjour Service that handles the Bonjour protocol stack. - * - *@return the Bonjour Service linked with this Protocol Provider - */ - public BonjourService getBonjourService() - { - return bonjourService; - } - - /** - * Initializes the service implementation, and puts it in a sate where it - * could interoperate with other services. It is strongly recomended that - * properties in this Map be mapped to property names as specified by - * AccountProperties. - * - * @param userID the user id of the zeroconf account we're currently - * initializing - * @param accountID the identifier of the account that this protocol - * provider represents. - * - * @see net.java.sip.communicator.service.protocol.AccountID - */ - protected void initialize(String userID, - AccountID accountID) - { - synchronized(initializationLock) - { - this.accountID = accountID; - - - //initialize the presence operationset - OperationSetPersistentPresenceZeroconfImpl persistentPresence = - new OperationSetPersistentPresenceZeroconfImpl(this); - - addSupportedOperationSet( - OperationSetPersistentPresence.class, - persistentPresence); - //register it once again for those that simply need presence and - //won't be smart enough to check for a persistent presence - //alternative - addSupportedOperationSet( - OperationSetPresence.class, - persistentPresence); - - //initialize the IM operation set - addSupportedOperationSet( - OperationSetBasicInstantMessaging.class, - new OperationSetBasicInstantMessagingZeroconfImpl( - this, - persistentPresence)); - - //initialize the typing notifications operation set - addSupportedOperationSet( - OperationSetTypingNotifications.class, - new OperationSetTypingNotificationsZeroconfImpl(this)); - - isInitialized = true; - } - } - - /** - * Returns the short name of the protocol that the implementation of this - * provider is based upon (like SIP, Jabber, ICQ/AIM, or others for - * example). - * - * @return a String containing the short name of the protocol this - * service is implementing (most often that would be a name in - * ProtocolNames). - */ - public String getProtocolName() - { - return ProtocolNames.ZEROCONF; - } - - /** - * Returns the state of the registration of this protocol provider with - * the corresponding registration service. - * - * @return ProviderRegistrationState - */ - public RegistrationState getRegistrationState() - { - return currentRegistrationState; - } - - /** - * Starts the registration process. - * - * @param authority the security authority that will be used for - * resolving any security challenges that may be returned during the - * registration or at any moment while wer're registered. - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void register(SecurityAuthority authority) - throws OperationFailedException - { - //we don't need a password here since there's no server in - //zeroconf. - - RegistrationState oldState = currentRegistrationState; - currentRegistrationState = RegistrationState.REGISTERED; - - - //ICI : creer le service Zeroconf !! - if (logger.isInfoEnabled()) - logger.info("ZEROCONF: Starting the service"); - this.bonjourService = new BonjourService(5298, this); - - //bonjourService.changeStatus(ZeroconfStatusEnum.ONLINE); - - fireRegistrationStateChanged( - oldState - , currentRegistrationState - , RegistrationStateChangeEvent.REASON_USER_REQUEST - , null); - } - - /** - * Makes the service implementation close all open sockets and release - * any resources that it might have taken and prepare for - * shutdown/garbage collection. - */ - public void shutdown() - { - if(!isInitialized) - { - return; - } - if (logger.isTraceEnabled()) - logger.trace("Killing the Zeroconf Protocol Provider."); - - if(isRegistered()) - { - try - { - //do the unregistration - unregister(); - } - catch (OperationFailedException ex) - { - //we're shutting down so we need to silence the exception here - logger.error( - "Failed to properly unregister before shutting down. " - + getAccountID() - , ex); - } - } - - isInitialized = false; - } - - /** - * Ends the registration of this protocol provider with the current - * registration service. - * - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void unregister() - throws OperationFailedException - { - RegistrationState oldState = currentRegistrationState; - currentRegistrationState = RegistrationState.UNREGISTERED; - - if(bonjourService != null) - bonjourService.shutdown(); - - fireRegistrationStateChanged( - oldState - , currentRegistrationState - , RegistrationStateChangeEvent.REASON_USER_REQUEST - , null); - } - - /* - * (non-Javadoc) - * - * @see net.java.sip.communicator.service.protocol.ProtocolProviderService# - * isSignallingTransportSecure() - */ - public boolean isSignalingTransportSecure() - { - return false; - } - - /** - * Returns the "transport" protocol of this instance used to carry the - * control channel for the current protocol service. - * - * @return The "transport" protocol of this instance: TCP. - */ - public TransportProtocol getTransportProtocol() - { - return TransportProtocol.TCP; - } - - /** - * Returns the zeroconf protocol icon. - * @return the zeroconf protocol icon - */ - public ProtocolIcon getProtocolIcon() - { - return zeroconfIcon; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfAccountID.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfAccountID.java deleted file mode 100644 index 64e22c7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfAccountID.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Zeroconf implementation of a sip-communicator AccountID - * - * @author Christian Vincenot - */ -public class ZeroconfAccountID - extends AccountID -{ - /* Firstname, lastname, mail address */ - private String first = null; - private String last = null; - private String mail = null; - - private boolean rememberContacts = false; - - /** - * Creates a zeroconf account id from the specified id and account - * properties. - * @param userID id identifying this account - * @param accountProperties any other properties necessary for the account. - */ - ZeroconfAccountID(String userID, Map accountProperties) - { - super(userID, - accountProperties, - ProtocolNames.ZEROCONF, - "zeroconf.org"); - - first = accountProperties.get("first"); - last = accountProperties.get("last"); - mail = accountProperties.get("mail"); - - rememberContacts = - new Boolean(accountProperties.get("rememberContacts")) - .booleanValue(); - } - - /** - * Returns a String representing the firstname of this user. - * @return String representing the firstname of this user. - */ - public String getFirst() - { - return first; - } - - /** - * Returns a String representing the lastname of this user. - * @return String representing the lastname of this user. - */ - public String getLast() - { - return last; - } - - /** - * Returns a String representing the mail address of this user. - * @return String representing the mail address of this user. - */ - public String getMail() - { - return mail; - } - - /** - * Returns a boolean indicating if we store the contacts we meet or not. - * @return boolean indicating if we store the contacts we meet or not. - */ - public boolean isRememberContacts() - { - return rememberContacts; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfActivator.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfActivator.java deleted file mode 100644 index 2544bab..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfActivator.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Loads the Zeroconf provider factory and registers its services in the OSGI - * bundle context. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ZeroconfActivator - implements BundleActivator -{ - private static final Logger logger - = Logger.getLogger(ZeroconfActivator.class); - - /** - * A reference to the registration of our Zeroconf protocol provider - * factory. - */ - private ServiceRegistration zeroconfPpFactoryServReg = null; - - /** - * A reference to the Zeroconf protocol provider factory. - */ - private static ProtocolProviderFactoryZeroconfImpl - zeroconfProviderFactory = null; - - /** - * The currently valid bundle context. - */ - static BundleContext bundleContext = null; - - - /** - * Called when this bundle is started. In here we'll export the - * zeroconf ProtocolProviderFactory implementation so that it could be - * possible to register accounts with it in SIP Communicator. - * - * @param context The execution context of the bundle being started. - * @throws Exception If this method throws an exception, this bundle is - * marked as stopped and the Framework will remove this bundle's - * listeners, unregister all services registered by this bundle, and - * release all services used by this bundle. - */ - public void start(BundleContext context) - throws Exception - { -// logger.setLevelAll(); - - bundleContext = context; - - Hashtable hashtable = new Hashtable(); - hashtable.put(ProtocolProviderFactory.PROTOCOL, "Zeroconf"); - - zeroconfProviderFactory = new ProtocolProviderFactoryZeroconfImpl(); - - //register the zeroconf provider factory. - zeroconfPpFactoryServReg = context.registerService( - ProtocolProviderFactory.class.getName(), - zeroconfProviderFactory, - hashtable); - - if (logger.isInfoEnabled()) - logger.info("Zeroconf protocol implementation [STARTED]."); - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return a reference to the BundleContext instance that we were started - * witn. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Retrurns a reference to the protocol provider factory that we have - * registered. - * @return a reference to the ProtocolProviderFactoryJabberImpl - * instance that we have registered from this package. - */ - public static ProtocolProviderFactoryZeroconfImpl getProtocolProviderFactory() - { - return zeroconfProviderFactory; - } - - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param context The execution context of the bundle being stopped. - * @throws Exception If this method throws an exception, the bundle is - * still marked as stopped, and the Framework will remove the bundle's - * listeners, unregister all services registered by the bundle, and - * release all services used by the bundle. - */ - public void stop(BundleContext context) - throws Exception - { - zeroconfProviderFactory.stop(); - zeroconfPpFactoryServReg.unregister(); - - if (logger.isInfoEnabled()) - logger.info("Zeroconf protocol implementation [STOPPED]."); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfStatusEnum.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfStatusEnum.java deleted file mode 100644 index 3fe2745..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/ZeroconfStatusEnum.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * An implementation of PresenceStatus that enumerates all states that - * a Zeroconf contact can fall into. - * - * @author Christian Vincenot - * @author Jonathan Martin - */ -public class ZeroconfStatusEnum - extends PresenceStatus -{ - - /** - * Indicates an Offline status or status with 0 connectivity. - */ - public static final ZeroconfStatusEnum OFFLINE - = new ZeroconfStatusEnum( - 0, - "Offline", - ProtocolIconZeroconfImpl.getImageInBytes( - "service.protocol.zeroconf.OFFLINE_STATUS_ICON")); - - /** - * The DND status. Indicates that the user has connectivity but prefers - * not to be contacted. - */ - public static final ZeroconfStatusEnum DO_NOT_DISTURB - = new ZeroconfStatusEnum( - 30, - "Do Not Disturb",//, "Do Not Disturb", - ProtocolIconZeroconfImpl.getImageInBytes( - "service.protocol.zeroconf.DND_STATUS_ICON")); - - /** - * The Invisible status. Indicates that the user has connectivity even - * though it may appear otherwise to others, to whom she would appear to be - * offline. - */ - public static final ZeroconfStatusEnum INVISIBLE - = new ZeroconfStatusEnum( - 45, - "Invisible", - ProtocolIconZeroconfImpl.getImageInBytes( - "service.protocol.zeroconf.INVISIBLE_STATUS_ICON")); - - /** - * The Online status. Indicate that the user is able and willing to - * communicate. - */ - public static final ZeroconfStatusEnum ONLINE - = new ZeroconfStatusEnum( - 65, - "Available",//, "Online" - ProtocolIconZeroconfImpl.getImageInBytes( - "service.protocol.zeroconf.ONLINE_STATUS_ICON")); - - - /** - * Initialize the list of supported status states. - */ - private static List supportedStatusSet = new LinkedList(); - static - { - supportedStatusSet.add(OFFLINE); - supportedStatusSet.add(DO_NOT_DISTURB); - - /* INVISIBLE STATUS could be supported by unregistering JmDNS and - * accepting unknown contacts' messages */ - //supportedStatusSet.add(INVISIBLE); - - supportedStatusSet.add(ONLINE); - } - - /** - * Creates an instance of ZeroconfPresneceStatus with the - * specified parameters. - * @param status the connectivity level of the new presence status instance - * @param statusName the name of the presence status. - * @param statusIcon the icon associated with this status - */ - private ZeroconfStatusEnum(int status, - String statusName, - byte[] statusIcon) - { - super(status, statusName, statusIcon); - } - - /** - * Returns an iterator over all status instances supproted by the zeroconf - * provider. - * @return an Iterator over all status instances supported by the - * zeroconf provider. - */ - static Iterator supportedStatusSet() - { - return supportedStatusSet.iterator(); - } - - /** - * @param status String representation of the status - * @return ZeroconfStatusEnum corresponding the supplied String value - */ - static ZeroconfStatusEnum statusOf(String status) - { - Iterator statusIter = supportedStatusSet(); - while (statusIter.hasNext()) - { - ZeroconfStatusEnum state = (ZeroconfStatusEnum)statusIter.next(); - if (state.statusName.equalsIgnoreCase(status)) - return state; - } - return null; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSCache.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSCache.java deleted file mode 100644 index 0baaff4..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSCache.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.*; - -import net.java.sip.communicator.util.*; - -/** - * A table of DNS entries. This is a hash table which - * can handle multiple entries with the same name. - *

    - * Storing multiple entries with the same name is implemented using a - * linked list of CacheNode's. - *

    - * The current implementation of the API of DNSCache does expose the - * cache nodes to clients. Clients must explicitly deal with the nodes - * when iterating over entries in the cache. Here's how to iterate over - * all entries in the cache: - *

    - * for (Iterator i=dnscache.iterator(); i.hasNext(); )
    - * {
    - *    for ( DNSCache.CacheNode n = (DNSCache.CacheNode) i.next();
    - *          n != null;
    - *          n.next())
    - *    {
    - *       DNSEntry entry = n.getValue();
    - *       ...do something with entry...
    - *    }
    - * }
    - * 
    - *

    - * And here's how to iterate over all entries having a given name: - *

    - * for (    DNSCache.CacheNode n = (DNSCache.CacheNode) dnscache.find(name);
    - *          n != null;
    - *          n.next())
    - * {
    - *     DNSEntry entry = n.getValue();
    - *     ...do something with entry...
    - * }
    - * 
    - * - * @version %I%, %G% - * @author Arthur van Hoff, Werner Randelshofer, Rick Blair - */ -class DNSCache -{ - private static Logger logger = Logger.getLogger(DNSCache.class.toString()); - // Implementation note: - // We might completely hide the existence of CacheNode's in a future version - // of DNSCache. But this will require to implement two (inner) classes for - // the iterators that will be returned by method iterator() and - // method find(name). - // Since DNSCache is not a public class, it does not seem worth the effort - // to clean its API up that much. - - // [PJYF Oct 15 2004] This should implements Collections - // that would be amuch cleaner implementation - - /** - * The number of DNSEntry's in the cache. - */ - private int size; - - /** - * The hashtable used internally to store the entries of the cache. - * Keys are instances of String. The String contains an unqualified service - * name. - * Values are linked lists of CacheNode instances. - */ - private HashMap hashtable; - - /** - * Cache nodes are used to implement storage of multiple DNSEntry's of the - * same name in the cache. - */ - public static class CacheNode - { - private DNSEntry value; - private CacheNode next; - - public CacheNode(DNSEntry value) - { - this.value = value; -// String SLevel = System.getProperty("jmdns.debug"); -// if (SLevel == null) -// SLevel = "INFO"; -// logger.setLevel(Level.parse(SLevel)); - } - - public CacheNode next() - { - return next; - } - - public DNSEntry getValue() - { - return value; - } - } - - - /** - * Create a table with a given initial size. - * @param size initial size. - */ - public DNSCache(final int size) - { - hashtable = new HashMap(size); - -// String SLevel = System.getProperty("jmdns.debug"); -// if (SLevel == null) SLevel = "INFO"; -// logger.setLevel(Level.parse(SLevel)); - } - - /** - * Clears the cache. - */ - public synchronized void clear() - { - hashtable.clear(); - size = 0; - } - - /** - * Adds an entry to the table. - * @param entry added to the table. - */ - public synchronized void add(final DNSEntry entry) - { - //logger.log("DNSCache.add("+entry.getName()+")"); - CacheNode newValue = new CacheNode(entry); - CacheNode node = hashtable.get(entry.getName()); - if (node == null) - { - hashtable.put(entry.getName(), newValue); - } - else - { - newValue.next = node.next; - node.next = newValue; - } - size++; - } - - /** - * Remove a specific entry from the table. - * @param entry removed from table. - * @return Returns true if the entry was found. - */ - public synchronized boolean remove(DNSEntry entry) - { - CacheNode node = hashtable.get(entry.getName()); - if (node != null) - { - if (node.value == entry) - { - if (node.next == null) - { - hashtable.remove(entry.getName()); - } - else - { - hashtable.put(entry.getName(), node.next); - } - size--; - return true; - } - - CacheNode previous = node; - node = node.next; - while (node != null) - { - if (node.value == entry) - { - previous.next = node.next; - size--; - return true; - } - previous = node; - node = node.next; - } - ; - } - return false; - } - - /** - * Get a matching DNS entry from the table (using equals). - * @param entry to be found in table. - * @return Returns the entry that was found. - */ - public synchronized DNSEntry get(DNSEntry entry) - { - for (CacheNode node = find(entry.getName()); node != null; node = node.next) - { - if (node.value.equals(entry)) - { - return node.value; - } - } - return null; - } - - /** - * Get a matching DNS entry from the table. - * @param name - * @param type - * @param clazz - * @return Return the entry if found, null otherwise. - */ - public synchronized DNSEntry get(String name, int type, int clazz) - { - for (CacheNode node = find(name); node != null; node = node.next) - { - if (node.value.type == type && node.value.clazz == clazz) - { - return node.value; - } - } - return null; - } - - /** - * Iterates over all cache nodes. - * The iterator returns instances of DNSCache.CacheNode. - * Each instance returned is the first node of a linked list. - * To retrieve all entries, one must iterate over this linked list. See - * code snippets in the header of the class. - * @return Returns iterator with instances of DNSCache.CacheNode. - */ - public Iterator iterator() - { - return Collections.unmodifiableCollection(hashtable.values()).iterator(); - } - - /** - * Iterate only over items with matching name. - * If an instance is returned, it is the first node of a linked list. - * To retrieve all entries, one must iterate over this linked list. - * @param name to be found. - * @return Returns an instance of DNSCache.CacheNode or null. - */ - public synchronized CacheNode find(String name) - { - return hashtable.get(name); - } - - /** - * List all entries for debugging. - */ - public synchronized void print() - { - for (Iterator i = iterator(); i.hasNext();) - { - for (CacheNode n = i.next(); n != null; n = n.next) - { - if (logger.isInfoEnabled()) - logger.info(n.value.toString()); - } - } - } - - @Override - public synchronized String toString() - { - StringBuffer aLog = new StringBuffer(); - aLog.append("\t---- cache ----"); - for (Iterator i = iterator(); i.hasNext();) - { - for (CacheNode n = i.next(); n != null; n = n.next) - { - aLog.append("\n\t\t" + n.value); - } - } - return aLog.toString(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSConstants.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSConstants.java deleted file mode 100644 index 8792c8d..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSConstants.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff, Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -/** - * DNS constants. - * - * @version %I%, %G% - * @author Arthur van Hoff, Jeff Sonstein, - * Werner Randelshofer, Pierre Frisch, Rick Blair - */ -public final class DNSConstants -{ - - // changed to final class - jeffs - final static String MDNS_GROUP = "224.0.0.251"; - final static String MDNS_GROUP_IPV6 = "FF02::FB"; - final static int MDNS_PORT = 5353; - final static int DNS_PORT = 53; - // default one hour TTL - final static int DNS_TTL = 60 * 60; - // two hour TTL (draft-cheshire-dnsext-multicastdns.txt ch 13) - // final static int DNS_TTL = 120 * 60; - - final static int MAX_MSG_TYPICAL = 1460; - final static int MAX_MSG_ABSOLUTE = 8972; - - final static int FLAGS_QR_MASK = 0x8000; // Query response mask - final static int FLAGS_QR_QUERY = 0x0000; // Query - final static int FLAGS_QR_RESPONSE = 0x8000;// Response - - public final static int FLAGS_AA = 0x0400; // Authorative answer - final static int FLAGS_TC = 0x0200; // Truncated - final static int FLAGS_RD = 0x0100; // Recursion desired - public final static int FLAGS_RA = 0x8000; // Recursion available - - final static int FLAGS_Z = 0x0040; // Zero - final static int FLAGS_AD = 0x0020; // Authentic data - final static int FLAGS_CD = 0x0010; // Checking disabled - - // Final Static Internet - public final static int CLASS_IN = 1; - // CSNET - final static int CLASS_CS = 2; - // CHAOS - final static int CLASS_CH = 3; - // Hesiod - final static int CLASS_HS = 4; - // Used in DNS UPDATE [RFC 2136] - final static int CLASS_NONE = 254; - // Not a DNS class, but a DNS query class, meaning "all classes" - final static int CLASS_ANY = 255; - // Multicast DNS uses the bottom 15 bits to identify the record class... - final static int CLASS_MASK = 0x7FFF; - // ... and the top bit indicates that all other cached records are now invalid - public final static int CLASS_UNIQUE = 0x8000; - - final static int TYPE_IGNORE = 0; // This is a hack to stop further processing - public final static int TYPE_A = 1; // Address - final static int TYPE_NS = 2; // Name Server - final static int TYPE_MD = 3; // Mail Destination - final static int TYPE_MF = 4; // Mail Forwarder - final static int TYPE_CNAME = 5; // Canonical Name - final static int TYPE_SOA = 6; // Start of Authority - final static int TYPE_MB = 7; // Mailbox - final static int TYPE_MG = 8; // Mail Group - final static int TYPE_MR = 9; // Mail Rename - final static int TYPE_NULL = 10; // NULL RR - final static int TYPE_WKS = 11; // Well-known-service - final static int TYPE_PTR = 12; // Domain Name pofinal static inter - final static int TYPE_HINFO = 13; // Host information - final static int TYPE_MINFO = 14; // Mailbox information - final static int TYPE_MX = 15; // Mail exchanger - public final static int TYPE_TXT = 16;// Arbitrary text string - final static int TYPE_RP = 17; // for Responsible Person [RFC1183] - final static int TYPE_AFSDB = 18; // for AFS Data Base location [RFC1183] - final static int TYPE_X25 = 19; // for X.25 PSDN address [RFC1183] - final static int TYPE_ISDN = 20; // for ISDN address [RFC1183] - final static int TYPE_RT = 21; // for Route Through [RFC1183] - final static int TYPE_NSAP = 22; // for NSAP address, NSAP style A record [RFC1706] - final static int TYPE_NSAP_PTR = 23;// - final static int TYPE_SIG = 24; // for security signature [RFC2931] - final static int TYPE_KEY = 25; // for security key [RFC2535] - final static int TYPE_PX = 26; // X.400 mail mapping information [RFC2163] - final static int TYPE_GPOS = 27; // Geographical Position [RFC1712] - final static int TYPE_AAAA = 28; // IP6 Address [Thomson] - final static int TYPE_LOC = 29; // Location Information [Vixie] - final static int TYPE_NXT = 30; // Next Domain - OBSOLETE [RFC2535, RFC3755] - final static int TYPE_EID = 31; // Endpoint Identifier [Patton] - final static int TYPE_NIMLOC = 32; // Nimrod Locator [Patton] - public final static int TYPE_SRV = 33;// Server Selection [RFC2782] - final static int TYPE_ATMA = 34; // ATM Address [Dobrowski] - final static int TYPE_NAPTR = 35; // Naming Authority Pointer [RFC2168, RFC2915] - final static int TYPE_KX = 36; // Key Exchanger [RFC2230] - final static int TYPE_CERT = 37; // CERT [RFC2538] - final static int TYPE_A6 = 38; // A6 [RFC2874] - final static int TYPE_DNAME = 39; // DNAME [RFC2672] - final static int TYPE_SINK = 40; // SINK [Eastlake] - final static int TYPE_OPT = 41; // OPT [RFC2671] - final static int TYPE_APL = 42; // APL [RFC3123] - final static int TYPE_DS = 43; // Delegation Signer [RFC3658] - final static int TYPE_SSHFP = 44; // SSH Key Fingerprint [RFC-ietf-secsh-dns-05.txt] - final static int TYPE_RRSIG = 46; // RRSIG [RFC3755] - final static int TYPE_NSEC = 47; // NSEC [RFC3755] - final static int TYPE_DNSKEY = 48; // DNSKEY [RFC3755] - final static int TYPE_UINFO = 100; // [IANA-Reserved] - final static int TYPE_UID = 101; // [IANA-Reserved] - final static int TYPE_GID = 102; // [IANA-Reserved] - final static int TYPE_UNSPEC = 103; // [IANA-Reserved] - final static int TYPE_TKEY = 249; // Transaction Key [RFC2930] - final static int TYPE_TSIG = 250; // Transaction Signature [RFC2845] - final static int TYPE_IXFR = 251; // Incremental transfer [RFC1995] - final static int TYPE_AXFR = 252; // Transfer of an entire zone [RFC1035] - final static int TYPE_MAILA = 253; // Mailbox-related records (MB, MG or MR) [RFC1035] - final static int TYPE_MAILB = 254; // Mail agent RRs (Obsolete - see MX) [RFC1035] - final static int TYPE_ANY = 255; // Request for all records [RFC1035] - - //Time Intervals for various functions - - //milliseconds before send shared query - final static int SHARED_QUERY_TIME = 20; - //milliseconds between query loops. - final static int QUERY_WAIT_INTERVAL = 225; - //milliseconds between probe loops. - final static int PROBE_WAIT_INTERVAL = 250; - //minimal wait interval for response. - final static int RESPONSE_MIN_WAIT_INTERVAL = 20; - //maximal wait interval for response - final static int RESPONSE_MAX_WAIT_INTERVAL = 115; - //milliseconds to wait after conflict. - final static int PROBE_CONFLICT_INTERVAL = 1000; - //After x tries go 1 time a sec. on probes. - final static int PROBE_THROTTLE_COUNT = 10; - //We only increment the throttle count, if - // the previous increment is inside this interval. - final static int PROBE_THROTTLE_COUNT_INTERVAL = 5000; - //milliseconds between Announce loops. - final static int ANNOUNCE_WAIT_INTERVAL = 1000; - //milliseconds between cache cleanups. - final static int RECORD_REAPER_INTERVAL = 10000; - - final static int KNOWN_ANSWER_TTL = 120; - // 50% of the TTL in milliseconds - final static int ANNOUNCED_RENEWAL_TTL_INTERVAL = DNS_TTL * 500; -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSEntry.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSEntry.java deleted file mode 100644 index 7132756..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSEntry.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.logging.*; - -/** - * DNS entry with a name, type, and class. This is the base - * class for questions and records. - * - * @version %I%, %G% - * @author Arthur van Hoff, Pierre Frisch, Rick Blair - * @author Christian Vincenot - */ -public class DNSEntry -{ - private static Logger logger = Logger.getLogger(DNSEntry.class.toString()); - String key; - String name; - int type; - int clazz; - boolean unique; - - /** - * Create an entry. - */ - DNSEntry(String name, int type, int clazz) - { - this.key = name.toLowerCase(); - this.name = name; - this.type = type; - this.clazz = clazz & DNSConstants.CLASS_MASK; - this.unique = (clazz & DNSConstants.CLASS_UNIQUE) != 0; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - /** - * Check if two entries have exactly the same name, type, and class. - */ - @Override - public boolean equals(Object obj) - { - if (obj instanceof DNSEntry) - { - DNSEntry other = (DNSEntry) obj; - return name.equals(other.name) && - type == other.type && - clazz == other.clazz; - } - return false; - } - - public String getName() - { - return name; - } - - public int getType() - { - return type; - } - - public int getClazz() - { - return clazz; - } - - - public boolean isUnique() - { - return unique; - } - - /** - * Overriden, to return a value which is consistent with the value returned - * by equals(Object). - */ - @Override - public int hashCode() - { - return name.hashCode() + type + clazz; - } - - /** - * Get a string given a clazz. - */ - static String getClazz(int clazz) - { - switch (clazz & DNSConstants.CLASS_MASK) - { - case DNSConstants.CLASS_IN: - return "in"; - case DNSConstants.CLASS_CS: - return "cs"; - case DNSConstants.CLASS_CH: - return "ch"; - case DNSConstants.CLASS_HS: - return "hs"; - case DNSConstants.CLASS_NONE: - return "none"; - case DNSConstants.CLASS_ANY: - return "any"; - default: - return "?"; - } - } - - /** - * Get a string given a type. - */ - static String getType(int type) - { - switch (type) - { - case DNSConstants.TYPE_A: - return "a"; - case DNSConstants.TYPE_AAAA: - return "aaaa"; - case DNSConstants.TYPE_NS: - return "ns"; - case DNSConstants.TYPE_MD: - return "md"; - case DNSConstants.TYPE_MF: - return "mf"; - case DNSConstants.TYPE_CNAME: - return "cname"; - case DNSConstants.TYPE_SOA: - return "soa"; - case DNSConstants.TYPE_MB: - return "mb"; - case DNSConstants.TYPE_MG: - return "mg"; - case DNSConstants.TYPE_MR: - return "mr"; - case DNSConstants.TYPE_NULL: - return "null"; - case DNSConstants.TYPE_WKS: - return "wks"; - case DNSConstants.TYPE_PTR: - return "ptr"; - case DNSConstants.TYPE_HINFO: - return "hinfo"; - case DNSConstants.TYPE_MINFO: - return "minfo"; - case DNSConstants.TYPE_MX: - return "mx"; - case DNSConstants.TYPE_TXT: - return "txt"; - case DNSConstants.TYPE_SRV: - return "srv"; - case DNSConstants.TYPE_ANY: - return "any"; - default: - return "?"; - } - } - - public String toString(String hdr, String other) - { - return hdr + "[" + getType(type) + "," + - getClazz(clazz) + (unique ? "-unique," : ",") + - name + ((other != null) ? "," + - other + "]" : "]"); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSIncoming.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSIncoming.java deleted file mode 100644 index 3dcedc4..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSIncoming.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.logging.*; - -/** - * Parse an incoming DNS message into its components. - * - * @version %I%, %G% - * @author Arthur van Hoff, Werner Randelshofer, Pierre Frisch, Daniel Bobbert - */ -final class DNSIncoming -{ - private static Logger logger = Logger.getLogger(DNSIncoming.class.toString()); - // Implementation note: This vector should be immutable. - // If a client of DNSIncoming changes the contents of this vector, - // we get undesired results. To fix this, we have to migrate to - // the Collections API of Java 1.2. i.e we replace Vector by List. - // final static Vector EMPTY = new Vector(); - - private DatagramPacket packet; - private int off; - private int len; - private byte data[]; - - int id; - private int flags; - private int numQuestions; - int numAnswers; - private int numAuthorities; - private int numAdditionals; - private long receivedTime; - - List questions; - List answers; - - /** - * Parse a message from a datagram packet. - */ - DNSIncoming(DatagramPacket packet) throws IOException - { - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - - this.packet = packet; - this.data = packet.getData(); - this.len = packet.getLength(); - this.off = packet.getOffset(); - this.questions = new LinkedList(); - this.answers = new LinkedList(); - this.receivedTime = System.currentTimeMillis(); - - try - { - id = readUnsignedShort(); - flags = readUnsignedShort(); - numQuestions = readUnsignedShort(); - numAnswers = readUnsignedShort(); - numAuthorities = readUnsignedShort(); - numAdditionals = readUnsignedShort(); - - // parse questions - if (numQuestions > 0) - { - questions = - Collections.synchronizedList( - new ArrayList(numQuestions)); - for (int i = 0; i < numQuestions; i++) - { - DNSQuestion question = - new DNSQuestion( - readName(), - readUnsignedShort(), - readUnsignedShort()); - - questions.add(question); - } - } - - // parse answers - int n = numAnswers + numAuthorities + numAdditionals; - if (n > 0) - { - //System.out.println("JMDNS received "+n+" answers!"); - answers = Collections.synchronizedList( - new ArrayList(n)); - for (int i = 0; i < n; i++) - { - String domain = readName(); - int type = readUnsignedShort(); - int clazz = readUnsignedShort(); - int ttl = readInt(); - int len = readUnsignedShort(); - int end = off + len; - DNSRecord rec = null; - - switch (type) - { - case DNSConstants.TYPE_A: // IPv4 - case DNSConstants.TYPE_AAAA: // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested - rec = new DNSRecord.Address( - domain, type, clazz, ttl, readBytes(off, len)); - break; - case DNSConstants.TYPE_CNAME: - case DNSConstants.TYPE_PTR: - rec = new DNSRecord.Pointer( - domain, type, clazz, ttl, readName()); - break; - case DNSConstants.TYPE_TXT: - rec = new DNSRecord.Text( - domain, type, clazz, ttl, readBytes(off, len)); - break; - case DNSConstants.TYPE_SRV: - //System.out.println("JMDNS: One is a SRV field!!"); - rec = new DNSRecord.Service( domain, - type, - clazz, - ttl, - readUnsignedShort(), - readUnsignedShort(), - readUnsignedShort(), - readName()); - break; - case DNSConstants.TYPE_HINFO: - // Maybe we should do something with those - break; - default : - logger.finer("DNSIncoming() unknown type:" + type); - break; - } - - if (rec != null) - { - // Add a record, if we were able to create one. - answers.add(rec); - } - else - { - // Addjust the numbers for the skipped record - if (answers.size() < numAnswers) - { - numAnswers--; - } - else - { - if (answers.size() < numAnswers + numAuthorities) - { - numAuthorities--; - } - else - { - if (answers.size() < numAnswers + - numAuthorities + - numAdditionals) - { - numAdditionals--; - } - } - } - } - off = end; - } - } - } - catch (IOException e) - { - logger.log(Level.WARNING, - "DNSIncoming() dump " + print(true) + "\n exception ", e); - throw e; - } - } - - /** - * Check if the message is a query. - */ - boolean isQuery() - { - return (flags & DNSConstants.FLAGS_QR_MASK) == - DNSConstants.FLAGS_QR_QUERY; - } - - /** - * Check if the message is truncated. - */ - boolean isTruncated() - { - return (flags & DNSConstants.FLAGS_TC) != 0; - } - - /** - * Check if the message is a response. - */ - boolean isResponse() - { - return (flags & DNSConstants.FLAGS_QR_MASK) == - DNSConstants.FLAGS_QR_RESPONSE; - } - - private int get(int off) throws IOException - { - if ((off < 0) || (off >= len)) - { - throw new IOException("parser error: offset=" + off); - } - return data[off] & 0xFF; - } - - private int readUnsignedShort() throws IOException - { - return (get(off++) << 8) + get(off++); - } - - private int readInt() throws IOException - { - return (readUnsignedShort() << 16) + readUnsignedShort(); - } - - private byte[] readBytes(int off, int len) throws IOException - { - byte bytes[] = new byte[len]; - System.arraycopy(data, off, bytes, 0, len); - return bytes; - } - - private void readUTF(StringBuffer buf, int off, int len) throws IOException - { - for (int end = off + len; off < end;) - { - int ch = get(off++); - switch (ch >> 4) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // 0xxxxxxx - break; - case 12: - case 13: - // 110x xxxx 10xx xxxx - ch = ((ch & 0x1F) << 6) | (get(off++) & 0x3F); - break; - case 14: - // 1110 xxxx 10xx xxxx 10xx xxxx - ch = ((ch & 0x0f) << 12) | - ((get(off++) & 0x3F) << 6) | - (get(off++) & 0x3F); - break; - default: - // 10xx xxxx, 1111 xxxx - ch = ((ch & 0x3F) << 4) | (get(off++) & 0x0f); - break; - } - buf.append((char) ch); - } - } - - private String readName() throws IOException - { - StringBuffer buf = new StringBuffer(); - int off = this.off; - int next = -1; - int first = off; - - while (true) - { - int len = get(off++); - if (len == 0) - { - break; - } - switch (len & 0xC0) - { - case 0x00: - //buf.append("[" + off + "]"); - readUTF(buf, off, len); - off += len; - buf.append('.'); - break; - case 0xC0: - //buf.append("<" + (off - 1) + ">"); - if (next < 0) - { - next = off + 1; - } - off = ((len & 0x3F) << 8) | get(off++); - if (off >= first) - { - throw new IOException( - "bad domain name: possible circular name detected"); - } - first = off; - break; - default: - throw new IOException( - "bad domain name: '" + buf + "' at " + off); - } - } - this.off = (next >= 0) ? next : off; - return buf.toString(); - } - - /** - * Debugging. - */ - String print(boolean dump) - { - StringBuffer buf = new StringBuffer(); - buf.append(toString() + "\n"); - for (Iterator iterator = questions.iterator(); - iterator.hasNext();) - { - buf.append(" ques:" + iterator.next() + "\n"); - } - int count = 0; - for (Iterator iterator = answers.iterator(); - iterator.hasNext(); - count++) - { - if (count < numAnswers) - { - buf.append(" answ:"); - } - else - { - if (count < numAnswers + numAuthorities) - { - buf.append(" auth:"); - } - else - { - buf.append(" addi:"); - } - } - buf.append(iterator.next() + "\n"); - } - if (dump) - { - for (int off = 0, len = packet.getLength(); off < len; off += 32) - { - int n = Math.min(32, len - off); - if (off < 10) - { - buf.append(' '); - } - if (off < 100) - { - buf.append(' '); - } - buf.append(off); - buf.append(':'); - for (int i = 0; i < n; i++) - { - if ((i % 8) == 0) - { - buf.append(' '); - } - buf.append(Integer.toHexString((data[off + i] & 0xF0) >> 4)); - buf.append(Integer.toHexString((data[off + i] & 0x0F) >> 0)); - } - buf.append("\n"); - buf.append(" "); - for (int i = 0; i < n; i++) - { - if ((i % 8) == 0) - { - buf.append(' '); - } - buf.append(' '); - int ch = data[off + i] & 0xFF; - buf.append(((ch > ' ') && (ch < 127)) ? (char) ch : '.'); - } - buf.append("\n"); - - // limit message size - if (off + 32 >= 256) - { - buf.append("....\n"); - break; - } - } - } - return buf.toString(); - } - - @Override - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append(isQuery() ? "dns[query," : "dns[response,"); - if (packet.getAddress() != null) - { - buf.append(packet.getAddress().getHostAddress()); - } - buf.append(':'); - buf.append(packet.getPort()); - buf.append(",len="); - buf.append(packet.getLength()); - buf.append(",id=0x"); - buf.append(Integer.toHexString(id)); - if (flags != 0) - { - buf.append(",flags=0x"); - buf.append(Integer.toHexString(flags)); - if ((flags & DNSConstants.FLAGS_QR_RESPONSE) != 0) - { - buf.append(":r"); - } - if ((flags & DNSConstants.FLAGS_AA) != 0) - { - buf.append(":aa"); - } - if ((flags & DNSConstants.FLAGS_TC) != 0) - { - buf.append(":tc"); - } - } - if (numQuestions > 0) - { - buf.append(",questions="); - buf.append(numQuestions); - } - if (numAnswers > 0) - { - buf.append(",answers="); - buf.append(numAnswers); - } - if (numAuthorities > 0) - { - buf.append(",authorities="); - buf.append(numAuthorities); - } - if (numAdditionals > 0) - { - buf.append(",additionals="); - buf.append(numAdditionals); - } - buf.append("]"); - return buf.toString(); - } - - /** - * Appends answers to this Incoming. - * - * @throws IllegalArgumentException If not a query or if Truncated. - */ - void append(DNSIncoming that) - { - if (this.isQuery() && this.isTruncated() && that.isQuery()) - { - if (that.numQuestions > 0) { - if (Collections.EMPTY_LIST.equals(this.questions)) - this.questions = - Collections.synchronizedList( - new ArrayList(that.numQuestions)); - - this.questions.addAll(that.questions); - this.numQuestions += that.numQuestions; - } - - if (Collections.EMPTY_LIST.equals(answers)) - { - answers = Collections.synchronizedList( - new ArrayList()); - } - - if (that.numAnswers > 0) - { - this.answers.addAll(this.numAnswers, - that.answers.subList(0, that.numAnswers)); - this.numAnswers += that.numAnswers; - } - if (that.numAuthorities > 0) - { - this.answers.addAll(this.numAnswers + this.numAuthorities, - that.answers.subList( - that.numAnswers, - that.numAnswers + that.numAuthorities)); - this.numAuthorities += that.numAuthorities; - } - if (that.numAdditionals > 0) - { - this.answers.addAll( - that.answers.subList( - that.numAnswers + that.numAuthorities, - that.numAnswers + that.numAuthorities + that.numAdditionals)); - this.numAdditionals += that.numAdditionals; - } - } - else - { - throw new IllegalArgumentException(); - } - } - - int elapseSinceArrival() - { - return (int) (System.currentTimeMillis() - receivedTime); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSListener.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSListener.java deleted file mode 100644 index d317953..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -// REMIND: Listener should follow Java idiom for listener or have a different -// name. - -/** - * DNSListener. - * Listener for record updates. - * - * @author Werner Randelshofer, Rick Blair - * @version 1.0 May 22, 2004 Created. - */ -public interface DNSListener -{ - /** - * Update a DNS record. - * @param jmdns - * @param now - * @param record - */ - public void updateRecord(JmDNS jmdns, long now, DNSRecord record); -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSOutgoing.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSOutgoing.java deleted file mode 100644 index 4d099b8..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSOutgoing.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.io.*; -import java.util.*; -import java.util.logging.*; - -/** - * An outgoing DNS message. - * - * @version %I%, %G% - * @author Arthur van Hoff, Rick Blair, Werner Randelshofer - */ -final class DNSOutgoing -{ - private static Logger logger = - Logger.getLogger(DNSOutgoing.class.toString()); - - int id; - int flags; - private boolean multicast; - private int numQuestions; - private int numAnswers; - private int numAuthorities; - private int numAdditionals; - private Hashtable names; - - byte data[]; - int off; - int len; - - /** - * Create an outgoing multicast query or response. - */ - DNSOutgoing(int flags) - { - this(flags, true); - - } - - /** - * Create an outgoing query or response. - */ - DNSOutgoing(int flags, boolean multicast) - { - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - - this.flags = flags; - this.multicast = multicast; - names = new Hashtable(); - data = new byte[DNSConstants.MAX_MSG_TYPICAL]; - off = 12; - } - - /** - * Add a question to the message. - */ - void addQuestion(DNSQuestion rec) throws IOException - { - if (numAnswers > 0 || numAuthorities > 0 || numAdditionals > 0) - { - throw new IllegalStateException("Questions must be added before answers"); - } - numQuestions++; - writeQuestion(rec); - } - - /** - * Add an answer if it is not suppressed. - */ - void addAnswer(DNSIncoming in, DNSRecord rec) throws IOException - { - if (numAuthorities > 0 || numAdditionals > 0) - { - throw new IllegalStateException( - "Answers must be added before authorities and additionals"); - } - if (!rec.suppressedBy(in)) - { - addAnswer(rec, 0); - } - } - - /** - * Add an additional answer to the record. Omit if there is no room. - */ - void addAdditionalAnswer(DNSIncoming in, DNSRecord rec) throws IOException - { - if ((off < DNSConstants.MAX_MSG_TYPICAL - 200) && !rec.suppressedBy(in)) - { - writeRecord(rec, 0); - numAdditionals++; - } - } - - /** - * Add an answer to the message. - */ - void addAnswer(DNSRecord rec, long now) throws IOException - { - if (numAuthorities > 0 || numAdditionals > 0) - { - throw new IllegalStateException( - "Questions must be added before answers"); - } - if (rec != null) - { - if ((now == 0) || !rec.isExpired(now)) - { - writeRecord(rec, now); - numAnswers++; - } - } - } - - private LinkedList authorativeAnswers = new LinkedList(); - - /** - * Add an authorative answer to the message. - */ - void addAuthorativeAnswer(DNSRecord rec) throws IOException - { - if (numAdditionals > 0) - { - throw new IllegalStateException( - "Authorative answers must be added before additional answers"); - } - authorativeAnswers.add(rec); - writeRecord(rec, 0); - numAuthorities++; - - // VERIFY: - - } - - void writeByte(int value) throws IOException - { - if (off >= data.length) - { - throw new IOException("buffer full"); - } - data[off++] = (byte) value; - } - - void writeBytes(String str, int off, int len) throws IOException - { - for (int i = 0; i < len; i++) - { - writeByte(str.charAt(off + i)); - } - } - - void writeBytes(byte data[]) throws IOException - { - if (data != null) - { - writeBytes(data, 0, data.length); - } - } - - void writeBytes(byte data[], int off, int len) throws IOException - { - for (int i = 0; i < len; i++) - { - writeByte(data[off + i]); - } - } - - void writeShort(int value) throws IOException - { - writeByte(value >> 8); - writeByte(value); - } - - void writeInt(int value) throws IOException - { - writeShort(value >> 16); - writeShort(value); - } - - void writeUTF(String str, int off, int len) throws IOException - { - // compute utf length - int utflen = 0; - for (int i = 0; i < len; i++) - { - int ch = str.charAt(off + i); - if ((ch >= 0x0001) && (ch <= 0x007F)) - { - utflen += 1; - } - else - { - if (ch > 0x07FF) - { - utflen += 3; - } - else - { - utflen += 2; - } - } - } - // write utf length - writeByte(utflen); - // write utf data - for (int i = 0; i < len; i++) - { - int ch = str.charAt(off + i); - if ((ch >= 0x0001) && (ch <= 0x007F)) - { - writeByte(ch); - } - else - { - if (ch > 0x07FF) - { - writeByte(0xE0 | ((ch >> 12) & 0x0F)); - writeByte(0x80 | ((ch >> 6) & 0x3F)); - writeByte(0x80 | ((ch >> 0) & 0x3F)); - } - else - { - writeByte(0xC0 | ((ch >> 6) & 0x1F)); - writeByte(0x80 | ((ch >> 0) & 0x3F)); - } - } - } - } - - void writeName(String name) throws IOException - { - while (true) - { - int n = name.indexOf('.'); - if (n < 0) - { - n = name.length(); - } - if (n <= 0) - { - writeByte(0); - return; - } - Integer offset = names.get(name); - if (offset != null) - { - int val = offset.intValue(); - - if (val > off) - { - logger.log(Level.WARNING, - "DNSOutgoing writeName failed val=" + val + " name=" + name); - } - - writeByte((val >> 8) | 0xC0); - writeByte(val); - return; - } - names.put(name, off); - writeUTF(name, 0, n); - name = name.substring(n); - if (name.startsWith(".")) - { - name = name.substring(1); - } - } - } - - void writeQuestion(DNSQuestion question) throws IOException - { - writeName(question.name); - writeShort(question.type); - writeShort(question.clazz); - } - - void writeRecord(DNSRecord rec, long now) throws IOException - { - int save = off; - try - { - writeName(rec.name); - writeShort(rec.type); - writeShort(rec.clazz | - ((rec.unique && multicast) ? DNSConstants.CLASS_UNIQUE : 0)); - writeInt((now == 0) ? rec.ttl : rec.getRemainingTTL(now)); - writeShort(0); - int start = off; - rec.write(this); - int len = off - start; - data[start - 2] = (byte) (len >> 8); - data[start - 1] = (byte) (len & 0xFF); - } - catch (IOException e) - { - off = save; - throw e; - } - } - - /** - * Finish the message before sending it off. - */ - void finish() throws IOException - { - int save = off; - off = 0; - - writeShort(multicast ? 0 : id); - writeShort(flags); - writeShort(numQuestions); - writeShort(numAnswers); - writeShort(numAuthorities); - writeShort(numAdditionals); - off = save; - } - - boolean isQuery() - { - return (flags & DNSConstants.FLAGS_QR_MASK) == - DNSConstants.FLAGS_QR_QUERY; - } - - public boolean isEmpty() - { - return numQuestions == 0 && numAuthorities == 0 - && numAdditionals == 0 && numAnswers == 0; - } - - - @Override - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append(isQuery() ? "dns[query," : "dns[response,"); - //buf.append(packet.getAddress().getHostAddress()); - buf.append(':'); - //buf.append(packet.getPort()); - //buf.append(",len="); - //buf.append(packet.getLength()); - buf.append(",id=0x"); - buf.append(Integer.toHexString(id)); - if (flags != 0) - { - buf.append(",flags=0x"); - buf.append(Integer.toHexString(flags)); - if ((flags & DNSConstants.FLAGS_QR_RESPONSE) != 0) - { - buf.append(":r"); - } - if ((flags & DNSConstants.FLAGS_AA) != 0) - { - buf.append(":aa"); - } - if ((flags & DNSConstants.FLAGS_TC) != 0) - { - buf.append(":tc"); - } - } - if (numQuestions > 0) - { - buf.append(",questions="); - buf.append(numQuestions); - } - if (numAnswers > 0) - { - buf.append(",answers="); - buf.append(numAnswers); - } - if (numAuthorities > 0) - { - buf.append(",authorities="); - buf.append(numAuthorities); - } - if (numAdditionals > 0) - { - buf.append(",additionals="); - buf.append(numAdditionals); - } - buf.append(",\nnames=" + names); - buf.append(",\nauthorativeAnswers=" + authorativeAnswers); - - buf.append("]"); - return buf.toString(); - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSQuestion.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSQuestion.java deleted file mode 100644 index f6abaa7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSQuestion.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.logging.*; - -/** - * A DNS question. - * - * @version %I%, %G% - * @author Arthur van Hoff - */ -public final class DNSQuestion - extends DNSEntry -{ - private static Logger logger = - Logger.getLogger(DNSQuestion.class.toString()); - - /** - * Create a question. - * @param name - * @param type - * @param clazz - */ - public DNSQuestion(String name, int type, int clazz) - { - super(name, type, clazz); - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - /** - * Check if this question is answered by a given DNS record. - */ - boolean answeredBy(DNSRecord rec) - { - return (clazz == rec.clazz) && - ((type == rec.type) || - (type == DNSConstants.TYPE_ANY)) && - name.equals(rec.name); - } - - /** - * For debugging only. - */ - @Override - public String toString() - { - return toString("question", null); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSRecord.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSRecord.java deleted file mode 100644 index 673bbc4..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSRecord.java +++ /dev/null @@ -1,796 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.io.*; -import java.net.*; -import java.util.logging.*; - -/** - * DNS record - * - * @version %I%, %G% - * @author Arthur van Hoff, Rick Blair, Werner Randelshofer, Pierre Frisch - */ -public abstract class DNSRecord extends DNSEntry -{ - private static Logger logger = - Logger.getLogger(DNSRecord.class.toString()); - int ttl; - private long created; - - /** - * Create a DNSRecord with a name, type, clazz, and ttl. - */ - DNSRecord(String name, int type, int clazz, int ttl) - { - super(name, type, clazz); - this.ttl = ttl; - this.created = System.currentTimeMillis(); - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - /** - * True if this record is the same as some other record. - * @param other obj to be compared to. - */ - @Override - public boolean equals(Object other) - { - return (other instanceof DNSRecord) && sameAs((DNSRecord) other); - } - - /** - * True if this record is the same as some other record. - */ - boolean sameAs(DNSRecord other) - { - return super.equals(other) && sameValue(other); - } - - /** - * True if this record has the same value as some other record. - */ - abstract boolean sameValue(DNSRecord other); - - /** - * True if this record has the same type as some other record. - */ - boolean sameType(DNSRecord other) - { - return type == other.type; - } - - /** - * Handles a query represented by this record. - * - * @return Returns true if a conflict with one of the services registered - * with JmDNS or with the hostname occured. - */ - abstract boolean handleQuery(JmDNS dns, long expirationTime); - - /** - * Handles a responserepresented by this record. - * - * @return Returns true if a conflict with one of the services registered - * with JmDNS or with the hostname occured. - */ - abstract boolean handleResponse(JmDNS dns); - - /** - * Adds this as an answer to the provided outgoing datagram. - */ - abstract DNSOutgoing addAnswer(JmDNS dns, DNSIncoming in, InetAddress addr, - int port, DNSOutgoing out) - throws IOException; - - /** - * True if this record is suppressed by the answers in a message. - */ - boolean suppressedBy(DNSIncoming msg) - { - try - { - for (int i = msg.numAnswers; i-- > 0;) - { - if (suppressedBy(msg.answers.get(i))) - { - return true; - } - } - return false; - } - catch (ArrayIndexOutOfBoundsException e) - { - logger.log(Level.WARNING, - "suppressedBy() message " + msg + " exception ", e); - // msg.print(true); - return false; - } - } - - /** - * True if this record would be supressed by an answer. - * This is the case if this record would not have a - * significantly longer TTL. - */ - boolean suppressedBy(DNSRecord other) - { - if (sameAs(other) && (other.ttl > ttl / 2)) - { - return true; - } - return false; - } - - /** - * Get the expiration time of this record. - */ - long getExpirationTime(int percent) - { - return created + (percent * ttl * 10L); - } - - /** - * Get the remaining TTL for this record. - */ - int getRemainingTTL(long now) - { - return (int) Math.max(0, (getExpirationTime(100) - now) / 1000); - } - - /** - * Check if the record is expired. - */ - boolean isExpired(long now) - { - return getExpirationTime(100) <= now; - } - - /** - * Check if the record is stale, ie it has outlived - * more than half of its TTL. - */ - boolean isStale(long now) - { - return getExpirationTime(50) <= now; - } - - /** - * Reset the TTL of a record. This avoids having to - * update the entire record in the cache. - */ - void resetTTL(DNSRecord other) - { - created = other.created; - ttl = other.ttl; - } - - /** - * Write this record into an outgoing message. - */ - abstract void write(DNSOutgoing out) throws IOException; - - /** - * Address record. - */ - static class Address extends DNSRecord - { - private static Logger logger = - Logger.getLogger(Address.class.toString()); - InetAddress addr; - - Address(String name, int type, int clazz, int ttl, InetAddress addr) - { - super(name, type, clazz, ttl); - this.addr = addr; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - Address(String name, int type, int clazz, int ttl, byte[] rawAddress) - { - super(name, type, clazz, ttl); - try - { - this.addr = InetAddress.getByAddress(rawAddress); - } - catch (UnknownHostException exception) - { - logger.log(Level.WARNING, "Address() exception ", exception); - } - } - - @Override - void write(DNSOutgoing out) throws IOException - { - if (addr != null) - { - byte[] buffer = addr.getAddress(); - if (DNSConstants.TYPE_A == type) - { - // If we have a type A records we should - // answer with a IPv4 address - if (addr instanceof Inet4Address) - { - // All is good - } - else - { - // Get the last four bytes - byte[] tempbuffer = buffer; - buffer = new byte[4]; - System.arraycopy(tempbuffer, 12, buffer, 0, 4); - } - } - else - { - // If we have a type AAAA records we should - // answer with a IPv6 address - if (addr instanceof Inet4Address) - { - byte[] tempbuffer = buffer; - buffer = new byte[16]; - for (int i = 0; i < 16; i++) - { - if (i < 11) - { - buffer[i] = tempbuffer[i - 12]; - } - else - { - buffer[i] = 0; - } - } - } - } - int length = buffer.length; - out.writeBytes(buffer, 0, length); - } - } - - boolean same(DNSRecord other) - { - return ((sameName(other)) && ((sameValue(other)))); - } - - boolean sameName(DNSRecord other) - { - return name.equalsIgnoreCase(((Address) other).name); - } - - @Override - boolean sameValue(DNSRecord other) - { - return addr.equals(((Address) other).getAddress()); - } - - InetAddress getAddress() - { - return addr; - } - - /** - * Creates a byte array representation of this record. - * This is needed for tie-break tests according to - * draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2. - */ - private byte[] toByteArray() - { - try - { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - DataOutputStream dout = new DataOutputStream(bout); - dout.write(name.getBytes("UTF8")); - dout.writeShort(type); - dout.writeShort(clazz); - //dout.writeInt(len); - byte[] buffer = addr.getAddress(); - for (int i = 0; i < buffer.length; i++) - { - dout.writeByte(buffer[i]); - } - dout.close(); - return bout.toByteArray(); - } - catch (IOException e) - { - throw new InternalError(); - } - } - - /** - * Does a lexicographic comparison of the byte array representation - * of this record and that record. - * This is needed for tie-break tests according to - * draft-cheshire-dnsext-multicastdns-04.txt chapter 9.2. - */ - private int lexCompare(DNSRecord.Address that) - { - byte[] thisBytes = this.toByteArray(); - byte[] thatBytes = that.toByteArray(); - for ( int i = 0, n = Math.min(thisBytes.length, thatBytes.length); - i < n; - i++) - { - if (thisBytes[i] > thatBytes[i]) - { - return 1; - } - else - { - if (thisBytes[i] < thatBytes[i]) - { - return -1; - } - } - } - return thisBytes.length - thatBytes.length; - } - - /** - * Does the necessary actions, when this as a query. - */ - @Override - boolean handleQuery(JmDNS dns, long expirationTime) - { - DNSRecord.Address dnsAddress = - dns.getLocalHost().getDNSAddressRecord(this); - if (dnsAddress != null) - { - if (dnsAddress.sameType(this) && - dnsAddress.sameName(this) && - (!dnsAddress.sameValue(this))) - { - logger.finer( - "handleQuery() Conflicting probe detected. dns state " + - dns.getState() + - " lex compare " + lexCompare(dnsAddress)); - // Tie-breaker test - if (dns.getState().isProbing() && lexCompare(dnsAddress) >= 0) - { - // We lost the tie-break. We have to choose a different name. - dns.getLocalHost().incrementHostName(); - dns.getCache().clear(); - for (ServiceInfo info : dns.services.values()) - info.revertState(); - } - dns.revertState(); - return true; - } - } - return false; - } - - /** - * Does the necessary actions, when this as a response. - */ - @Override - boolean handleResponse(JmDNS dns) - { - DNSRecord.Address dnsAddress = - dns.getLocalHost().getDNSAddressRecord(this); - if (dnsAddress != null) - { - if (dnsAddress.sameType(this) && - dnsAddress.sameName(this) && - (!dnsAddress.sameValue(this))) - { - logger.finer("handleResponse() Denial detected"); - - if (dns.getState().isProbing()) - { - dns.getLocalHost().incrementHostName(); - dns.getCache().clear(); - for (ServiceInfo info : dns.services.values()) - info.revertState(); - } - dns.revertState(); - return true; - } - } - return false; - } - - @Override - DNSOutgoing addAnswer(JmDNS dns, - DNSIncoming in, - InetAddress addr, - int port, - DNSOutgoing out) - throws IOException - { - return out; - } - - @Override - public String toString() - { - return toString(" address '" + - (addr != null ? addr.getHostAddress() : "null") + "'"); - } - - } - - /** - * Pointer record. - */ - static class Pointer extends DNSRecord - { - private static Logger logger = - Logger.getLogger(Pointer.class.toString()); - String alias; - - Pointer(String name, int type, int clazz, int ttl, String alias) - { - super(name, type, clazz, ttl); - this.alias = alias; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - @Override - void write(DNSOutgoing out) throws IOException - { - out.writeName(alias); - } - - @Override - boolean sameValue(DNSRecord other) - { - return alias.equals(((Pointer) other).alias); - } - - @Override - boolean handleQuery(JmDNS dns, long expirationTime) - { - // Nothing to do (?) - // I think there is no possibility - // for conflicts for this record type? - return false; - } - - @Override - boolean handleResponse(JmDNS dns) - { - // Nothing to do (?) - // I think there is no possibility for conflicts for this record type? - return false; - } - - String getAlias() - { - return alias; - } - - @Override - DNSOutgoing addAnswer(JmDNS dns, - DNSIncoming in, - InetAddress addr, - int port, - DNSOutgoing out) - throws IOException - { - return out; - } - - @Override - public String toString() - { - return toString(alias); - } - } - - static class Text extends DNSRecord - { - private static Logger logger = - Logger.getLogger(Text.class.toString()); - byte text[]; - - Text(String name, int type, int clazz, int ttl, byte text[]) - { - super(name, type, clazz, ttl); - this.text = text; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - @Override - void write(DNSOutgoing out) throws IOException - { - out.writeBytes(text, 0, text.length); - } - - @Override - boolean sameValue(DNSRecord other) - { - Text txt = (Text) other; - if (txt.text.length != text.length) - { - return false; - } - for (int i = text.length; i-- > 0;) - { - if (txt.text[i] != text[i]) - { - return false; - } - } - return true; - } - - @Override - boolean handleQuery(JmDNS dns, long expirationTime) - { - // Nothing to do (?) - // I think there is no possibility for conflicts for this record type? - return false; - } - - @Override - boolean handleResponse(JmDNS dns) - { - // Nothing to do (?) - // Shouldn't we care if we get a conflict at this level? - /* - ServiceInfo info = (ServiceInfo) dns.services.get(name.toLowerCase()); - if (info != null) - { - if (! Arrays.equals(text,info.text)) - { - info.revertState(); - return true; - } - } - */ - return false; - } - - @Override - DNSOutgoing addAnswer(JmDNS dns, - DNSIncoming in, - InetAddress addr, - int port, - DNSOutgoing out) - throws IOException - { - return out; - } - - @Override - public String toString() - { - return toString((text.length > 10) ? - new String(text, 0, 7) + "..." : - new String(text)); - } - } - - /** - * Service record. - */ - static class Service extends DNSRecord - { - private static Logger logger = - Logger.getLogger(Service.class.toString()); - int priority; - int weight; - int port; - String server; - - Service(String name, - int type, - int clazz, - int ttl, - int priority, - int weight, - int port, - String server) - { - super(name, type, clazz, ttl); - this.priority = priority; - this.weight = weight; - this.port = port; - this.server = server; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - @Override - void write(DNSOutgoing out) throws IOException - { - out.writeShort(priority); - out.writeShort(weight); - out.writeShort(port); - out.writeName(server); - } - - private byte[] toByteArray() - { - try - { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - DataOutputStream dout = new DataOutputStream(bout); - dout.write(name.getBytes("UTF8")); - dout.writeShort(type); - dout.writeShort(clazz); - //dout.writeInt(len); - dout.writeShort(priority); - dout.writeShort(weight); - dout.writeShort(port); - dout.write(server.getBytes("UTF8")); - dout.close(); - return bout.toByteArray(); - } - catch (IOException e) - { - throw new InternalError(); - } - } - - private int lexCompare(DNSRecord.Service that) - { - byte[] thisBytes = this.toByteArray(); - byte[] thatBytes = that.toByteArray(); - for (int i = 0, n = Math.min(thisBytes.length, thatBytes.length); - i < n; - i++) - { - if (thisBytes[i] > thatBytes[i]) - { - return 1; - } - else - { - if (thisBytes[i] < thatBytes[i]) - { - return -1; - } - } - } - return thisBytes.length - thatBytes.length; - } - - @Override - boolean sameValue(DNSRecord other) - { - Service s = (Service) other; - return (priority == s.priority) && - (weight == s.weight) && - (port == s.port) && - server.equals(s.server); - } - - @Override - boolean handleQuery(JmDNS dns, long expirationTime) - { - ServiceInfo info = dns.services.get(name.toLowerCase()); - if (info != null && - (port != info.port || - !server.equalsIgnoreCase(dns.getLocalHost().getName()))) - { - logger.finer("handleQuery() Conflicting probe detected"); - - // Tie breaker test - if (info.getState().isProbing() && - lexCompare(new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - dns.getLocalHost().getName())) >= 0) - { - // We lost the tie break - String oldName = info.getQualifiedName().toLowerCase(); - info.setName(dns.incrementName(info.getName())); - dns.services.remove(oldName); - dns.services.put(info.getQualifiedName().toLowerCase(), info); - logger.finer( - "handleQuery() Lost tie break: new unique name chosen:" + info.getName()); - - } - info.revertState(); - return true; - - } - return false; - } - - @Override - boolean handleResponse(JmDNS dns) - { - ServiceInfo info = dns.services.get(name.toLowerCase()); - if (info != null && - (port != info.port || !server.equalsIgnoreCase(dns.getLocalHost().getName()))) - { - logger.finer("handleResponse() Denial detected"); - - if (info.getState().isProbing()) - { - String oldName = info.getQualifiedName().toLowerCase(); - info.setName(dns.incrementName(info.getName())); - dns.services.remove(oldName); - dns.services.put(info.getQualifiedName().toLowerCase(), info); - logger.finer( - "handleResponse() New unique name chose:" + info.getName()); - - } - info.revertState(); - return true; - } - return false; - } - - @Override - DNSOutgoing addAnswer(JmDNS dns, - DNSIncoming in, - InetAddress addr, - int port, - DNSOutgoing out) - throws IOException - { - ServiceInfo info = dns.services.get(name.toLowerCase()); - if (info != null) - { - if (this.port == info.port != server.equals(dns.getLocalHost().getName())) - { - return dns.addAnswer(in, addr, port, out, - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - dns.getLocalHost().getName())); - } - } - return out; - } - - @Override - public String toString() - { - return toString(server + ":" + port); - } - } - - public String toString(String other) - { - return toString("record", ttl + "/" + - getRemainingTTL(System.currentTimeMillis()) -// + "," + other - ); - } -} - diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSState.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSState.java deleted file mode 100644 index 5016050..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/DNSState.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.*; -import java.util.logging.*; - -/** - * DNSState defines the possible states for services registered with JmDNS. - * - * @author Werner Randelshofer, Rick Blair - * @version 1.0 May 23, 2004 Created. - */ -public class DNSState - implements Comparable -{ - private static Logger logger = - Logger.getLogger(DNSState.class.toString()); - - private final String name; - - /** - * Ordinal of next state to be created. - */ - private static int nextOrdinal = 0; - /** - * Assign an ordinal to this state. - */ - private final int ordinal = nextOrdinal++; - /** - * Logical sequence of states. - * The sequence is consistent with the ordinal of a state. - * This is used for advancing through states. - */ - private final static ArrayList sequence - = new ArrayList(); - - private DNSState(String name) - { - this.name = name; - sequence.add(this); - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - @Override - public final String toString() - { - return name; - } - - public static final DNSState PROBING_1 = new DNSState("probing 1"); - public static final DNSState PROBING_2 = new DNSState("probing 2"); - public static final DNSState PROBING_3 = new DNSState("probing 3"); - public static final DNSState ANNOUNCING_1 = new DNSState("announcing 1"); - public static final DNSState ANNOUNCING_2 = new DNSState("announcing 2"); - public static final DNSState ANNOUNCED = new DNSState("announced"); - public static final DNSState CANCELED = new DNSState("canceled"); - - /** - * Returns the next advanced state. - * In general, this advances one step in the following sequence: PROBING_1, - * PROBING_2, PROBING_3, ANNOUNCING_1, ANNOUNCING_2, ANNOUNCED. - * Does not advance for ANNOUNCED and CANCELED state. - * @return Returns the next advanced state. - */ - public final DNSState advance() - { - return (isProbing() || isAnnouncing()) ? - sequence.get(ordinal + 1) : - this; - } - - /** - * Returns to the next reverted state. - * All states except CANCELED revert to PROBING_1. - * Status CANCELED does not revert. - * @return Returns to the next reverted state. - */ - public final DNSState revert() - { - return (this == CANCELED) ? this : PROBING_1; - } - - /** - * Returns true, if this is a probing state. - * @return Returns true, if this is a probing state. - */ - public boolean isProbing() - { - return compareTo(PROBING_1) >= 0 && compareTo(PROBING_3) <= 0; - } - - /** - * Returns true, if this is an announcing state. - * @return Returns true, if this is an announcing state. - */ - public boolean isAnnouncing() - { - return compareTo(ANNOUNCING_1) >= 0 && compareTo(ANNOUNCING_2) <= 0; - } - - /** - * Returns true, if this is an announced state. - * @return Returns true, if this is an announced state. - */ - public boolean isAnnounced() - { - return compareTo(ANNOUNCED) == 0; - } - - /** - * Compares two states. - * The states compare as follows: - * PROBING_1 < PROBING_2 < PROBING_3 < ANNOUNCING_1 < - * ANNOUNCING_2 < RESPONDING < ANNOUNCED < CANCELED. - */ - public int compareTo(DNSState state) - { - return ordinal - state.ordinal; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/HostInfo.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/HostInfo.java deleted file mode 100644 index 644afc9..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/HostInfo.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.net.*; -import java.util.logging.*; - - -/** - * HostInfo information on the local host to be able to cope with change of addresses. - * - * @version %I%, %G% - * @author Pierre Frisch, Werner Randelshofer - */ -class HostInfo -{ - private static Logger logger = Logger.getLogger(HostInfo.class.toString()); - protected String name; - protected InetAddress address; - protected NetworkInterface interfaze; - /** - * This is used to create a unique name for the host name. - */ - private int hostNameCount; - - public HostInfo(InetAddress address, String name) - { - super(); - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - - this.address = address; - this.name = name; - if (address != null) - { - try - { - interfaze = NetworkInterface.getByInetAddress(address); - } - catch (Exception exception) - { - // FIXME Shouldn't we take an action here? - logger.log(Level.WARNING, - "LocalHostInfo() exception ", exception); - } - } - } - - public String getName() - { - return name; - } - - public InetAddress getAddress() - { - return address; - } - - public NetworkInterface getInterface() - { - return interfaze; - } - - synchronized String incrementHostName() - { - hostNameCount++; - int plocal = name.indexOf(".local."); - int punder = name.lastIndexOf("-"); - name = name.substring(0, (punder == -1 ? plocal : punder)) + "-" + - hostNameCount + ".local."; - return name; - } - - boolean shouldIgnorePacket(DatagramPacket packet) - { - boolean result = false; - if (getAddress() != null) - { - InetAddress from = packet.getAddress(); - if (from != null) - { - if (from.isLinkLocalAddress() && - (!getAddress().isLinkLocalAddress())) - { - // Ignore linklocal packets on regular interfaces, unless this is - // also a linklocal interface. This is to avoid duplicates. This is - // a terrible hack caused by the lack of an API to get the address - // of the interface on which the packet was received. - result = true; - } - if (from.isLoopbackAddress() && - (!getAddress().isLoopbackAddress())) - { - // Ignore loopback packets on a regular interface unless this is - // also a loopback interface. - result = true; - } - } - } - return result; - } - - DNSRecord.Address getDNSAddressRecord(DNSRecord.Address address) - { - return (DNSConstants.TYPE_AAAA == address.type ? - getDNS6AddressRecord() : - getDNS4AddressRecord()); - } - - DNSRecord.Address getDNS4AddressRecord() - { - if ((getAddress() != null) && - ((getAddress() instanceof Inet4Address) || - ((getAddress() instanceof Inet6Address) && - (((Inet6Address) getAddress()).isIPv4CompatibleAddress())))) - { - return new DNSRecord.Address(getName(), - DNSConstants.TYPE_A, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, getAddress()); - } - return null; - } - - DNSRecord.Address getDNS6AddressRecord() - { - if ((getAddress() != null) && (getAddress() instanceof Inet6Address)) - { - return new DNSRecord.Address( - getName(), - DNSConstants.TYPE_AAAA, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - getAddress()); - } - return null; - } - - @Override - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append("local host info["); - buf.append(getName() != null ? getName() : "no name"); - buf.append(", "); - buf.append(getInterface() != null ? - getInterface().getDisplayName() : - "???"); - buf.append(":"); - buf.append(getAddress() != null ? - getAddress().getHostAddress() : - "no address"); - buf.append("]"); - return buf.toString(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/JmDNS.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/JmDNS.java deleted file mode 100644 index 96420ba..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/JmDNS.java +++ /dev/null @@ -1,3048 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.io.*; -import java.net.*; -import java.util.*; - -import net.java.sip.communicator.util.*; - -// REMIND: multiple IP addresses - -/** - * mDNS implementation in Java. - * - * @version %I%, %G% - * @author Arthur van Hoff, Rick Blair, Jeff Sonstein, - * Werner Randelshofer, Pierre Frisch, Scott Lewis - * @author Christian Vincenot - */ -public class JmDNS -{ - private static final Logger logger - = Logger.getLogger(JmDNS.class); - - /** - * The version of JmDNS. - */ - public static String VERSION = "2.0"; - - /** - * This is the multicast group, we are listening to for - * multicast DNS messages. - */ - private InetAddress group; - /** - * This is our multicast socket. - */ - private MulticastSocket socket; - - /** - * Used to fix live lock problem on unregester. - */ - - protected boolean closed = false; - - /** - * Holds instances of JmDNS.DNSListener. - * Must by a synchronized collection, because it is updated from - * concurrent threads. - */ - private List listeners; - /** - * Holds instances of ServiceListener's. - * Keys are Strings holding a fully qualified service type. - * Values are LinkedList's of ServiceListener's. - */ - private Map> serviceListeners; - /** - * Holds instances of ServiceTypeListener's. - */ - private List typeListeners; - - - /** - * Cache for DNSEntry's. - */ - private DNSCache cache; - - /** - * This hashtable holds the services that have been registered. - * Keys are instances of String which hold an all lower-case version of the - * fully qualified service name. - * Values are instances of ServiceInfo. - */ - Map services; - - /** - * This hashtable holds the service types that have been registered or - * that have been received in an incoming datagram. - * Keys are instances of String which hold an all lower-case version of the - * fully qualified service type. - * Values hold the fully qualified service type. - */ - Map serviceTypes; - - /** - * Handle on the local host - */ - HostInfo localHost; - - private Thread incomingListener = null; - - /** - * Throttle count. - * This is used to count the overall number of probes sent by JmDNS. - * When the last throttle increment happened . - */ - private int throttle; - /** - * Last throttle increment. - */ - private long lastThrottleIncrement; - - /** - * The timer is used to dispatch all outgoing messages of JmDNS. - * It is also used to dispatch maintenance tasks for the DNS cache. - */ - private Timer timer; - - /** - * The source for random values. - * This is used to introduce random delays in responses. This reduces the - * potential for collisions on the network. - */ - private final static Random random = new Random(); - - /** - * This lock is used to coordinate processing of incoming and outgoing - * messages. This is needed, because the Rendezvous Conformance Test - * does not forgive race conditions. - */ - private Object ioLock = new Object(); - - /** - * If an incoming package which needs an answer is truncated, we store it - * here. We add more incoming DNSRecords to it, until the JmDNS.Responder - * timer picks it up. - * Remind: This does not work well with multiple planned answers for packages - * that came in from different clients. - */ - private DNSIncoming plannedAnswer; - - // State machine - /** - * The state of JmDNS. - *

    - * For proper handling of concurrency, this variable must be - * changed only using methods advanceState(), revertState() and cancel(). - */ - private DNSState state = DNSState.PROBING_1; - - /** - * Timer task associated to the host name. - * This is used to prevent from having multiple tasks associated to the host - * name at the same time. - */ - TimerTask task; - - /** - * This hashtable is used to maintain a list of service types being collected - * by this JmDNS instance. - * The key of the hashtable is a service type name, the value is an instance - * of JmDNS.ServiceCollector. - * - * @see #list - */ - private HashMap serviceCollectors = new HashMap(); - - /** - * Create an instance of JmDNS. - * @throws java.io.IOException - */ - public JmDNS() - throws IOException - { - //String SLevel = System.getProperty("jmdns.debug"); - - if (logger.isDebugEnabled()) - logger.debug("JmDNS instance created"); - try - { - InetAddress addr = InetAddress.getLocalHost(); - // [PJYF Oct 14 2004] Why do we disallow the loopback address? - init(addr.isLoopbackAddress() ? null : addr, addr.getHostName()); - } - catch (IOException exc) - { - logger.error("Failed to get a reference to localhost", exc); - init(null, "computer"); - } - } - - /** - * Create an instance of JmDNS and bind it to a - * specific network interface given its IP-address. - * @param addr - * @throws java.io.IOException - */ - public JmDNS(InetAddress addr) - throws IOException - { - try - { - init(addr, addr.getHostName()); - } - catch (IOException e) - { - init(null, "computer"); - } - } - - /** - * Initialize everything. - * - * @param address The interface to which JmDNS binds to. - * @param name The host name of the interface. - */ - private void init(InetAddress address, String name) throws IOException - { - // A host name with "." is illegal. - // so strip off everything and append .local. - int idx = name.indexOf("."); - if (idx > 0) - { - name = name.substring(0, idx); - } - name += ".local."; - // localHost to IP address binding - localHost = new HostInfo(address, name); - - cache = new DNSCache(100); - - listeners = Collections.synchronizedList(new ArrayList()); - serviceListeners = new HashMap>(); - typeListeners = new ArrayList(); - - services = new Hashtable(20); - serviceTypes = new Hashtable(20); - - // REMIND: If I could pass in a name for the Timer thread, - // I would pass 'JmDNS.Timer'. - timer = new Timer(); - new RecordReaper().start(); - - incomingListener = new Thread( - new SocketListener(), "JmDNS.SocketListener"); - incomingListener.setDaemon(true); - // Bind to multicast socket - openMulticastSocket(localHost); - start(services.values()); - } - - private void start(Collection serviceInfos) - { - state = DNSState.PROBING_1; - incomingListener.start(); - new Prober().start(); - for (ServiceInfo serviceInfo : serviceInfos) - { - try - { - registerService(new ServiceInfo(serviceInfo)); - } - catch (Exception exception) - { - logger.warn("start() Registration exception ", exception); - } - } - } - - private void openMulticastSocket(HostInfo hostInfo) throws IOException - { - if (group == null) - { - group = InetAddress.getByName(DNSConstants.MDNS_GROUP); - } - if (socket != null) - { - this.closeMulticastSocket(); - } - socket = new MulticastSocket(DNSConstants.MDNS_PORT); - if ((hostInfo != null) && (localHost.getInterface() != null)) - { - socket.setNetworkInterface(hostInfo.getInterface()); - } - socket.setTimeToLive(255); - socket.joinGroup(group); - } - - private void closeMulticastSocket() - { - if (logger.isDebugEnabled()) - logger.debug("closeMulticastSocket()"); - if (socket != null) - { - // close socket - try - { - socket.leaveGroup(group); - socket.close(); - if (incomingListener != null) - { - incomingListener.join(); - } - } - catch (Exception exception) - { - logger.warn("closeMulticastSocket() Close socket exception ", - exception); - } - socket = null; - } - } - - // State machine - /** - * Sets the state and notifies all objects that wait on JmDNS. - */ - synchronized void advanceState() - { - state = state.advance(); - notifyAll(); - } - - /** - * Sets the state and notifies all objects that wait on JmDNS. - */ - synchronized void revertState() - { - state = state.revert(); - notifyAll(); - } - - /** - * Sets the state and notifies all objects that wait on JmDNS. - */ - synchronized void cancel() - { - state = DNSState.CANCELED; - notifyAll(); - } - - /** - * Returns the current state of this info. - */ - DNSState getState() - { - return state; - } - - - /** - * Return the DNSCache associated with the cache variable - */ - DNSCache getCache() - { - return cache; - } - - /** - * Return the HostName associated with this JmDNS instance. - * Note: May not be the same as what started. The host name is subject to - * negotiation. - * @return Return the HostName associated with this JmDNS instance. - */ - public String getHostName() - { - return localHost.getName(); - } - - public HostInfo getLocalHost() - { - return localHost; - } - - /** - * Return the address of the interface to which this instance of JmDNS is - * bound. - * @return Return the address of the interface to which this instance - * of JmDNS is bound. - * @throws java.io.IOException - */ - public InetAddress getInterface() - throws IOException - { - return socket.getInterface(); - } - - /** - * Get service information. If the information is not cached, the method - * will block until updated information is received. - *

    - * Usage note: Do not call this method from the AWT event dispatcher thread. - * You will make the user interface unresponsive. - * - * @param type fully qualified service type, - * such as _http._tcp.local. . - * @param name unqualified service name, such as foobar . - * @return null if the service information cannot be obtained - */ - public ServiceInfo getServiceInfo(String type, String name) - { - return getServiceInfo(type, name, 3 * 1000); - } - - /** - * Get service information. If the information is not cached, the method - * will block for the given timeout until updated information is received. - *

    - * Usage note: If you call this method from the AWT event dispatcher thread, - * use a small timeout, or you will make the user interface unresponsive. - * - * @param type full qualified service type, - * such as _http._tcp.local. . - * @param name unqualified service name, such as foobar . - * @param timeout timeout in milliseconds - * @return null if the service information cannot be obtained - */ - public ServiceInfo getServiceInfo(String type, String name, int timeout) - { - ServiceInfo info = new ServiceInfo(type, name); - new ServiceInfoResolver(info).start(); - - try - { - long end = System.currentTimeMillis() + timeout; - long delay; - synchronized (info) - { - while (!info.hasData() && - (delay = end - System.currentTimeMillis()) > 0) - { - info.wait(delay); - } - } - } - catch (InterruptedException e) - { - // empty - } - - return (info.hasData()) ? info : null; - } - - /** - * Request service information. The information about the service is - * requested and the ServiceListener.resolveService method is called as soon - * as it is available. - *

    - * Usage note: Do not call this method from the AWT event dispatcher thread. - * You will make the user interface unresponsive. - * - * @param type full qualified service type, - * such as _http._tcp.local. . - * @param name unqualified service name, such as foobar . - */ - public void requestServiceInfo(String type, String name) - { - requestServiceInfo(type, name, 3 * 1000); - } - - /** - * Request service information. The information about the service - * is requested and the ServiceListener.resolveService method is - * called as soon as it is available. - * - * @param type full qualified service type, - * such as _http._tcp.local. . - * @param name unqualified service name, such as foobar . - * @param timeout timeout in milliseconds - */ - public void requestServiceInfo(String type, String name, int timeout) - { - registerServiceType(type); - ServiceInfo info = new ServiceInfo(type, name); - new ServiceInfoResolver(info).start(); - - try - { - long end = System.currentTimeMillis() + timeout; - long delay; - synchronized (info) - { - while (!info.hasData() && - (delay = end - System.currentTimeMillis()) > 0) - { - info.wait(delay); - } - } - } - catch (InterruptedException e) - { - // empty - } - } - - void handleServiceResolved(ServiceInfo info) - { - List list = serviceListeners.get(info.type.toLowerCase()); - if (list != null) - { - ServiceEvent event = - new ServiceEvent(this, info.type, info.getName(), info); - // Iterate on a copy in case listeners will modify it - List listCopy - = new ArrayList (list); - for (ServiceListener serviceListener : listCopy) - serviceListener.serviceResolved(event); - } - } - - /** - * Listen for service types. - * - * @param listener listener for service types - * @throws java.io.IOException - */ - public void addServiceTypeListener(ServiceTypeListener listener) - throws IOException - { - synchronized (this) - { - typeListeners.remove(listener); - typeListeners.add(listener); - } - - // report cached service types - for (String serviceType : serviceTypes.values()) - { - listener.serviceTypeAdded( - new ServiceEvent(this, serviceType, null, null)); - } - - new TypeResolver().start(); - } - - /** - * Remove listener for service types. - * - * @param listener listener for service types - */ - public void removeServiceTypeListener(ServiceTypeListener listener) - { - synchronized (this) - { - typeListeners.remove(listener); - } - } - - /** - * Listen for services of a given type. The type has to be a fully - * qualified type name such as _http._tcp.local.. - * - * @param type full qualified service type, - * such as _http._tcp.local.. - * @param listener listener for service updates - */ - public void addServiceListener(String type, ServiceListener listener) - { - String lotype = type.toLowerCase(); - removeServiceListener(lotype, listener); - List list = null; - synchronized (this) - { - list = serviceListeners.get(lotype); - if (list == null) - { - list = Collections.synchronizedList(new LinkedList()); - serviceListeners.put(lotype, list); - } - list.add(listener); - } - - // report cached service types - for (Iterator i = cache.iterator(); i.hasNext();) - { - for (DNSCache.CacheNode n = i.next(); n != null; n = n.next()) - { - DNSRecord rec = (DNSRecord) n.getValue(); - if (rec.type == DNSConstants.TYPE_SRV) - { - if (rec.name.endsWith(type)) - { - listener.serviceAdded( - new ServiceEvent( - this, - type, - toUnqualifiedName(type, rec.name), - null)); - } - } - } - } - new ServiceResolver(type).start(); - } - - /** - * Remove listener for services of a given type. - * - * @param type of listener to be removed - * @param listener listener for service updates - */ - public void removeServiceListener(String type, ServiceListener listener) - { - type = type.toLowerCase(); - List list = serviceListeners.get(type); - if (list != null) - { - synchronized (this) - { - list.remove(listener); - if (list.size() == 0) - { - serviceListeners.remove(type); - } - } - } - } - - /** - * Register a service. The service is registered - * for access by other jmdns clients. - * The name of the service may be changed to make it unique. - * @param info of service - * @throws java.io.IOException - */ - public void registerService(ServiceInfo info) throws IOException - { - registerServiceType(info.type); - - // bind the service to this address - info.server = localHost.getName(); - info.addr = localHost.getAddress(); - - synchronized (this) - { - makeServiceNameUnique(info); - services.put(info.getQualifiedName().toLowerCase(), info); - } - - new /*Service*/Prober().start(); - try - { - synchronized (info) - { - while (info.getState().compareTo(DNSState.ANNOUNCED) < 0) - { - info.wait(); - } - } - } - catch (InterruptedException e) - { - logger.error(e.getMessage(), e); - } - if (logger.isDebugEnabled()) - logger.debug("registerService() JmDNS registered service as " + info); - } - - /** - * Unregister a service. The service should have been registered. - * @param info of service - */ - public void unregisterService(ServiceInfo info) - { - synchronized (this) - { - services.remove(info.getQualifiedName().toLowerCase()); - } - info.cancel(); - - // Note: We use this lock object to synchronize on it. - // Synchronizing on another object (e.g. the ServiceInfo) does - // not make sense, because the sole purpose of the lock is to - // wait until the canceler has finished. If we synchronized on - // the ServiceInfo or on the Canceler, we would block all - // accesses to synchronized methods on that object. This is not - // what we want! - Object lock = new Object(); - new Canceler(info, lock).start(); - - // Remind: We get a deadlock here, if the Canceler does not run! - try - { - synchronized (lock) - { - lock.wait(); - } - } - catch (InterruptedException e) - { - // empty - } - } - - /** - * Unregister all services. - */ - public void unregisterAllServices() - { - if (logger.isDebugEnabled()) - logger.debug("unregisterAllServices()"); - if (services.size() == 0) - { - return; - } - - Collection list; - synchronized (this) - { - list = new LinkedList(services.values()); - services.clear(); - } - for (Iterator iterator = list.iterator(); iterator.hasNext();) - { - iterator.next().cancel(); - } - - - Object lock = new Object(); - new Canceler(list, lock).start(); - // Remind: We get a livelock here, if the Canceler does not run! - try - { - synchronized (lock) - { - if (!closed) - { - lock.wait(); - } - } - } - catch (InterruptedException e) - { - // empty - } - } - - /** - * Register a service type. If this service type was not already known, - * all service listeners will be notified of the new service type. - * Service types are automatically registered as they are discovered. - * @param type of service - */ - public void registerServiceType(String type) - { - String name = type.toLowerCase(); - if (serviceTypes.get(name) == null) - { - if ((type.indexOf("._mdns._udp.") < 0) && - !type.endsWith(".in-addr.arpa.")) - { - Collection list; - synchronized (this) - { - serviceTypes.put(name, type); - list = new LinkedList(typeListeners); - } - for (ServiceTypeListener listener : list) - listener - .serviceTypeAdded( - new ServiceEvent(this, type, null, null)); - } - } - } - - /** - * Generate a possibly unique name for a service using the information we - * have in the cache. - * - * @return returns true, if the name of the service info had to be changed. - */ - private boolean makeServiceNameUnique(ServiceInfo info) - { - String originalQualifiedName = info.getQualifiedName(); - long now = System.currentTimeMillis(); - - boolean collision; - do - { - collision = false; - - // Check for collision in cache - for (DNSCache.CacheNode j = cache.find( - info.getQualifiedName().toLowerCase()); - j != null; - j = j.next()) - { - DNSRecord a = (DNSRecord) j.getValue(); - if ((a.type == DNSConstants.TYPE_SRV) && !a.isExpired(now)) - { - DNSRecord.Service s = (DNSRecord.Service) a; - if (s.port != info.port || !s.server.equals(localHost.getName())) - { - if (logger.isDebugEnabled()) - logger.debug("makeServiceNameUnique() " + - "JmDNS.makeServiceNameUnique srv collision:" + - a + " s.server=" + s.server + " " + - localHost.getName() + " equals:" + - (s.server.equals(localHost.getName()))); - info.setName(incrementName(info.getName())); - collision = true; - break; - } - } - } - - // Check for collision with other service infos published by JmDNS - Object selfService = - services.get(info.getQualifiedName().toLowerCase()); - if (selfService != null && selfService != info) - { - info.setName(incrementName(info.getName())); - collision = true; - } - } - while (collision); - - return !(originalQualifiedName.equals(info.getQualifiedName())); - } - - String incrementName(String name) - { - try - { - int l = name.lastIndexOf('('); - int r = name.lastIndexOf(')'); - if ((l >= 0) && (l < r)) - { - name = name.substring(0, l) + "(" + - (Integer.parseInt(name.substring(l + 1, r)) + 1) + ")"; - } - else - { - name += " (2)"; - } - } - catch (NumberFormatException e) - { - name += " (2)"; - } - return name; - } - - /** - * Add a listener for a question. The listener will receive updates - * of answers to the question as they arrive, or from the cache if they - * are already available. - * @param listener to be added - * @param question - which the listener is responsible for. - */ - public void addListener(DNSListener listener, DNSQuestion question) - { - long now = System.currentTimeMillis(); - - // add the new listener - synchronized (this) - { - listeners.add(listener); - } - - // report existing matched records - if (question != null) - { - for (DNSCache.CacheNode i = cache.find(question.name); - i != null; - i = i.next()) - { - DNSRecord c = (DNSRecord) i.getValue(); - if (question.answeredBy(c) && !c.isExpired(now)) - { - listener.updateRecord(this, now, c); - } - } - } - } - - /** - * Remove a listener from all outstanding questions. - * The listener will no longer receive any updates. - */ - void removeListener(DNSListener listener) - { - synchronized (this) - { - listeners.remove(listener); - } - } - - - // Remind: Method updateRecord should receive a better name. - /** - * Notify all listeners that a record was updated. - */ - void updateRecord(long now, DNSRecord rec) - { - // We do not want to block the entire DNS - // while we are updating the record for each listener (service info) - List listenerList = null; - synchronized (this) - { - listenerList = new ArrayList(listeners); - } - - //System.out.println("OUT OF MUTEX!!!!!"); - - for (DNSListener listener : listenerList) - listener.updateRecord(this, now, rec); - - if (rec.type == DNSConstants.TYPE_PTR || - rec.type == DNSConstants.TYPE_SRV) - { - List serviceListenerList = null; - synchronized (this) - { - serviceListenerList = serviceListeners.get(rec.name.toLowerCase()); - // Iterate on a copy in case listeners will modify it - if (serviceListenerList != null) - { - serviceListenerList = new ArrayList(serviceListenerList); - } - } - if (serviceListenerList != null) - { - boolean expired = rec.isExpired(now); - String type = rec.getName(); - String name = ((DNSRecord.Pointer) rec).getAlias(); - // DNSRecord old = (DNSRecord)services.get(name.toLowerCase()); - if (!expired) - { - // new record - ServiceEvent event = - new ServiceEvent( - this, - type, - toUnqualifiedName(type, name), - null); - for (Iterator iterator = serviceListenerList.iterator(); - iterator.hasNext();) - { - iterator.next().serviceAdded(event); - } - } - else - { - // expire record - ServiceEvent event = - new ServiceEvent( - this, - type, - toUnqualifiedName(type, name), - null); - for (Iterator iterator = serviceListenerList.iterator(); - iterator.hasNext();) - { - iterator.next().serviceRemoved(event); - } - } - } - } - } - - /** - * Handle an incoming response. Cache answers, and pass them on to - * the appropriate questions. - */ - private void handleResponse(DNSIncoming msg) - throws IOException - { - long now = System.currentTimeMillis(); - - boolean hostConflictDetected = false; - boolean serviceConflictDetected = false; - - if (logger.isTraceEnabled()) - logger.trace("JMDNS/handleResponse received " + - msg.answers.size()+ " messages"); - for (DNSRecord rec : msg.answers) - { - if (logger.isTraceEnabled()) - logger.trace("PRINT: "+ rec); - //cache.add(rec); - } - - for (DNSRecord rec : msg.answers) - { - boolean isInformative = false; - boolean expired = rec.isExpired(now); - - if (logger.isTraceEnabled()) - logger.trace("JMDNS received : " + rec + " expired: "+expired); - - // update the cache - DNSRecord c = (DNSRecord) cache.get(rec); - if (c != null) - { - if (logger.isTraceEnabled()) - logger.trace("JMDNS has found "+rec+" in cache"); - if (expired) - { - isInformative = true; - cache.remove(c); - } - else - { - /* Special case for SIP Communicator. - * We want to be informed if a cache entry is modified - */ -// if ((c.isUnique() -// && c.getType() == DNSConstants.TYPE_TXT -// && ((c.getClazz() & DNSConstants.CLASS_IN) != 0))) -// isInformative = true; -// c.resetTTL(rec); -// rec = c; - if (logger.isTraceEnabled()) - logger.trace( - new Boolean(c.isUnique()).toString() + - c.getType()+c.getClazz() + "/" + - DNSConstants.TYPE_TXT + " "+DNSConstants.CLASS_IN); - - if ((rec.isUnique() - && ((rec.getType() & DNSConstants.TYPE_TXT) != 0) - && ((rec.getClazz() & DNSConstants.CLASS_IN) != 0))) - { - if (logger.isTraceEnabled()) - logger.trace("UPDATING CACHE !! "); - isInformative = true; - cache.remove(c); - cache.add(rec); - } - else - { - c.resetTTL(rec); - rec = c; - } - } - } - else - { - if (!expired) - { - isInformative = true; - if (logger.isTraceEnabled()) - logger.trace("Adding "+rec+" to the cache"); - cache.add(rec); - } - } - switch (rec.type) - { - case DNSConstants.TYPE_PTR: - // handle _mdns._udp records - if (rec.getName().indexOf("._mdns._udp.") >= 0) - { - if (!expired && - rec.name.startsWith("_services._mdns._udp.")) - { - isInformative = true; - registerServiceType(((DNSRecord.Pointer)rec).alias); - } - continue; - } - registerServiceType(rec.name); - break; - } - - - if ((rec.getType() == DNSConstants.TYPE_A) || - (rec.getType() == DNSConstants.TYPE_AAAA)) - { - hostConflictDetected |= rec.handleResponse(this); - } - else - { - serviceConflictDetected |= rec.handleResponse(this); - } - - // notify the listeners - if (isInformative) - { - updateRecord(now, rec); - } - - - } - - if (hostConflictDetected || serviceConflictDetected) - { - new Prober().start(); - } - } - - /** - * Handle an incoming query. See if we can answer any part of it - * given our service infos. - */ - private void handleQuery(DNSIncoming in, InetAddress addr, int port) - throws IOException - { - // Track known answers - boolean hostConflictDetected = false; - boolean serviceConflictDetected = false; - long expirationTime = System.currentTimeMillis() + - DNSConstants.KNOWN_ANSWER_TTL; - for (DNSRecord answer : in.answers) - { - if ((answer.getType() == DNSConstants.TYPE_A) || - (answer.getType() == DNSConstants.TYPE_AAAA)) - { - hostConflictDetected |= - answer.handleQuery(this, expirationTime); - } - else - { - serviceConflictDetected |= - answer.handleQuery(this, expirationTime); - } - } - - if (plannedAnswer != null) - { - plannedAnswer.append(in); - } - else - { - if (in.isTruncated()) - { - plannedAnswer = in; - } - - new Responder(in, addr, port).start(); - } - - if (hostConflictDetected || serviceConflictDetected) - { - new Prober().start(); - } - } - - /** - * Add an answer to a question. Deal with the case when the - * outgoing packet overflows - */ - DNSOutgoing addAnswer(DNSIncoming in, - InetAddress addr, - int port, - DNSOutgoing out, - DNSRecord rec) - throws IOException - { - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA); - } - try - { - out.addAnswer(in, rec); - } - catch (IOException e) - { - out.flags |= DNSConstants.FLAGS_TC; - out.id = in.id; - out.finish(); - send(out); - - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA); - out.addAnswer(in, rec); - } - return out; - } - - - /** - * Send an outgoing multicast DNS message. - */ - private void send(DNSOutgoing out) throws IOException - { - out.finish(); - if (!out.isEmpty()) - { - DatagramPacket packet = - new DatagramPacket( - out.data, out.off, group, DNSConstants.MDNS_PORT); - - try - { - DNSIncoming msg = new DNSIncoming(packet); - if (logger.isTraceEnabled()) - logger.trace("send() JmDNS out:" + msg.print(true)); - } - catch (IOException exc) - { - logger.error( - "send(DNSOutgoing) - JmDNS can not parse what it sends!!!", - exc); - } - socket.send(packet); - } - } - - /** - * Listen for multicast packets. - */ - class SocketListener implements Runnable - { - public void run() - { - try - { - byte buf[] = new byte[DNSConstants.MAX_MSG_ABSOLUTE]; - DatagramPacket packet = new DatagramPacket(buf, buf.length); - while (state != DNSState.CANCELED) - { - packet.setLength(buf.length); - socket.receive(packet); - if (state == DNSState.CANCELED) - { - break; - } - try - { - if (localHost.shouldIgnorePacket(packet)) - { - continue; - } - - DNSIncoming msg = new DNSIncoming(packet); - if (logger.isTraceEnabled()) - logger.trace("SocketListener.run() JmDNS in:" + - msg.print(true)); - - synchronized (ioLock) - { - if (msg.isQuery()) - { - if (packet.getPort() != DNSConstants.MDNS_PORT) - { - handleQuery(msg, - packet.getAddress(), - packet.getPort()); - } - handleQuery(msg, group, DNSConstants.MDNS_PORT); - } - else - { - handleResponse(msg); - } - } - } - catch (IOException e) - { - logger.warn( "run() exception ", e); - } - } - } - catch (IOException e) - { - if (state != DNSState.CANCELED) - { - logger.warn( "run() exception ", e); - recover(); - } - } - } - } - - - /** - * Periodicaly removes expired entries from the cache. - */ - private class RecordReaper extends TimerTask - { - public void start() - { - timer.schedule( this, - DNSConstants.RECORD_REAPER_INTERVAL, - DNSConstants.RECORD_REAPER_INTERVAL); - } - - @Override - public void run() - { - synchronized (JmDNS.this) - { - if (state == DNSState.CANCELED) - { - return; - } - if (logger.isTraceEnabled()) - logger.trace("run() JmDNS reaping cache"); - - // Remove expired answers from the cache - // ------------------------------------- - // To prevent race conditions, we defensively copy all cache - // entries into a list. - List list = new ArrayList(); - synchronized (cache) - { - for (Iterator i = cache.iterator(); - i.hasNext();) - { - for (DNSCache.CacheNode n = i.next(); - n != null; - n = n.next()) - { - list.add(n.getValue()); - } - } - } - // Now, we remove them. - long now = System.currentTimeMillis(); - for (Iterator i = list.iterator(); i.hasNext();) - { - DNSRecord c = (DNSRecord)i.next(); - if (c.isExpired(now)) - { - updateRecord(now, c); - cache.remove(c); - } - } - } - } - } - - - /** - * The Prober sends three consecutive probes for all service infos - * that needs probing as well as for the host name. - * The state of each service info of the host name is advanced, - * when a probe has been sent for it. - * When the prober has run three times, it launches an Announcer. - *

    - * If a conflict during probes occurs, the affected service - * infos (and affected host name) are taken away from the prober. - * This eventually causes the prober tho cancel itself. - */ - private class Prober extends TimerTask - { - /** - * The state of the prober. - */ - DNSState taskState = DNSState.PROBING_1; - - public Prober() - { - // Associate the host name to this, if it needs probing - if (state == DNSState.PROBING_1) - { - task = this; - } - // Associate services to this, if they need probing - synchronized (JmDNS.this) - { - for (Iterator iterator = services.values().iterator(); - iterator.hasNext();) - { - ServiceInfo info = iterator.next(); - if (info.getState() == DNSState.PROBING_1) - { - info.task = this; - } - } - } - } - - - public void start() - { - long now = System.currentTimeMillis(); - if (now - lastThrottleIncrement < - DNSConstants.PROBE_THROTTLE_COUNT_INTERVAL) - { - throttle++; - } - else - { - throttle = 1; - } - lastThrottleIncrement = now; - - if (state == DNSState.ANNOUNCED && - throttle < DNSConstants.PROBE_THROTTLE_COUNT) - { - timer.schedule(this, - random.nextInt(1 + DNSConstants.PROBE_WAIT_INTERVAL), - DNSConstants.PROBE_WAIT_INTERVAL); - } - else - { - timer.schedule(this, - DNSConstants.PROBE_CONFLICT_INTERVAL, - DNSConstants.PROBE_CONFLICT_INTERVAL); - } - } - - @Override - public boolean cancel() - { - // Remove association from host name to this - if (task == this) - { - task = null; - } - - // Remove associations from services to this - synchronized (JmDNS.this) - { - for (Iterator i = services.values().iterator(); - i.hasNext();) - { - ServiceInfo info = i.next(); - if (info.task == this) - { - info.task = null; - } - } - } - - return super.cancel(); - } - - @Override - public void run() - { - synchronized (ioLock) - { - DNSOutgoing out = null; - try - { - // send probes for JmDNS itself - if (state == taskState && task == this) - { - if (out == null) - { - out = new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY); - } - out.addQuestion( - new DNSQuestion( - localHost.getName(), - DNSConstants.TYPE_ANY, - DNSConstants.CLASS_IN)); - DNSRecord answer = localHost.getDNS4AddressRecord(); - if (answer != null) - { - out.addAuthorativeAnswer(answer); - } - answer = localHost.getDNS6AddressRecord(); - if (answer != null) - { - out.addAuthorativeAnswer(answer); - } - advanceState(); - } - // send probes for services - // Defensively copy the services into a local list, - // to prevent race conditions with methods registerService - // and unregisterService. - List list; - synchronized (JmDNS.this) - { - list = new LinkedList(services.values()); - } - for (Iterator i = list.iterator(); i.hasNext();) - { - ServiceInfo info = i.next(); - - synchronized (info) - { - if (info.getState() == taskState && - info.task == this) - { - info.advanceState(); - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS probing " + - info.getQualifiedName() + " state " + - info.getState()); - - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_QUERY); - out.addQuestion( - new DNSQuestion( - info.getQualifiedName(), - DNSConstants.TYPE_ANY, - DNSConstants.CLASS_IN)); - } - out.addAuthorativeAnswer( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - localHost.getName())); - } - } - } - if (out != null) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS probing #" + taskState); - send(out); - } - else - { - // If we have nothing to send, another timer taskState - // ahead of us has done the job for us. We can cancel. - cancel(); - return; - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - - taskState = taskState.advance(); - if (!taskState.isProbing()) - { - cancel(); - - new Announcer().start(); - } - } - } - - } - - /** - * The Announcer sends an accumulated query of all announces, and advances - * the state of all serviceInfos, for which it has sent an announce. - * The Announcer also sends announcements and advances the state of JmDNS - * itself. - *

    - * When the announcer has run two times, it finishes. - */ - private class Announcer extends TimerTask - { - /** - * The state of the announcer. - */ - DNSState taskState = DNSState.ANNOUNCING_1; - - public Announcer() - { - // Associate host to this, if it needs announcing - if (state == DNSState.ANNOUNCING_1) - { - task = this; - } - // Associate services to this, if they need announcing - synchronized (JmDNS.this) - { - for (Iterator s = services.values().iterator(); s.hasNext();) - { - ServiceInfo info = s.next(); - if (info.getState() == DNSState.ANNOUNCING_1) - { - info.task = this; - } - } - } - } - - public void start() - { - timer.schedule(this, - DNSConstants.ANNOUNCE_WAIT_INTERVAL, - DNSConstants.ANNOUNCE_WAIT_INTERVAL); - } - - @Override - public boolean cancel() - { - // Remove association from host to this - if (task == this) - { - task = null; - } - - // Remove associations from services to this - synchronized (JmDNS.this) - { - for (Iterator i = services.values().iterator(); - i.hasNext();) - { - ServiceInfo info = i.next(); - if (info.task == this) - { - info.task = null; - } - } - } - - return super.cancel(); - } - - @Override - public void run() - { - DNSOutgoing out = null; - try - { - // send probes for JmDNS itself - if (state == taskState) - { - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA); - } - DNSRecord answer = localHost.getDNS4AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - answer = localHost.getDNS6AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - advanceState(); - } - // send announces for services - // Defensively copy the services into a local list, - // to prevent race conditions with methods registerService - // and unregisterService. - List list; - synchronized (JmDNS.this) - { - list = new ArrayList(services.values()); - } - for (Iterator i = list.iterator(); i.hasNext();) - { - ServiceInfo info = i.next(); - synchronized (info) - { - if (info.getState() == taskState && info.task == this) - { - info.advanceState(); - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS announcing " + - info.getQualifiedName() + - " state " + info.getState()); - - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | - DNSConstants.FLAGS_AA); - } - out.addAnswer( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.getQualifiedName()), 0); - out.addAnswer( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - localHost.getName()), 0); - out.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.text), 0); - } - } - } - if (out != null) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS announcing #" + taskState); - send(out); - } - else - { - // If we have nothing to send, another timer taskState ahead - // of us has done the job for us. We can cancel. - cancel(); - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - - taskState = taskState.advance(); - if (!taskState.isAnnouncing()) - { - cancel(); - - new Renewer().start(); - } - } - } - - /** - * The Renewer is there to send renewal announcment - * when the record expire for ours infos. - */ - private class Renewer extends TimerTask - { - /** - * The state of the announcer. - */ - DNSState taskState = DNSState.ANNOUNCED; - - public Renewer() - { - // Associate host to this, if it needs renewal - if (state == DNSState.ANNOUNCED) - { - task = this; - } - // Associate services to this, if they need renewal - synchronized (JmDNS.this) - { - for (Iterator s = services.values().iterator(); s.hasNext();) - { - ServiceInfo info = s.next(); - if (info.getState() == DNSState.ANNOUNCED) - { - info.task = this; - } - } - } - } - - public void start() - { - timer.schedule(this, - DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL, - DNSConstants.ANNOUNCED_RENEWAL_TTL_INTERVAL); - } - - @Override - public boolean cancel() - { - // Remove association from host to this - if (task == this) - { - task = null; - } - - // Remove associations from services to this - synchronized (JmDNS.this) - { - for (Iterator i = services.values().iterator(); - i.hasNext();) - { - ServiceInfo info = i.next(); - if (info.task == this) - { - info.task = null; - } - } - } - - return super.cancel(); - } - - @Override - public void run() - { - DNSOutgoing out = null; - try - { - // send probes for JmDNS itself - if (state == taskState) - { - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA); - } - DNSRecord answer = localHost.getDNS4AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - answer = localHost.getDNS6AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - advanceState(); - } - // send announces for services - // Defensively copy the services into a local list, - // to prevent race conditions with methods registerService - // and unregisterService. - List list; - synchronized (JmDNS.this) - { - list = new ArrayList(services.values()); - } - for (Iterator i = list.iterator(); i.hasNext();) - { - ServiceInfo info = i.next(); - synchronized (info) - { - if (info.getState() == taskState && info.task == this) - { - info.advanceState(); - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS announced " + - info.getQualifiedName() + " state " + info.getState()); - - if (out == null) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | - DNSConstants.FLAGS_AA); - } - out.addAnswer( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.getQualifiedName()), 0); - out.addAnswer( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - localHost.getName()), 0); - out.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.text), 0); - } - } - } - if (out != null) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS announced"); - send(out); - } - else - { - // If we have nothing to send, another timer taskState ahead - // of us has done the job for us. We can cancel. - cancel(); - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - - taskState = taskState.advance(); - if (!taskState.isAnnounced()) - { - cancel(); - - } - } - } - - /** - * The Responder sends a single answer for the specified service infos - * and for the host name. - */ - private class Responder extends TimerTask - { - private DNSIncoming in; - private InetAddress addr; - private int port; - - public Responder(DNSIncoming in, InetAddress addr, int port) - { - this.in = in; - this.addr = addr; - this.port = port; - } - - public void start() - { - // According to draft-cheshire-dnsext-multicastdns.txt - // chapter "8 Responding": - // We respond immediately if we know for sure, that we are - // the only one who can respond to the query. - // In all other cases, we respond within 20-120 ms. - // - // According to draft-cheshire-dnsext-multicastdns.txt - // chapter "7.2 Multi-Packet Known Answer Suppression": - // We respond after 20-120 ms if the query is truncated. - - boolean iAmTheOnlyOne = true; - for (DNSEntry entry : in.questions) - { - if (entry instanceof DNSQuestion) - { - DNSQuestion q = (DNSQuestion) entry; - if (logger.isTraceEnabled()) - logger.trace("start() question=" + q); - iAmTheOnlyOne &= (q.type == DNSConstants.TYPE_SRV - || q.type == DNSConstants.TYPE_TXT - || q.type == DNSConstants.TYPE_A - || q.type == DNSConstants.TYPE_AAAA - || localHost.getName().equalsIgnoreCase(q.name) - || services.containsKey(q.name.toLowerCase())); - if (!iAmTheOnlyOne) - { - break; - } - } - } - int delay = (iAmTheOnlyOne && !in.isTruncated()) ? - 0 : - DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + - random.nextInt( - DNSConstants.RESPONSE_MAX_WAIT_INTERVAL - - DNSConstants.RESPONSE_MIN_WAIT_INTERVAL + 1) - - in.elapseSinceArrival(); - if (delay < 0) - { - delay = 0; - } - if (logger.isTraceEnabled()) - logger.trace("start() Responder chosen delay=" + delay); - timer.schedule(this, delay); - } - - @Override - public void run() - { - synchronized (ioLock) - { - if (plannedAnswer == in) - { - plannedAnswer = null; - } - - // We use these sets to prevent duplicate records - // FIXME - This should be moved into DNSOutgoing - HashSet questions = new HashSet(); - HashSet answers = new HashSet(); - - - if (state == DNSState.ANNOUNCED) - { - try - { - boolean isUnicast = (port != DNSConstants.MDNS_PORT); - - - // Answer questions - for (Iterator iterator = in.questions.iterator(); - iterator.hasNext();) - { - DNSEntry entry = iterator.next(); - if (entry instanceof DNSQuestion) - { - DNSQuestion q = (DNSQuestion) entry; - - // for unicast responses the question - // must be included - if (isUnicast) - { - //out.addQuestion(q); - questions.add(q); - } - - int type = q.type; - if (type == DNSConstants.TYPE_ANY || - type == DNSConstants.TYPE_SRV) - { // I ama not sure of why there is a special - // case here [PJYF Oct 15 2004] - if (localHost.getName(). - equalsIgnoreCase(q.getName())) - { - // type = DNSConstants.TYPE_A; - DNSRecord answer = - localHost.getDNS4AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - answer = localHost.getDNS6AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - type = DNSConstants.TYPE_IGNORE; - } - else - { - if (serviceTypes.containsKey( - q.getName().toLowerCase())) - { - type = DNSConstants.TYPE_PTR; - } - } - } - - switch (type) - { - case DNSConstants.TYPE_A: - { - // Answer a query for a domain name - //out = addAnswer( in, addr, port, out, host ); - DNSRecord answer = - localHost.getDNS4AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - break; - } - case DNSConstants.TYPE_AAAA: - { - // Answer a query for a domain name - DNSRecord answer = - localHost.getDNS6AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - break; - } - case DNSConstants.TYPE_PTR: - { - // Answer a query for services of a given type - - // find matching services - for (Iterator serviceIterator = - services.values().iterator(); - serviceIterator.hasNext();) - { - ServiceInfo info = serviceIterator.next(); - if (info.getState() == DNSState.ANNOUNCED) - { - if (q.name.equalsIgnoreCase(info.type)) - { - DNSRecord answer = - localHost.getDNS4AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - answer = - localHost.getDNS6AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - answers.add( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.getQualifiedName())); - answers.add( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - localHost.getName())); - answers.add( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.text)); - } - } - } - if (q.name.equalsIgnoreCase("_services._mdns._udp.local.")) - { - for (Iterator serviceTypeIterator = serviceTypes.values().iterator(); - serviceTypeIterator.hasNext();) - { - answers.add( - new DNSRecord.Pointer( - "_services._mdns._udp.local.", - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - serviceTypeIterator.next())); - } - } - break; - } - case DNSConstants.TYPE_SRV: - case DNSConstants.TYPE_ANY: - case DNSConstants.TYPE_TXT: - { - ServiceInfo info = services.get(q.name.toLowerCase()); - if (info != null && - info.getState() == DNSState.ANNOUNCED) - { - DNSRecord answer = - localHost.getDNS4AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - answer = - localHost.getDNS6AddressRecord(); - if (answer != null) - { - answers.add(answer); - } - answers.add( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.getQualifiedName())); - answers.add( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.priority, - info.weight, - info.port, - localHost.getName())); - answers.add( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.text)); - } - break; - } - default : - { - //System.out.println("JmDNSResponder.unhandled query:"+q); - break; - } - } - } - } - - - // remove known answers, if the ttl is at least half of - // the correct value. (See Draft Cheshire chapter 7.1.). - for (DNSRecord knownAnswer : in.answers) - { - if (knownAnswer.ttl > DNSConstants.DNS_TTL / 2 && - answers.remove(knownAnswer)) - { - if (logger.isDebugEnabled()) - logger.debug( - "JmDNS Responder Known Answer Removed"); - } - } - - - // responde if we have answers - if (answers.size() != 0) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS responding"); - DNSOutgoing out = null; - if (isUnicast) - { - out = new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE - | DNSConstants.FLAGS_AA, - false); - } - - for (Iterator i = questions.iterator(); - i.hasNext();) - { - out.addQuestion(i.next()); - } - for (Iterator i = answers.iterator(); - i.hasNext();) - { - out = addAnswer(in, addr, port, out, i.next()); - } - send(out); - } - this.cancel(); - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - close(); - } - } - } - } - } - - /** - * Helper class to resolve service types. - *

    - * The TypeResolver queries three times consecutively for service types, and then - * removes itself from the timer. - *

    - * The TypeResolver will run only if JmDNS is in state ANNOUNCED. - */ - private class TypeResolver extends TimerTask - { - public void start() - { - timer.schedule(this, - DNSConstants.QUERY_WAIT_INTERVAL, - DNSConstants.QUERY_WAIT_INTERVAL); - } - - /** - * Counts the number of queries that were sent. - */ - int count = 0; - - @Override - public void run() - { - try - { - if (state == DNSState.ANNOUNCED) - { - if (count++ < 3) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS querying type"); - DNSOutgoing out = - new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY); - out.addQuestion( - new DNSQuestion( - "_services._mdns._udp.local.", - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN)); - for (String serviceType : serviceTypes.values()) - { - out.addAnswer( - new DNSRecord.Pointer( - "_services._mdns._udp.local.", - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - serviceType), 0); - } - send(out); - } - else - { - // After three queries, we can quit. - this.cancel(); - } - } - else - { - if (state == DNSState.CANCELED) - { - this.cancel(); - } - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - } - } - - /** - * The ServiceResolver queries three times consecutively for services of - * a given type, and then removes itself from the timer. - *

    - * The ServiceResolver will run only if JmDNS is in state ANNOUNCED. - * REMIND: Prevent having multiple service resolvers for the same type in the - * timer queue. - */ - private class ServiceResolver extends TimerTask - { - /** - * Counts the number of queries being sent. - */ - int count = 0; - private String type; - - public ServiceResolver(String type) - { - this.type = type; - } - - public void start() - { - timer.schedule(this, - DNSConstants.QUERY_WAIT_INTERVAL, - DNSConstants.QUERY_WAIT_INTERVAL); - } - - @Override - public void run() - { - try - { - if (state == DNSState.ANNOUNCED) - { - if (count++ < 3) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS querying service"); - long now = System.currentTimeMillis(); - DNSOutgoing out = - new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY); - out.addQuestion( - new DNSQuestion( - type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN)); - for (Iterator s = services.values().iterator(); s.hasNext();) - { - final ServiceInfo info = s.next(); - try - { - out.addAnswer( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - DNSConstants.DNS_TTL, - info.getQualifiedName()), now); - } - catch (IOException ee) - { - break; - } - } - send(out); - } - else - { - // After three queries, we can quit. - this.cancel(); - } - } - else - { - if (state == DNSState.CANCELED) - { - this.cancel(); - } - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - } - } - - /** - * The ServiceInfoResolver queries up to three times consecutively for - * a service info, and then removes itself from the timer. - *

    - * The ServiceInfoResolver will run only if JmDNS is in state ANNOUNCED. - * REMIND: Prevent having multiple service resolvers for the same info in the - * timer queue. - */ - private class ServiceInfoResolver extends TimerTask - { - /** - * Counts the number of queries being sent. - */ - int count = 0; - private ServiceInfo info; - - public ServiceInfoResolver(ServiceInfo info) - { - this.info = info; - info.dns = JmDNS.this; - addListener(info, - new DNSQuestion( - info.getQualifiedName(), - DNSConstants.TYPE_ANY, - DNSConstants.CLASS_IN)); - } - - public void start() - { - timer.schedule(this, - DNSConstants.QUERY_WAIT_INTERVAL, - DNSConstants.QUERY_WAIT_INTERVAL); - } - - @Override - public void run() - { - try - { - if (state == DNSState.ANNOUNCED) - { - if (count++ < 3 && !info.hasData()) - { - long now = System.currentTimeMillis(); - DNSOutgoing out = - new DNSOutgoing(DNSConstants.FLAGS_QR_QUERY); - out.addQuestion( - new DNSQuestion( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN)); - out.addQuestion( - new DNSQuestion( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN)); - if (info.server != null) - { - out.addQuestion( - new DNSQuestion( - info.server, - DNSConstants.TYPE_A, - DNSConstants.CLASS_IN)); - } - out.addAnswer((DNSRecord) cache.get( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN), now); - out.addAnswer((DNSRecord) cache.get( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN), now); - if (info.server != null) - { - out.addAnswer((DNSRecord) cache.get( - info.server, - DNSConstants.TYPE_A, - DNSConstants.CLASS_IN), now); - } - send(out); - } - else - { - // After three queries, we can quit. - this.cancel(); - removeListener(info); - } - } - else - { - if (state == DNSState.CANCELED) - { - this.cancel(); - removeListener(info); - } - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - } - } - - /** - * The Canceler sends two announces with TTL=0 for the specified services. - */ - /* TODO: Clarify whether 2 or 3 announces should be sent. The header says 2, - * run() uses the (misleading) ++count < 3 (while all other tasks use count++ < 3) - * and the comment in the else block in run() says: "After three successful..." - */ - public class Canceler extends TimerTask - { - /** - * Counts the number of announces being sent. - */ - int count = 0; - /** - * The services that need cancelling. - * Note: We have to use a local variable here, because the services - * that are canceled, are removed immediately from variable JmDNS.services. - */ - private ServiceInfo[] infos; - /** - * We call notifyAll() on the lock object, when we have canceled the - * service infos. - * This is used by method JmDNS.unregisterService() and - * JmDNS.unregisterAllServices, to ensure that the JmDNS - * socket stays open until the Canceler has canceled all services. - *

    - * Note: We need this lock, because ServiceInfos do the transition from - * state ANNOUNCED to state CANCELED before we get here. We could get - * rid of this lock, if we added a state named CANCELLING to DNSState. - */ - private Object lock; - int ttl = 0; - - public Canceler(ServiceInfo info, Object lock) - { - this.infos = new ServiceInfo[]{info}; - this.lock = lock; - addListener(info, - new DNSQuestion( - info.getQualifiedName(), - DNSConstants.TYPE_ANY, - DNSConstants.CLASS_IN)); - } - - public Canceler(ServiceInfo[] infos, Object lock) - { - this.infos = infos; - this.lock = lock; - } - - public Canceler(Collection infos, Object lock) - { - this.infos = infos.toArray(new ServiceInfo[infos.size()]); - this.lock = lock; - } - - public void start() - { - timer.schedule(this, 0, DNSConstants.ANNOUNCE_WAIT_INTERVAL); - } - - @Override - public void run() - { - try - { - if (++count < 3) - { - if (logger.isDebugEnabled()) - logger.debug("run() JmDNS canceling service"); - // announce the service - //long now = System.currentTimeMillis(); - DNSOutgoing out = - new DNSOutgoing( - DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA); - for (int i = 0; i < infos.length; i++) - { - ServiceInfo info = infos[i]; - out.addAnswer( - new DNSRecord.Pointer( - info.type, - DNSConstants.TYPE_PTR, - DNSConstants.CLASS_IN, - ttl, - info.getQualifiedName()), 0); - out.addAnswer( - new DNSRecord.Service( - info.getQualifiedName(), - DNSConstants.TYPE_SRV, - DNSConstants.CLASS_IN, - ttl, - info.priority, - info.weight, - info.port, - localHost.getName()), 0); - out.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN, - ttl, - info.text), 0); - DNSRecord answer = localHost.getDNS4AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - answer = localHost.getDNS6AddressRecord(); - if (answer != null) - { - out.addAnswer(answer, 0); - } - } - send(out); - } - else - { - // After three successful announcements, we are finished. - synchronized (lock) - { - closed=true; - lock.notifyAll(); - } - this.cancel(); - } - } - catch (Throwable e) - { - logger.warn( "run() exception ", e); - recover(); - } - } - } - - /** - * Recover jmdns when there is an error. - */ - protected void recover() - { - if (logger.isDebugEnabled()) - logger.debug("recover()"); - // We have an IO error so lets try to recover if anything happens lets close it. - // This should cover the case of the IP address changing under our feet - if (DNSState.CANCELED != state) - { - synchronized (this) - { // Synchronize only if we are not already in process to prevent dead locks - // - if (logger.isDebugEnabled()) - logger.debug("recover() Cleanning up"); - // Stop JmDNS - state = DNSState.CANCELED; // This protects against recursive calls - - // We need to keep a copy for reregistration - Collection oldServiceInfos = new ArrayList(services.values()); - - // Cancel all services - unregisterAllServices(); - disposeServiceCollectors(); - // - // close multicast socket - closeMulticastSocket(); - // - cache.clear(); - if (logger.isDebugEnabled()) - logger.debug("recover() All is clean"); - // - // All is clear now start the services - // - try - { - openMulticastSocket(localHost); - start(oldServiceInfos); - } - catch (Exception exception) - { - logger.warn( - "recover() Start services exception ", exception); - } - logger.warn( "recover() We are back!"); - } - } - } - - /** - * Close down jmdns. Release all resources and unregister all services. - */ - public void close() - { - if (state != DNSState.CANCELED) - { - synchronized (this) - { // Synchronize only if we are not already in process to prevent dead locks - // Stop JmDNS - state = DNSState.CANCELED; // This protects against recursive calls - - unregisterAllServices(); - disposeServiceCollectors(); - - // close socket - closeMulticastSocket(); - - // Stop the timer - timer.cancel(); - } - } - } - - /** - * List cache entries, for debugging only. - */ - void print() - { - if (logger.isInfoEnabled()) - logger.info("---- cache ----\n"); - cache.print(); - if (logger.isInfoEnabled()) - logger.info("\n"); - } - - /** - * List Services and serviceTypes. - * Debugging Only - */ - - public void printServices() - { - if (logger.isInfoEnabled()) - logger.info(toString()); - } - - @Override - public String toString() - { - StringBuffer aLog = new StringBuffer(); - aLog.append("\t---- Services -----"); - if (services != null) - { - for (Map.Entry entry : services.entrySet()) - { - aLog.append("\n\t\tService: " + entry.getKey() + ": " - + entry.getValue()); - } - } - aLog.append("\n"); - aLog.append("\t---- Types ----"); - if (serviceTypes != null) - { - for (Map.Entry entry : serviceTypes.entrySet()) - { - aLog.append("\n\t\tType: " + entry.getKey() + ": " - + entry.getValue()); - } - } - aLog.append("\n"); - aLog.append(cache.toString()); - aLog.append("\n"); - aLog.append("\t---- Service Collectors ----"); - if (serviceCollectors != null) - { - synchronized (serviceCollectors) - { - for (Map.Entry entry - : serviceCollectors.entrySet()) - { - aLog.append("\n\t\tService Collector: " + entry.getKey() - + ": " + entry.getValue()); - } - serviceCollectors.clear(); - } - } - return aLog.toString(); - } - - /** - * Returns a list of service infos of the specified type. - * - * @param type Service type name, such as _http._tcp.local.. - * @return An array of service instance names. - */ - public ServiceInfo[] list(String type) - { - // Implementation note: The first time a list for a given type is - // requested, a ServiceCollector is created which collects service - // infos. This greatly speeds up the performance of subsequent calls - // to this method. The caveats are, that 1) the first call to this method - // for a given type is slow, and 2) we spawn a ServiceCollector - // instance for each service type which increases network traffic a - // little. - - ServiceCollector collector; - - boolean newCollectorCreated; - synchronized (serviceCollectors) - { - collector = serviceCollectors.get(type); - if (collector == null) - { - collector = new ServiceCollector(type); - serviceCollectors.put(type, collector); - addServiceListener(type, collector); - newCollectorCreated = true; - } - else - { - newCollectorCreated = false; - } - } - - // After creating a new ServiceCollector, we collect service infos for - // 200 milliseconds. This should be enough time, to get some service - // infos from the network. - if (newCollectorCreated) - { - try - { - Thread.sleep(200); - } - catch (InterruptedException e) - { - } - } - - return collector.list(); - } - - /** - * This method disposes all ServiceCollector instances which have been - * created by calls to method list(type). - * - * @see #list - */ - private void disposeServiceCollectors() - { - if (logger.isDebugEnabled()) - logger.debug("disposeServiceCollectors()"); - synchronized (serviceCollectors) - { - for (Iterator i = serviceCollectors.values().iterator(); i.hasNext();) - { - ServiceCollector collector = i.next(); - removeServiceListener(collector.type, collector); - } - serviceCollectors.clear(); - } - } - - /** - * Instances of ServiceCollector are used internally to speed up the - * performance of method list(type). - * - * @see #list - */ - private static class ServiceCollector implements ServiceListener - { - - /** - * A set of collected service instance names. - */ - private Map infos = Collections.synchronizedMap(new HashMap()); - - public String type; - - public ServiceCollector(String type) - { - this.type = type; - } - - /** - * A service has been added. - */ - public void serviceAdded(ServiceEvent event) - { - synchronized (infos) - { - event.getDNS().requestServiceInfo( - event.getType(), event.getName(), 0); - } - } - - /** - * A service has been removed. - */ - public void serviceRemoved(ServiceEvent event) - { - synchronized (infos) - { - infos.remove(event.getName()); - } - } - - /** - * A service hase been resolved. Its details are now available in the - * ServiceInfo record. - */ - public void serviceResolved(ServiceEvent event) - { - synchronized (infos) - { - infos.put(event.getName(), event.getInfo()); - } - } - - /** - * Returns an array of all service infos which have been collected by this - * ServiceCollector. - * @return - */ - public ServiceInfo[] list() - { - synchronized (infos) - { - return infos.values(). - toArray(new ServiceInfo[infos.size()]); - } - } - - @Override - public String toString() - { - StringBuffer aLog = new StringBuffer(); - synchronized (infos) - { - for (Map.Entry entry : infos.entrySet()) - { - aLog.append("\n\t\tService: " + entry.getKey() + ": " - + entry.getValue()); - } - } - return aLog.toString(); - } - }; - - private static String toUnqualifiedName(String type, String qualifiedName) - { - if (qualifiedName.endsWith(type)) - { - return qualifiedName.substring(0, - qualifiedName.length() - type.length() - 1); - } - else - { - return qualifiedName; - } - } - - /** - * SC-Bonjour Implementation : Method used to update the corresponding DNS - * entry in the cache of JmDNS with the new information in this ServiceInfo. - * A call to getLocalService must first be issued to get the - * ServiceInfo object to be modified. - * THIS METHOD MUST BE USED INSTEAD OF ANY DIRECT ACCESS TO JMDNS' CACHE!! - * This is used in the implementation of Zeroconf in SIP Communicator - * to be able to change fields declared by the local contact (status, etc). - * @param info Updated service data to be used to replace the old - * stuff contained in JmDNS' cache - * @param old info bytes - */ - public void updateInfos(ServiceInfo info, byte[] old) - { - - DNSOutgoing out, out2; - synchronized (JmDNS.this) - { - //list = new ArrayList(services.values()); - services.put(info.getQualifiedName().toLowerCase(), info); - } - - synchronized (info) - { - if (logger.isDebugEnabled()) - logger.debug("updateInfos() JmDNS updating " + - info.getQualifiedName() + " state " + - info.getState()); - - out = new DNSOutgoing( - /*DNSConstants.FLAGS_QR_RESPONSE*/ - DNSConstants.FLAGS_RA | DNSConstants.FLAGS_AA); - out2 = new DNSOutgoing( - /*DNSConstants.FLAGS_QR_RESPONSE*/ - DNSConstants.FLAGS_RA | DNSConstants.FLAGS_AA); - - - try - { - //out.addAnswer(new DNSRecord.Pointer(info.type, DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.getQualifiedName()), 0); - //out.addAnswer(new DNSRecord.Service(info.getQualifiedName(), DNSConstants.TYPE_A, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.priority, info.weight, info.port, localHost.getName()), 0); - //out.addAnswer(new DNSRecord.Service(info.getQualifiedName(), DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.priority, info.weight, info.port, localHost.getName()), 0); -// out.addAnswer( -// new DNSRecord.Text( -// info.getQualifiedName(), -// DNSConstants.TYPE_TXT, -// DNSConstants.CLASS_IN , -// DNSConstants.DNS_TTL, -// info.text), 0); - out.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN , - 0, - old), 0); - out.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.text), 0); - - out2.addAnswer( - new DNSRecord.Text( - info.getQualifiedName(), - DNSConstants.TYPE_TXT, - DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, - DNSConstants.DNS_TTL, - info.text), 0); - - if (logger.isDebugEnabled()) - logger.debug("updateInfos() JmDNS updated infos for "+info); - - send(out); - Thread.sleep(1000); - send(out2); - Thread.sleep(2000); - send(out2); - } - catch( Exception e) - { - logger.warn( "", e); - } - } - } - - - /** - * SC-Bonjour Implementation: Method to retrieve the DNS Entry corresponding to a service - * that has been declared and return it as a ServiceInfo structure. - * It is used in the implementation of Bonjour in SIP Communicator to retrieve the information - * concerning the service declared by the local contact. THIS METHOD MUST BE USED INSTEAD OF ANY - * LOCAL COPY SAVED BEFORE SERVICE REGISTRATION!! - * @return information corresponding to the specified service - * @param FQN String representing the Fully Qualified name of the service we want info about - */ - public ServiceInfo getLocalService(String FQN) - { - return services.get(FQN); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceEvent.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceEvent.java deleted file mode 100644 index ff922d1..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceEvent.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.*; -import java.util.logging.*; - -/** - * ServiceEvent. - * - * @author Werner Randelshofer, Rick Blair - * @version %I%, %G% - */ -public class ServiceEvent - extends EventObject -{ - private static Logger logger = - Logger.getLogger(ServiceEvent.class.toString()); - /** - * The type name of the service. - */ - private String type; - /** - * The instance name of the service. Or null, if the event was - * fired to a service type listener. - */ - private String name; - /** - * The service info record, or null if the service could be be resolved. - * This is also null, if the event was fired to a service type listener. - */ - private ServiceInfo info; - - /** - * Creates a new instance. - * - * @param source the JmDNS instance which originated the event. - * @param type the type name of the service. - * @param name the instance name of the service. - * @param info the service info record, or null if the - * service could be be resolved. - */ - public ServiceEvent(JmDNS source, String type, String name, ServiceInfo info) - { - super(source); - this.type = type; - this.name = name; - this.info = info; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - /** - * Returns the JmDNS instance which originated the event. - * @return Returns the JmDNS instance which originated the event. - */ - public JmDNS getDNS() - { - return (JmDNS) getSource(); - } - - /** - * Returns the fully qualified type of the service. - * @return Returns the fully qualified type of the service. - */ - public String getType() - { - return type; - } - - /** - * Returns the instance name of the service. - * Always returns null, if the event is sent to a service type listener. - * @return Returns the instance name of the service. - */ - public String getName() - { - return name; - } - - /** - * Returns the service info record, or null if the service could not be - * resolved. - * Always returns null, if the event is sent to a service type listener. - * @return Returns the service info record. - */ - public ServiceInfo getInfo() - { - return info; - } - - @Override - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append("<" + getClass().getName() + "> "); - buf.append(super.toString()); - buf.append(" name "); - buf.append(getName()); - buf.append(" type "); - buf.append(getType()); - buf.append(" info "); - buf.append(getInfo()); - return buf.toString(); - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceInfo.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceInfo.java deleted file mode 100644 index b7f7f2d..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceInfo.java +++ /dev/null @@ -1,785 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.logging.*; - -/** - * JmDNS service information. - * - * @version %I%, %G% - * @author Arthur van Hoff, Jeff Sonstein, Werner Randelshofer - * @author Christian Vincenot - */ -public class ServiceInfo implements DNSListener -{ - private static Logger logger = - Logger.getLogger(ServiceInfo.class.toString()); - public final static byte[] NO_VALUE = new byte[0]; - JmDNS dns; - - // State machine - /** - * The state of this service info. - * This is used only for services announced by JmDNS. - *

    - * For proper handling of concurrency, this variable must be - * changed only using methods advanceState(), revertState() and cancel(). - */ - private DNSState state = DNSState.PROBING_1; - - /** - * Task associated to this service info. - * Possible tasks are JmDNS.Prober, JmDNS.Announcer, JmDNS.Responder, - * JmDNS.Canceler. - */ - TimerTask task; - - String type; - private String name; - String server; - int port; - int weight; - int priority; - byte text[]; - private Map props; - InetAddress addr; - - - /** - * Construct a service description for registrating with JmDNS. - * - * @param type fully qualified service type name, - * such as _http._tcp.local.. - * @param name unqualified service instance name, - * such as foobar - * @param port the local port on which the service runs - * @param text string describing the service - */ - public ServiceInfo(String type, String name, int port, String text) - { - this(type, name, port, 0, 0, text); - } - - /** - * Construct a service description for registrating with JmDNS. - * - * @param type fully qualified service type name, - * such as _http._tcp.local.. - * @param name unqualified service instance name, - * such as foobar - * @param port the local port on which the service runs - * @param weight weight of the service - * @param priority priority of the service - * @param text string describing the service - */ - public ServiceInfo(String type, String name, - int port, int weight, - int priority, String text) - { - this(type, name, port, weight, priority, (byte[]) null); - try - { - ByteArrayOutputStream out = new ByteArrayOutputStream(text.length()); - writeUTF(out, text); - this.text = out.toByteArray(); - } - catch (IOException e) - { - throw new RuntimeException("unexpected exception: " + e); - } - } - - /** - * Construct a service description for registrating with JmDNS. The properties hashtable must - * map property names to either Strings or byte arrays describing the property values. - * - * @param type fully qualified service type name, such as _http._tcp.local.. - * @param name unqualified service instance name, such as foobar - * @param port the local port on which the service runs - * @param weight weight of the service - * @param priority priority of the service - * @param props properties describing the service - */ - public ServiceInfo(String type, String name, - int port, int weight, - int priority, Map props) - { - this(type, name, port, weight, priority, new byte[0]); - if (props != null) - { - try - { - ByteArrayOutputStream out = new ByteArrayOutputStream(256); - for (Map.Entry prop : props.entrySet()) - { - String key = prop.getKey(); - Object val = prop.getValue(); - ByteArrayOutputStream out2 = new ByteArrayOutputStream(100); - writeUTF(out2, key); - if (val instanceof String) - { - out2.write('='); - writeUTF(out2, (String) val); - } - else - { - if (val instanceof byte[]) - { - out2.write('='); - byte[] bval = (byte[]) val; - out2.write(bval, 0, bval.length); - } - else - { - if (val != NO_VALUE) - { - throw new IllegalArgumentException( - "invalid property value: " + val); - } - } - } - byte data[] = out2.toByteArray(); - out.write(data.length); - out.write(data, 0, data.length); - } - this.text = out.toByteArray(); - } - catch (IOException e) - { - throw new RuntimeException("unexpected exception: " + e); - } - } - } - - /** - * Construct a service description for registrating with JmDNS. - * - * @param type fully qualified service type name, - * such as _http._tcp.local.. - * @param name unqualified service instance name, - * such as foobar - * @param port the local port on which the service runs - * @param weight weight of the service - * @param priority priority of the service - * @param text bytes describing the service - */ - public ServiceInfo(String type, String name, - int port, int weight, - int priority, byte text[]) - { - this.type = type; - this.name = name; - this.port = port; - this.weight = weight; - this.priority = priority; - this.text = text; - - String SLevel = System.getProperty("jmdns.debug"); - if (SLevel == null) SLevel = "INFO"; - logger.setLevel(Level.parse(SLevel)); - } - - /** - * Construct a service record during service discovery. - */ - ServiceInfo(String type, String name) - { - if (!type.endsWith(".")) - { - throw new IllegalArgumentException( - "type must be fully qualified DNS name ending in '.': " + type); - } - - this.type = type; - this.name = name; - } - - /** - * During recovery we need to duplicate service info to reregister them - */ - ServiceInfo(ServiceInfo info) - { - if (info != null) - { - this.type = info.type; - this.name = info.name; - this.port = info.port; - this.weight = info.weight; - this.priority = info.priority; - this.text = info.text; - } - } - - /** - * Fully qualified service type name, - * such as _http._tcp.local. . - * @return Returns fully qualified service type name. - */ - public String getType() - { - return type; - } - - /** - * Unqualified service instance name, - * such as foobar . - * @return Returns unqualified service instance name. - */ - public String getName() - { - return name; - } - - /** - * Sets the service instance name. - * - * @param name unqualified service instance name, - * such as foobar - */ - void setName(String name) - { - this.name = name; - } - - /** - * Fully qualified service name, - * such as foobar._http._tcp.local. . - * @return Returns fully qualified service name. - */ - public String getQualifiedName() - { - return name + "." + type; - } - - /** - * Get the name of the server. - * @return Returns name of the server. - */ - public String getServer() - { - return server; - } - - /** - * Get the host address of the service (ie X.X.X.X). - * @return Returns host address of the service. - */ - public String getHostAddress() - { - return (addr != null ? addr.getHostAddress() : ""); - } - - public InetAddress getAddress() - { - return addr; - } - - /** - * Get the InetAddress of the service. - * @return Returns the InetAddress of the service. - */ - public InetAddress getInetAddress() - { - return addr; - } - - /** - * Get the port for the service. - * @return Returns port for the service. - */ - public int getPort() - { - return port; - } - - /** - * Get the priority of the service. - * @return Returns the priority of the service. - */ - public int getPriority() - { - return priority; - } - - /** - * Get the weight of the service. - * @return Returns the weight of the service. - */ - public int getWeight() - { - return weight; - } - - /** - * Get the text for the serivce as raw bytes. - * @return Returns the text for the serivce as raw bytes. - */ - public byte[] getTextBytes() - { - return text; - } - - /** - * Get the text for the service. This will interpret the text bytes - * as a UTF8 encoded string. Will return null if the bytes are not - * a valid UTF8 encoded string. - * @return Returns the text for the service. - */ - public String getTextString() - { - if ((text == null) || - (text.length == 0) || - ((text.length == 1) && (text[0] == 0))) - { - return null; - } - return readUTF(text, 0, text.length); - } - - /** - * Get the URL for this service. An http URL is created by - * combining the address, port, and path properties. - * @return Returns the URL for this service. - */ - public String getURL() - { - return getURL("http"); - } - - /** - * Get the URL for this service. An URL is created by - * combining the protocol, address, port, and path properties. - * @param protocol - * @return Returns URL for this service. - */ - public String getURL(String protocol) - { - String url = protocol + "://" + getHostAddress() + ":" + getPort(); - String path = getPropertyString("path"); - if (path != null) - { - if (path.indexOf("://") >= 0) - { - url = path; - } - else - { - url += path.startsWith("/") ? path : "/" + path; - } - } - return url; - } - - /** - * Get a property of the service. This involves decoding the - * text bytes into a property list. Returns null if the property - * is not found or the text data could not be decoded correctly. - * @param name - * @return Returns property of the service as bytes. - */ - public synchronized byte[] getPropertyBytes(String name) - { - return (byte[]) getProperties().get(name); - } - - /** - * Get a property of the service. This involves decoding the - * text bytes into a property list. Returns null if the property - * is not found, the text data could not be decoded correctly, or - * the resulting bytes are not a valid UTF8 string. - * @param name - * @return Returns property of the service as string. - */ - public synchronized String getPropertyString(String name) - { - byte data[] = (byte[]) getProperties().get(name); - - if (data == null) - { - return null; - } - if (data == NO_VALUE) - { - return "true"; - } - String res = readUTF(data, 0, data.length); - - return res; - } - - /** - * Iterator of the property names. - * @return Iterator of the property names. - */ - public Iterator getPropertyNames() - { - Map properties = getProperties(); - Iterable propertyNames - = (properties != null) ? properties.keySet() : new Vector(); - return propertyNames.iterator(); - } - - /** - * Write a UTF string with a length to a stream. - */ - void writeUTF(OutputStream out, String str) throws IOException - { - for (int i = 0, len = str.length(); i < len; i++) - { - int c = str.charAt(i); - if ((c >= 0x0001) && (c <= 0x007F)) - { - out.write(c); - } - else - { - if (c > 0x07FF) - { - out.write(0xE0 | ((c >> 12) & 0x0F)); - out.write(0x80 | ((c >> 6) & 0x3F)); - out.write(0x80 | ((c >> 0) & 0x3F)); - } - else - { - out.write(0xC0 | ((c >> 6) & 0x1F)); - out.write(0x80 | ((c >> 0) & 0x3F)); - } - } - } - } - - /** - * Read data bytes as a UTF stream. - */ - String readUTF(byte data[], int off, int len) - { - StringBuffer buf = new StringBuffer(); - for (int end = off + len; off < end;) - { - int ch = data[off++] & 0xFF; - switch (ch >> 4) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - // 0xxxxxxx - break; - case 12: - case 13: - if (off >= len) - { - return null; - } - // 110x xxxx 10xx xxxx - ch = ((ch & 0x1F) << 6) | (data[off++] & 0x3F); - break; - case 14: - if (off + 2 >= len) - { - return null; - } - // 1110 xxxx 10xx xxxx 10xx xxxx - ch = ((ch & 0x0f) << 12) | - ((data[off++] & 0x3F) << 6) | - (data[off++] & 0x3F); - break; - default: - if (off + 1 >= len) - { - return null; - } - // 10xx xxxx, 1111 xxxx - ch = ((ch & 0x3F) << 4) | (data[off++] & 0x0f); - break; - } - buf.append((char) ch); - } - return buf.toString(); - } - - synchronized Map getProperties() - { - if ((props == null) && (text != null)) - { - Map props = new Hashtable(); - int off = 0; - while (off < text.length) - { - // length of the next key value pair - int len = text[off++] & 0xFF; - if ((len == 0) || (off + len > text.length)) - { - props.clear(); - break; - } - // look for the '=' - int i = 0; - for (; (i < len) && (text[off + i] != '='); i++) - { - ; - } - - // get the property name - String name = readUTF(text, off, i); - if (name == null) - { - props.clear(); - break; - } - if (i == len) - { - props.put(name, NO_VALUE); - } - else - { - byte value[] = new byte[len - ++i]; - System.arraycopy(text, off + i, value, 0, len - i); - props.put(name, value); - off += len; - } - } - this.props = props; - } - return props; - } - - - /** - * JmDNS callback to update a DNS record. - * @param rec - */ - public void updateRecord(JmDNS jmdns, long now, DNSRecord rec) - { - if ((rec != null) && !rec.isExpired(now)) - { - switch (rec.type) - { - case DNSConstants.TYPE_A: // IPv4 - case DNSConstants.TYPE_AAAA: // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested - if (rec.name.equals(server)) - { - addr = ((DNSRecord.Address) rec).getAddress(); - - } - break; - case DNSConstants.TYPE_SRV: - if (rec.name.equals(getQualifiedName())) - { - DNSRecord.Service srv = (DNSRecord.Service) rec; - server = srv.server; - port = srv.port; - weight = srv.weight; - priority = srv.priority; - addr = null; - // changed to use getCache() instead - jeffs - // updateRecord(jmdns, now, (DNSRecord)jmdns.cache.get(server, TYPE_A, CLASS_IN)); - updateRecord(jmdns, - now, - (DNSRecord) jmdns.getCache().get( - server, - DNSConstants.TYPE_A, - DNSConstants.CLASS_IN)); - } - break; - case DNSConstants.TYPE_TXT: - if (rec.name.equals(getQualifiedName())) - { - DNSRecord.Text txt = (DNSRecord.Text) rec; - text = txt.text; - } - break; - } - // Future Design Pattern - // This is done, to notify the wait loop in method - // JmDNS.getServiceInfo(type, name, timeout); - if (hasData() && dns != null) - { - dns.handleServiceResolved(this); - dns = null; - } - synchronized (this) - { - notifyAll(); - } - } - } - - /** - * Returns true if the service info is filled with data. - */ - boolean hasData() - { - return server != null && addr != null && text != null; - } - - - // State machine - /** - * Sets the state and notifies all objects that wait on the ServiceInfo. - */ - synchronized void advanceState() - { - state = state.advance(); - notifyAll(); - } - - /** - * Sets the state and notifies all objects that wait on the ServiceInfo. - */ - synchronized void revertState() - { - state = state.revert(); - notifyAll(); - } - - /** - * Sets the state and notifies all objects that wait on the ServiceInfo. - */ - synchronized void cancel() - { - state = DNSState.CANCELED; - notifyAll(); - } - - /** - * Returns the current state of this info. - */ - DNSState getState() - { - return state; - } - - - @Override - public int hashCode() - { - return getQualifiedName().hashCode(); - } - - @Override - public boolean equals(Object obj) - { - return (obj instanceof ServiceInfo) && - getQualifiedName().equals(((ServiceInfo) obj).getQualifiedName()); - } - - public String getNiceTextString() - { - StringBuffer buf = new StringBuffer(); - for (int i = 0, len = text.length; i < len; i++) - { - if (i >= 20) - { - buf.append("..."); - break; - } - int ch = text[i] & 0xFF; - if ((ch < ' ') || (ch > 127)) - { - buf.append("\\0"); - buf.append(Integer.toString(ch, 8)); - } - else - { - buf.append((char) ch); - } - } - return buf.toString(); - } - - @Override - public String toString() - { - StringBuffer buf = new StringBuffer(); - buf.append("service["); - buf.append(getQualifiedName()); - buf.append(','); - buf.append(getAddress()); - buf.append(':'); - buf.append(port); - buf.append(','); - buf.append(getNiceTextString()); - buf.append(']'); - return buf.toString(); - } - - /** - * SC-Bonjour Implementation: Method used to set the properties of an existing ServiceInfo. - * This is used in the implementation of Bonjour in SIP Communicator to be able to replace - * old properties of the service we've declared to announce the local user with new properties - * (for example in case of a status change). - * @param props Hashtable containing all the new properties to set - */ - public void setProps(Map props) - { - if (props != null) - { - try - { - ByteArrayOutputStream out = new ByteArrayOutputStream(256); - for (Map.Entry prop : props.entrySet()) - { - String key = prop.getKey(); - Object val = prop.getValue(); - - ByteArrayOutputStream out2 = new ByteArrayOutputStream(100); - writeUTF(out2, key); - if (val instanceof String) - { - out2.write('='); - writeUTF(out2, (String) val); - } - else - { - if (val instanceof byte[]) - { - out2.write('='); - byte[] bval = (byte[]) val; - out2.write(bval, 0, bval.length); - } - else - { - if (val != NO_VALUE) - { - throw new IllegalArgumentException( - "invalid property value: " + val); - } - } - } - byte data[] = out2.toByteArray(); - out.write(data.length); - out.write(data, 0, data.length); - } - this.text = out.toByteArray(); - } - catch (IOException e) - { - throw new RuntimeException("unexpected exception: " + e); - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceListener.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceListener.java deleted file mode 100644 index 1c34adf..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceListener.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.*; - -/** - * Listener for service updates. - * - * @version %I%, %G% - * @author Arthur van Hoff, Werner Randelshofer - */ -public interface ServiceListener extends EventListener -{ - /** - * A service has been added. - * - * @param event The ServiceEvent providing the name and fully qualified type - * of the service. - */ - - void serviceAdded(ServiceEvent event); - - /** - * A service has been removed. - * - * @param event The ServiceEvent providing the name and fully qualified type - * of the service. - */ - void serviceRemoved(ServiceEvent event); - - /** - * A service has been resolved. Its details are now available in the - * ServiceInfo record. - * - * @param event The ServiceEvent providing the name, the fully qualified - * type of the service, and the service info record, - * or null if the service could not be resolved. - */ - - void serviceResolved(ServiceEvent event); -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceTypeListener.java b/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceTypeListener.java deleted file mode 100644 index 84e5c59..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/jmdns/ServiceTypeListener.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright 2003-2005 Arthur van Hoff Rick Blair - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.zeroconf.jmdns; - -import java.util.*; - -/** - * Listener for service types. - * - * @version %I%, %G% - * @author Arthur van Hoff, Werner Randelshofer - */ -public interface ServiceTypeListener extends EventListener -{ - /** - * A new service type was discovered. - * - * @param event The service event providing the fully qualified type of - * the service. - */ - void serviceTypeAdded(ServiceEvent event); -} diff --git a/src/net/java/sip/communicator/impl/protocol/zeroconf/zeroconf.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/zeroconf/zeroconf.provider.manifest.mf deleted file mode 100644 index 24daba0..0000000 --- a/src/net/java/sip/communicator/impl/protocol/zeroconf/zeroconf.provider.manifest.mf +++ /dev/null @@ -1,12 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.impl.protocol.zeroconf.ZeroconfActivator -Bundle-Name: Zeroconf Protocol Provider -Bundle-Description: A bundle providing support for the Zeroconf protocol. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.protocol.zeroconf -Import-Package: org.osgi.framework, - org.jitsi.service.configuration, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/FirstWizardPage.java deleted file mode 100644 index 0f8815c..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/FirstWizardPage.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.zeroconfaccregwizz; - -import java.awt.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * The FirstWizardPage is the page, where user could enter the user ID - * and the password of the account. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class FirstWizardPage - extends TransparentPanel - implements WizardPage, - DocumentListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier"; - - private JPanel userPassPanel = new TransparentPanel(new BorderLayout(10, 10)); - - private JPanel labelsPanel = new TransparentPanel(); - - private JPanel valuesPanel = new TransparentPanel(); - - private JLabel userID = new JLabel( - Resources.getString("plugin.zeroaccregwizz.USERID")); - - /* TEMPORARY : HARD CODED !! Should be added to Resource */ - private JLabel firstLabel - = new JLabel(Resources.getString("plugin.zeroaccregwizz.FIRST_NAME")); - private JLabel lastLabel - = new JLabel(Resources.getString("plugin.zeroaccregwizz.LAST_NAME")); - private JLabel mailLabel - = new JLabel(Resources.getString("plugin.zeroaccregwizz.EMAIL")); - - private JPanel emptyPanel = new TransparentPanel(); - private JPanel emptyPanel2 = new TransparentPanel(); - private JPanel emptyPanel3 = new TransparentPanel(); - private JPanel emptyPanel4 = new TransparentPanel(); - - private JLabel userIDExampleLabel = new JLabel("Ex: Bill@microsoft"); - private JLabel firstExampleLabel = new JLabel("Ex: Bill"); - private JLabel lastExampleLabel = new JLabel("Ex: Gates"); - private JLabel mailExampleLabel = new JLabel("Ex: Bill@microsoft.com"); - - private JTextField userIDField = new TrimTextField(); - private JTextField firstField = new JTextField(); - private JTextField lastField = new JTextField(); - private JTextField mailField = new JTextField(); - - private JCheckBox rememberContacts = - new SIPCommCheckBox(Resources.getString( - "plugin.zeroaccregwizz.REMEMBER_CONTACTS")); - - private JPanel mainPanel = new TransparentPanel(); - - private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER; - - private ZeroconfAccountRegistrationWizard wizard; - - private boolean isCommitted = false; - - /** - * Creates an instance of FirstWizardPage. - * - * @param wizard the parent wizard - */ - public FirstWizardPage(ZeroconfAccountRegistrationWizard wizard) - { - - super(new BorderLayout()); - - this.wizard = wizard; - - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - - this.init(); - - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.labelsPanel.setLayout( - new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); - - this.valuesPanel.setLayout( - new BoxLayout(valuesPanel, BoxLayout.Y_AXIS)); - } - - /** - * Initializes all panels, buttons, etc. - */ - private void init() - { - this.userIDField.getDocument().addDocumentListener(this); - this.firstField.getDocument().addDocumentListener(this); - this.rememberContacts.setSelected(false); - - // not used so disable it for the moment - this.rememberContacts.setEnabled(false); - - this.userIDExampleLabel.setForeground(Color.GRAY); - this.userIDExampleLabel.setFont( - userIDExampleLabel.getFont().deriveFont(8)); - this.emptyPanel.setMaximumSize(new Dimension(40, 35)); - this.userIDExampleLabel.setBorder( - BorderFactory.createEmptyBorder(0, 0, 8,0)); - - this.firstExampleLabel.setForeground(Color.GRAY); - this.firstExampleLabel.setFont( - firstExampleLabel.getFont().deriveFont(8)); - this.emptyPanel2.setMaximumSize(new Dimension(40, 35)); - this.firstExampleLabel.setBorder( - BorderFactory.createEmptyBorder(0, 0, 8,0)); - - this.lastExampleLabel.setForeground(Color.GRAY); - this.lastExampleLabel.setFont( - lastExampleLabel.getFont().deriveFont(8)); - this.emptyPanel3.setMaximumSize(new Dimension(40, 35)); - this.lastExampleLabel.setBorder( - BorderFactory.createEmptyBorder(0, 0, 8,0)); - - this.mailExampleLabel.setForeground(Color.GRAY); - this.mailExampleLabel.setFont( - mailExampleLabel.getFont().deriveFont(8)); - this.emptyPanel4.setMaximumSize(new Dimension(40, 35)); - this.mailExampleLabel.setBorder( - BorderFactory.createEmptyBorder(0, 0, 8,0)); - - labelsPanel.add(userID); - labelsPanel.add(emptyPanel); - labelsPanel.add(firstLabel); - labelsPanel.add(emptyPanel2); - labelsPanel.add(lastLabel); - labelsPanel.add(emptyPanel3); - labelsPanel.add(mailLabel); - - valuesPanel.add(userIDField); - valuesPanel.add(userIDExampleLabel); - valuesPanel.add(firstField); - valuesPanel.add(firstExampleLabel); - valuesPanel.add(lastField); - valuesPanel.add(lastExampleLabel); - valuesPanel.add(mailField); - valuesPanel.add(mailExampleLabel); - - userPassPanel.add(labelsPanel, BorderLayout.WEST); - userPassPanel.add(valuesPanel, BorderLayout.CENTER); - userPassPanel.add(rememberContacts, BorderLayout.SOUTH); - - userPassPanel.setBorder(BorderFactory.createTitledBorder( - Resources.getString("plugin.zeroaccregwizz.USERID_AND_PASSWORD"))); - - this.add(userPassPanel, BorderLayout.NORTH); - } - - /** - * Implements the WizardPage.getIdentifier to return - * this page identifier. - * - * @return the Identifier of the first page in this wizard. - */ - public Object getIdentifier() - { - return FIRST_PAGE_IDENTIFIER; - } - - /** - * Implements the WizardPage.getNextPageIdentifier to return - * the next page identifier - the summary page. - * - * @return the identifier of the page following this one. - */ - public Object getNextPageIdentifier() - { - return nextPageIdentifier; - } - - /** - * Implements the WizardPage.getBackPageIdentifier to return - * the back identifier. In this case it's null because this is the first - * wizard page. - * - * @return the identifier of the previous wizard page - */ - public Object getBackPageIdentifier() - { - return null; - } - - /** - * Implements the WizardPage.getWizardForm to return - * this panel. - * - * @return the component to be displayed in this wizard page. - */ - public Object getWizardForm() - { - return this; - } - - /** - * Before this page is displayed enables or disables the "Next" wizard - * button according to whether the UserID field is empty. - */ - public void pageShowing() - { - this.setNextButtonAccordingToUserID(); - } - - /** - * Saves the user input when the "Next" wizard buttons is clicked. - */ - public void commitPage() - { - ZeroconfAccountRegistration registration - = wizard.getRegistration(); - - String userID = userIDField.getText(); - - if(userID == null || userID.trim().length() == 0) - throw new IllegalStateException("No user ID provided."); - - registration.setUserID(userID); - registration.setFirst(firstField.getText()); - registration.setLast(lastField.getText()); - registration.setMail(mailField.getText()); - - registration.setRememberContacts(rememberContacts.isSelected()); - - nextPageIdentifier = SUMMARY_PAGE_IDENTIFIER; - - isCommitted = true; - } - - /** - * Enables or disables the "Next" wizard button according to whether the - * User ID field is empty. - */ - private void setNextButtonAccordingToUserID() - { - if (userIDField.getText() == null || userIDField.getText().equals("")) - { - wizard.getWizardContainer().setNextFinishButtonEnabled(false); - } - else - { - wizard.getWizardContainer().setNextFinishButtonEnabled(true); - } - } - - /** - * Handles the DocumentEvent triggered when user types in the - * User ID field. Enables or disables the "Next" wizard button according to - * whether the User ID field is empty. - * - * @param event the event containing the update. - */ - public void insertUpdate(DocumentEvent event) - { - this.setNextButtonAccordingToUserID(); - } - - /** - * Handles the DocumentEvent triggered when user deletes letters - * from the UserID field. Enables or disables the "Next" wizard button - * according to whether the UserID field is empty. - * - * @param event the event containing the update. - */ - public void removeUpdate(DocumentEvent event) - { - this.setNextButtonAccordingToUserID(); - } - - /** - * Implemented from Wizard interface - * @param event Event that happened - */ - public void changedUpdate(DocumentEvent event) - { - } - - /** - * Created to - */ - public void pageHiding() - { - } - - /** - * Implemented from Wizard interface - */ - public void pageShown() - { - } - - /** - * Implemented from Wizard interface - */ - public void pageBack() - { - } - - /** - * Fills the UserID field in this panel with the data comming - * from the given protocolProvider. - * @param protocolProvider The ProtocolProviderService to load the - * data from. - */ - public void loadAccount(ProtocolProviderService protocolProvider) - { - AccountID accountID = protocolProvider.getAccountID(); - - this.userIDField.setEnabled(false); - this.userIDField.setText(accountID.getUserID()); - this.firstField.setText(accountID.getAccountPropertyString("first")); - this.lastField.setText(accountID.getAccountPropertyString("last")); - this.mailField.setText(accountID.getAccountPropertyString("mail")); - - boolean remember = accountID - .getAccountPropertyBoolean("rememberContacts", true); - if (remember) - this.rememberContacts.setSelected(true); - } - - public Object getSimpleForm() - { - JPanel simplePanel = new TransparentPanel(new BorderLayout(10, 10)); - - simplePanel.add(userID, BorderLayout.WEST); - simplePanel.add(userIDField, BorderLayout.CENTER); - - return simplePanel; - } - - public boolean isCommitted() - { - return isCommitted; - } -} diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/Resources.java b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/Resources.java deleted file mode 100644 index 83b6131..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/Resources.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.zeroconfaccregwizz; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the images properties file. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - public static ImageID ZEROCONF_LOGO - = new ImageID("service.protocol.zeroconf.ZEROCONF_16x16"); - - public static ImageID PAGE_IMAGE - = new ImageID("service.protocol.zeroconf.ZEROCONF_64x64"); - - /** - * Returns an internationalized string corresponding to the given key. - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImage(ImageID imageID) - { - return getResources().getImageInBytes(imageID.getId()); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(ZeroconfAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccRegWizzActivator.java deleted file mode 100644 index 352796b..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccRegWizzActivator.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.zeroconfaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Registers the ZeroconfAccountRegistrationWizard in the UI Service. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ZeroconfAccRegWizzActivator - implements BundleActivator -{ - private static final Logger logger = - Logger.getLogger(ZeroconfAccRegWizzActivator.class); - - /** - * A currently valid bundle context. - */ - public static BundleContext bundleContext; - - private static UIService uiService; - - /** - * Starts this bundle. - * @param bc the currently valid BundleContext. - */ - public void start(BundleContext bc) - { - if (logger.isInfoEnabled()) - logger.info("Loading zeroconf account wizard."); - - bundleContext = bc; - - ServiceReference uiServiceRef = bundleContext - .getServiceReference(UIService.class.getName()); - - uiService = (UIService) bundleContext.getService(uiServiceRef); - - WizardContainer wizardContainer - = uiService.getAccountRegWizardContainer(); - - ZeroconfAccountRegistrationWizard zeroconfWizard - = new ZeroconfAccountRegistrationWizard(wizardContainer); - - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.ZEROCONF); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - zeroconfWizard, - containerFilter); - - if (logger.isInfoEnabled()) - logger.info("Zeroconf account registration wizard [STARTED]."); - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param context The execution context of the bundle being stopped. - */ - public void stop(BundleContext context) - { - - } - - /** - * Returns the ProtocolProviderFactory for the Zeroconf protocol. - * @return the ProtocolProviderFactory for the Zeroconf protocol - */ - public static ProtocolProviderFactory getZeroconfProtocolProviderFactory() - { - ServiceReference[] serRefs = null; - String osgiFilter - = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" - + ProtocolNames.ZEROCONF - + ")"; - - try - { - serRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), - osgiFilter); - } - catch (InvalidSyntaxException ex) - { - logger.error(ex); - } - - return - (serRefs == null) - ? null - : (ProtocolProviderFactory) - bundleContext.getService(serRefs[0]); - } - - /** - * Returns the bundleContext that we received when we were started. - * @return a currently valid instance of a bundleContext. - */ - public BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } -} diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistration.java b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistration.java deleted file mode 100644 index df4f6f5..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistration.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.zeroconfaccregwizz; - -/** - * The ZeroconfAccountRegistration is used to store - * all user input data - * through the ZeroconfAccountRegistrationWizard. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ZeroconfAccountRegistration -{ - private String userID; - private String first; - private String last; - private String mail; - private boolean rememberContacts; - - /** - * Returns the User ID of the zeroconf registration account. - * @return the User ID of the zeroconf registration account. - */ - public String getUserID() - { - return userID; - } - - /** - * Sets the user ID of the zeroconf registration account. - * @param userID the userID of the zeroconf registration account. - */ - public void setUserID(String userID) - { - this.userID = userID; - } - - /** - * Returns the password of the Zeroconf registration account. - * @return the password of the Zeroconf registration account. - */ - public String getFirst() - { - return first; - } - - /** - * Sets the password of the Zeroconf registration account. - * @param first first name - */ - public void setFirst(String first) - { - this.first = first; - } - - /** - * Returns true if password has to remembered, false - * otherwise. - * @return true if password has to remembered, false - * otherwise. - */ - public boolean isRememberContacts() - { - return rememberContacts; - } - - /** - * Sets the rememberPassword value of this Zeroconf account registration. - * @param rememberContacts true if we want to remember the - * contacts we meet, false otherwise - */ - public void setRememberContacts(boolean rememberContacts) - { - this.rememberContacts = rememberContacts; - } - - /** - * Returns the last name - * @return last name - */ - public String getLast() - { - return last; - } - - /** - * Sets the last name - * @param last last name - */ - public void setLast(String last) - { - this.last = last; - } - - /** - * Returns the mail address - * @return mail address - */ - public String getMail() - { - return mail; - } - - /** - * Sets the mail address - * @param mail mail address - */ - public void setMail(String mail) - { - this.mail = mail; - } - - -} diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistrationWizard.java deleted file mode 100644 index 79f085f..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/ZeroconfAccountRegistrationWizard.java +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.zeroconfaccregwizz; - -import java.awt.*; -import java.util.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The ZeroconfAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Zeroconf protocol. It allows - * the user to create and configure a new Zeroconf account. - * - * @author Christian Vincenot - * @author Maxime Catelin - */ -public class ZeroconfAccountRegistrationWizard - extends DesktopAccountRegistrationWizard -{ - private Logger logger - = Logger.getLogger(ZeroconfAccountRegistrationWizard.class); - - /** - * The first page of the zeroconf account registration wizard. - */ - private FirstWizardPage firstWizardPage; - - /** - * The object that we use to store details on an account that we will be - * creating. - */ - private ZeroconfAccountRegistration registration - = new ZeroconfAccountRegistration(); - - private ProtocolProviderService protocolProvider; - - /** - * Creates an instance of ZeroconfAccountRegistrationWizard. - * @param wizardContainer the wizard container, where this wizard - * is added - */ - public ZeroconfAccountRegistrationWizard(WizardContainer wizardContainer) - { - setWizardContainer(wizardContainer); - - wizardContainer - .setFinishButtonText(Resources.getString("service.gui.SIGN_IN")); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return Resources.getImage(Resources.ZEROCONF_LOGO); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Resources.getImage(Resources.PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString("plugin.zeroaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources.getString("plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - java.util.List pages = new ArrayList(); - - // create new registration, our container needs the pages - // this means this is a new wizard and we must reset all data - // it will be invoked and when the wizard cleans and unregister - // our pages, but this fix don't hurt in this situation. - this.registration = new ZeroconfAccountRegistration(); - - firstWizardPage = new FirstWizardPage(this); - - pages.add(firstWizardPage); - - return pages.iterator(); - } - - /** - * Returns the set of data that user has entered through this wizard. - * @return Iterator - */ - @Override - public Iterator> getSummary() - { - Hashtable summaryTable = new Hashtable(); - - summaryTable.put("User ID", registration.getUserID()); - summaryTable.put("First Name", registration.getFirst()); - summaryTable.put("Last Name", registration.getLast()); - summaryTable.put("Mail Address", registration.getMail()); - summaryTable.put("Remember Bonjour contacts?", - Boolean.toString(registration.isRememberContacts())); - - return summaryTable.entrySet().iterator(); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin() - throws OperationFailedException - { - firstWizardPage.commitPage(); - - return signin(registration.getUserID(), null); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @param userName the user name to sign in with - * @param password the password to sign in with - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin(String userName, String password) - throws OperationFailedException - { - ProtocolProviderFactory factory - = ZeroconfAccRegWizzActivator.getZeroconfProtocolProviderFactory(); - - return this.installAccount(factory, - userName); - } - - /** - * Creates an account for the given user and password. - * - * @return the ProtocolProviderService for the new account. - * @param providerFactory the ProtocolProviderFactory which will create - * the account - * @param user the user identifier - */ - public ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, - String user) - throws OperationFailedException - { - Hashtable accountProperties - = new Hashtable(); - - accountProperties.put(ProtocolProviderFactory.ACCOUNT_ICON_PATH, - "resources/images/protocol/zeroconf/zeroconf32x32.png"); - - accountProperties.put("first", registration.getFirst()); - accountProperties.put("last", registration.getLast()); - accountProperties.put("mail", registration.getMail()); - - accountProperties.put( - ProtocolProviderFactory.NO_PASSWORD_REQUIRED, - new Boolean(true).toString()); - - accountProperties.put("rememberContacts", - new Boolean(registration.isRememberContacts()).toString()); - - if (isModification()) - { - providerFactory.uninstallAccount(protocolProvider.getAccountID()); - this.protocolProvider = null; - setModification(false); - } - - try - { - AccountID accountID = providerFactory.installAccount( - user, accountProperties); - - ServiceReference serRef = providerFactory - .getProviderForAccount(accountID); - - protocolProvider = (ProtocolProviderService) - ZeroconfAccRegWizzActivator.bundleContext - .getService(serRef); - } - catch (IllegalStateException exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Account already exists.", - OperationFailedException.IDENTIFICATION_CONFLICT); - } - catch (Exception exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Failed to add account", - OperationFailedException.GENERAL_ERROR); - } - - - return protocolProvider; - } - - /** - * Fills the UserID and Password fields in this panel with the data coming - * from the given protocolProvider. - * @param protocolProvider The ProtocolProviderService to load the - * data from. - */ - @Override - public void loadAccount(ProtocolProviderService protocolProvider) - { - setModification(true); - - this.protocolProvider = protocolProvider; - - this.registration = new ZeroconfAccountRegistration(); - - this.firstWizardPage.loadAccount(protocolProvider); - } - - /** - * Returns the registration object, which will store all the data through - * the wizard. - * - * @return the registration object, which will store all the data through - * the wizard - */ - public ZeroconfAccountRegistration getRegistration() - { - return registration; - } - - /** - * Returns the size of this wizard. - * @return the size of this wizard - */ - @Override - public Dimension getSize() - { - return new Dimension(600, 500); - } - - /** - * Returns the identifier of the page to show first in the wizard. - * @return the identifier of the page to show first in the wizard. - */ - @Override - public Object getFirstPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns the identifier of the page to show last in the wizard. - * @return the identifier of the page to show last in the wizard. - */ - @Override - public Object getLastPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns the password label for the simplified account registration form. - * @return the password label for the simplified account registration form. - */ - public String getPasswordLabel() - { - return Resources.getString("service.gui.PASSWORD"); - } - - /** - * Returns the user name label for the simplified account registration - * form. - * - * @return the user name label for the simplified account registration - * form. - */ - public String getUserNameLabel() - { - return Resources.getString("userID"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return null; - } - - /** - * Indicates whether this wizard enables the simple "sign in" form shown - * when the user opens the application for the first time. The simple - * "sign in" form allows user to configure her account in one click, just - * specifying her username and password and leaving any other configuration - * as by default. - * @return true if the simple "Sign in" form is enabled or - * false otherwise. - */ - @Override - public boolean isSimpleFormEnabled() - { - return false; - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - // when creating first wizard page, create and new - // AccountRegistration to avoid reusing old instances and - // data left from old registrations - this.registration = new ZeroconfAccountRegistration(); - - firstWizardPage = new FirstWizardPage(this); - return firstWizardPage.getSimpleForm(); - } -} diff --git a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/zeroconfaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/zeroconfaccregwizz.manifest.mf deleted file mode 100644 index 57a863b..0000000 --- a/src/net/java/sip/communicator/plugin/zeroconfaccregwizz/zeroconfaccregwizz.manifest.mf +++ /dev/null @@ -1,32 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.zeroconfaccregwizz.ZeroconfAccRegWizzActivator -Bundle-Name: Zeroconf account registration wizard -Bundle-Description: Zeroconf account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.zeroconfaccregwizz -Import-Package: org.osgi.framework, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - javax.swing, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.accessibility, - javax.swing.plaf, - javax.swing.plaf.metal, - javax.swing.plaf.basic, - javax.imageio, - javax.swing.filechooser, - javax.swing.tree, - javax.swing.undo, - javax.swing.border -- cgit v1.1 From f5422c7fe3ebfda0b0034ebbcce5ca6c227950f5 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 20:00:19 +0200 Subject: Remove solaris stuff --- build.xml | 29 ----------------------------- lib/native/solaris/libCvidPro.so | Bin 157720 -> 0 bytes lib/native/solaris/soundbank.gm | Bin 1154250 -> 0 bytes web-start/WebStartBuild.xml | 1 - 4 files changed, 30 deletions(-) delete mode 100644 lib/native/solaris/libCvidPro.so delete mode 100644 lib/native/solaris/soundbank.gm diff --git a/build.xml b/build.xml index a86f850..a036c49 100644 --- a/build.xml +++ b/build.xml @@ -11,7 +11,6 @@ - @@ -23,8 +22,6 @@ - - @@ -122,31 +119,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - @@ -515,7 +487,6 @@ - diff --git a/lib/native/solaris/libCvidPro.so b/lib/native/solaris/libCvidPro.so deleted file mode 100644 index dcad6f9..0000000 Binary files a/lib/native/solaris/libCvidPro.so and /dev/null differ diff --git a/lib/native/solaris/soundbank.gm b/lib/native/solaris/soundbank.gm deleted file mode 100644 index 1b3f8dc..0000000 Binary files a/lib/native/solaris/soundbank.gm and /dev/null differ diff --git a/web-start/WebStartBuild.xml b/web-start/WebStartBuild.xml index 46e38d0..2289cab 100644 --- a/web-start/WebStartBuild.xml +++ b/web-start/WebStartBuild.xml @@ -31,7 +31,6 @@ - -- cgit v1.1 From 86f1c9216f2eb91523dee391b3166108d5acfe25 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 20:11:31 +0200 Subject: Remove SwingWorker library, it is included in Java 7 --- .classpath | 1 - build.xml | 1 - lib/installer-exclude/swing-worker-1.2.jar | Bin 12852 -> 0 bytes resources/install/debian/patches/encoding.patch | 17 ----------------- .../main/chat/conference/ConferenceChatManager.java | 2 +- 5 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 lib/installer-exclude/swing-worker-1.2.jar delete mode 100644 resources/install/debian/patches/encoding.patch diff --git a/.classpath b/.classpath index 605ad0c..9d0d798 100755 --- a/.classpath +++ b/.classpath @@ -63,7 +63,6 @@ - diff --git a/build.xml b/build.xml index a036c49..289f21c 100644 --- a/build.xml +++ b/build.xml @@ -1601,7 +1601,6 @@ javax.swing.event, javax.swing.border"/> manifest="${src}/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf"> - diff --git a/lib/installer-exclude/swing-worker-1.2.jar b/lib/installer-exclude/swing-worker-1.2.jar deleted file mode 100644 index 6953042..0000000 Binary files a/lib/installer-exclude/swing-worker-1.2.jar and /dev/null differ diff --git a/resources/install/debian/patches/encoding.patch b/resources/install/debian/patches/encoding.patch deleted file mode 100644 index 09176fd..0000000 --- a/resources/install/debian/patches/encoding.patch +++ /dev/null @@ -1,17 +0,0 @@ -Description: Set encoding for javadoc to fix errors with Java 7 -Author: Colin Watson -Bug-Debian: https://bugs.debian.org/759835 -Forwarded: no -Last-Update: 2014-09-05 - ---- jitsi.orig/lib/src/swingworker/build.xml -+++ jitsi/lib/src/swingworker/build.xml -@@ -63,7 +63,7 @@ reserved. Use is subject to license term - -+ nonavbar="false" notree="false" use="true" version="true" encoding="iso-8859-1"> - - - diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java index 079e22b..89ceb48 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java @@ -21,6 +21,7 @@ import java.util.*; import java.util.concurrent.*; import javax.swing.*; +import javax.swing.SwingWorker; import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.chat.*; @@ -35,7 +36,6 @@ import net.java.sip.communicator.service.protocol.globalstatus.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; -import org.jdesktop.swingworker.SwingWorker; import org.jitsi.util.*; import org.osgi.framework.*; -- cgit v1.1 From 5d6893eb92e2b1a210e5acb851d9a6fb5f3b82fb Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 4 Jun 2016 20:20:52 +0200 Subject: Remove unix socket, it isn't used anywhere --- .classpath | 1 - build.xml | 1 - lib/installer-exclude/unix-0.5.jar | Bin 8323 -> 0 bytes m2/jitsi-sysactivity/pom.xml | 16 ---------------- nbproject/project.xml | 2 +- resources/install/build.xml | 3 --- resources/install/debian/control-src.tmpl | 1 - 7 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 lib/installer-exclude/unix-0.5.jar diff --git a/.classpath b/.classpath index 9d0d798..5131ace 100755 --- a/.classpath +++ b/.classpath @@ -64,7 +64,6 @@ - diff --git a/build.xml b/build.xml index 289f21c..691c683 100644 --- a/build.xml +++ b/build.xml @@ -2616,7 +2616,6 @@ org.bouncycastle.util"/> - diff --git a/lib/installer-exclude/unix-0.5.jar b/lib/installer-exclude/unix-0.5.jar deleted file mode 100644 index d9810d9..0000000 Binary files a/lib/installer-exclude/unix-0.5.jar and /dev/null differ diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml index 0f45f4d..4151bd1 100644 --- a/m2/jitsi-sysactivity/pom.xml +++ b/m2/jitsi-sysactivity/pom.xml @@ -22,22 +22,6 @@ dbus-java 2.7 - - org.abstractj.libmatthew - hexdump - 0.2.1 - - - org.abstractj.libmatthew - unix - 0.5.1 - - - org.abstractj.libmatthew - libunix - 0.5.1 - so - ${project.groupId} diff --git a/nbproject/project.xml b/nbproject/project.xml index ba9c55e..633b4f1 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 diff --git a/resources/install/build.xml b/resources/install/build.xml index 9de80cf..956a762 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -3311,9 +3311,6 @@ - Date: Sat, 4 Jun 2016 22:36:51 +0200 Subject: Remove external httpclient manifest --- lib/installer-exclude/httpclient.manifest.mf | 41 ---------------------------- 1 file changed, 41 deletions(-) delete mode 100644 lib/installer-exclude/httpclient.manifest.mf diff --git a/lib/installer-exclude/httpclient.manifest.mf b/lib/installer-exclude/httpclient.manifest.mf deleted file mode 100644 index bbd83f0..0000000 --- a/lib/installer-exclude/httpclient.manifest.mf +++ /dev/null @@ -1,41 +0,0 @@ -Bundle-Name: Apache Http Client -Bundle-Description: Apache Http Client -Bundle-Vendor: jitsi.org -Bundle-Version: 4.2.3 -Bundle-SymbolicName: org.apache.http -Import-Package: org.apache.commons.logging, - javax.security.auth.x500, - javax.net.ssl -Export-Package: org.apache.http, - org.apache.http.entity, - org.apache.http.entity.mime, - org.apache.http.entity.mime.content, - org.apache.http.impl, - org.apache.http.impl.auth, - org.apache.http.impl.client, - org.apache.http.impl.conn, - org.apache.http.impl.entity, - org.apache.http.impl.io, - org.apache.http.io, - org.apache.http.message, - org.apache.http.params, - org.apache.http.protocol, - org.apache.http.util, - org.apache.http.annotation, - org.apache.http.auth, - org.apache.http.auth.params, - org.apache.http.client, - org.apache.http.client.entity, - org.apache.http.client.methods, - org.apache.http.client.params, - org.apache.http.client.protocol, - org.apache.http.client.utils, - org.apache.http.conn, - org.apache.http.conn.params, - org.apache.http.conn.routing, - org.apache.http.conn.scheme, - org.apache.http.conn.ssl, - org.apache.http.conn.util, - org.apache.http.impl.client - - -- cgit v1.1 From ce76d532db31fb6f30cbe299b1607c059c277f73 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 7 Jun 2016 22:11:56 +0200 Subject: Revert "Remove unix socket, it isn't used anywhere" This reverts commit 5d6893eb92e2b1a210e5acb851d9a6fb5f3b82fb. --- .classpath | 1 + build.xml | 1 + lib/installer-exclude/unix-0.5.jar | Bin 0 -> 8323 bytes m2/jitsi-sysactivity/pom.xml | 16 ++++++++++++++++ nbproject/project.xml | 2 +- resources/install/build.xml | 3 +++ resources/install/debian/control-src.tmpl | 1 + 7 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 lib/installer-exclude/unix-0.5.jar diff --git a/.classpath b/.classpath index 5131ace..9d0d798 100755 --- a/.classpath +++ b/.classpath @@ -64,6 +64,7 @@ + diff --git a/build.xml b/build.xml index 691c683..289f21c 100644 --- a/build.xml +++ b/build.xml @@ -2616,6 +2616,7 @@ org.bouncycastle.util"/> + diff --git a/lib/installer-exclude/unix-0.5.jar b/lib/installer-exclude/unix-0.5.jar new file mode 100644 index 0000000..d9810d9 Binary files /dev/null and b/lib/installer-exclude/unix-0.5.jar differ diff --git a/m2/jitsi-sysactivity/pom.xml b/m2/jitsi-sysactivity/pom.xml index 4151bd1..0f45f4d 100644 --- a/m2/jitsi-sysactivity/pom.xml +++ b/m2/jitsi-sysactivity/pom.xml @@ -22,6 +22,22 @@ dbus-java 2.7 + + org.abstractj.libmatthew + hexdump + 0.2.1 + + + org.abstractj.libmatthew + unix + 0.5.1 + + + org.abstractj.libmatthew + libunix + 0.5.1 + so + ${project.groupId} diff --git a/nbproject/project.xml b/nbproject/project.xml index 633b4f1..ba9c55e 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 diff --git a/resources/install/build.xml b/resources/install/build.xml index 956a762..9de80cf 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -3311,6 +3311,9 @@ + Date: Tue, 7 Jun 2016 22:18:54 +0200 Subject: Revert "Remove unused hexdump library" This reverts commit 6ebeb9189f578eee78d3a930a2bbb67bdfe9b0e6. --- .classpath | 1 + build.xml | 1 + lib/installer-exclude/hexdump-0.2.jar | Bin 0 -> 1633 bytes 3 files changed, 2 insertions(+) create mode 100644 lib/installer-exclude/hexdump-0.2.jar diff --git a/.classpath b/.classpath index 9d0d798..1e82588 100755 --- a/.classpath +++ b/.classpath @@ -27,6 +27,7 @@ + diff --git a/build.xml b/build.xml index 289f21c..1be362d 100644 --- a/build.xml +++ b/build.xml @@ -2617,6 +2617,7 @@ org.bouncycastle.util"/> prefix="net/java/sip/communicator/service/sysactivity" /> + diff --git a/lib/installer-exclude/hexdump-0.2.jar b/lib/installer-exclude/hexdump-0.2.jar new file mode 100644 index 0000000..4fb5ee1 Binary files /dev/null and b/lib/installer-exclude/hexdump-0.2.jar differ -- cgit v1.1 From d66d0ddcf7485a3ee77a14bc1a595cd4297d3b42 Mon Sep 17 00:00:00 2001 From: damencho Date: Fri, 10 Jun 2016 10:54:07 -0500 Subject: Adds a check whether provider is registered in sip uri handler. If not checked, after starting jitsi with parameter and it registers we end up with two calls(to call windows). --- .../java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java index 885455a..f62677e 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java @@ -351,7 +351,11 @@ public class UriHandlerSipImpl // Even if not registered after the timeout, try the call // anyway and the error popup will appear to ask the // user if they want to register - handleUri(uri, provider); + if(provider.getRegistrationState() + != RegistrationState.REGISTERED) + { + handleUri(uri, provider); + } } }, initialRegistrationTimeout); } -- cgit v1.1 From 45554a7a2ec4f20eb6905d6aba98ffb861bb0cef Mon Sep 17 00:00:00 2001 From: damencho Date: Fri, 10 Jun 2016 11:05:47 -0500 Subject: Temporary disable sip message tests. --- .../communicator/slick/protocol/sip/SipProtocolProviderServiceLick.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/net/java/sip/communicator/slick/protocol/sip/SipProtocolProviderServiceLick.java b/test/net/java/sip/communicator/slick/protocol/sip/SipProtocolProviderServiceLick.java index 9d192fe..d599b80 100644 --- a/test/net/java/sip/communicator/slick/protocol/sip/SipProtocolProviderServiceLick.java +++ b/test/net/java/sip/communicator/slick/protocol/sip/SipProtocolProviderServiceLick.java @@ -120,7 +120,7 @@ public class SipProtocolProviderServiceLick addTest(TestOperationSetPersistentPresence.suite()); //IM test - addTest(TestOperationSetBasicInstantMessaging.suite()); + //addTest(TestOperationSetBasicInstantMessaging.suite()); // telephony addTestSuite(TestOperationSetBasicTelephonySipImpl.class); -- cgit v1.1 From 005efc59c547adc56d0f8a6f192dc3b796407807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BC=D1=8F=D0=BD=20=D0=9C=D0=B8=D0=BD=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Sat, 11 Jun 2016 06:04:05 -0500 Subject: Adds parameter to sip command line calling. (#270) Adds a parameter to enable video on sip calling. You can call $jitsi sip:someaddr@domain.org?video=true. --- .../impl/protocol/sip/UriHandlerSipImpl.java | 27 +++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java index f62677e..ecec5c5 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/UriHandlerSipImpl.java @@ -405,9 +405,34 @@ public class UriHandlerSipImpl OperationSetBasicTelephony telephonyOpSet = provider.getOperationSet(OperationSetBasicTelephony.class); + OperationSetVideoTelephony videoTelephonyOpSet + = provider.getOperationSet(OperationSetVideoTelephony.class); + + boolean videoCall = false; + if(videoTelephonyOpSet != null + && uri.contains("?")) + { + String params = uri.substring(uri.indexOf('?') + 1); + uri = uri.substring(0, uri.indexOf('?')); + + StringTokenizer paramTokens = new StringTokenizer(params, "&"); + while(paramTokens.hasMoreTokens()) + { + String tok = paramTokens.nextToken(); + String[] keyValue = tok.split("\\="); + if (keyValue.length == 2 + && keyValue[0].equalsIgnoreCase("video") + && keyValue[1].equalsIgnoreCase("true")) + videoCall = true; + } + } + try { - telephonyOpSet.createCall(uri); + if(videoCall) + videoTelephonyOpSet.createVideoCall(uri); + else + telephonyOpSet.createCall(uri); } catch (OperationFailedException exc) { -- cgit v1.1 From 3ccebdc455b39218f42243d35b4d12e3fec7e822 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 26 Jun 2016 21:20:19 +0200 Subject: Fix a NPE when a domain has non-SIP NAPTR records --- .../java/sip/communicator/util/NetworkUtils.java | 28 +++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/net/java/sip/communicator/util/NetworkUtils.java b/src/net/java/sip/communicator/util/NetworkUtils.java index 5b641b9..427f176 100644 --- a/src/net/java/sip/communicator/util/NetworkUtils.java +++ b/src/net/java/sip/communicator/util/NetworkUtils.java @@ -752,30 +752,38 @@ public class NetworkUtils return null; } - String[][] recVals = new String[records.length][4]; + List recVals = new ArrayList<>(records.length); for (int i = 0; i < records.length; i++) { + String[] recVal = new String[4]; NAPTRRecord r = (NAPTRRecord)records[i]; // todo - check here for broken records as missing transport - recVals[i][0] = "" + r.getOrder(); - recVals[i][1] = getProtocolFromNAPTRRecords(r.getService()); + recVal[0] = "" + r.getOrder(); + recVal[1] = getProtocolFromNAPTRRecords(r.getService()); + if (recVal[1] == null) + { + // we don't understand this NAPTR, maybe it's not for SIP? + continue; + } + String replacement = r.getReplacement().toString(); if (replacement.endsWith(".")) { - recVals[i][2] = + recVal[2] = replacement.substring(0, replacement.length() - 1); } else { - recVals[i][2] = replacement; + recVal[2] = replacement; } - recVals[i][3] = "" + r.getPreference(); + recVal[3] = "" + r.getPreference(); + recVals.add(recVal); } // sort the SRV RRs by RR value (lower is preferred) - Arrays.sort(recVals, new Comparator() + Collections.sort(recVals, new Comparator() { // Sorts NAPTR records by ORDER (low number first), PREFERENCE (low // number first) and PROTOCOL (0-TLS, 1-TCP, 2-UDP). @@ -806,10 +814,12 @@ public class NetworkUtils } }); + String[][] arrayResult = new String[recVals.size()][4]; + arrayResult = recVals.toArray(arrayResult); if(logger.isTraceEnabled()) logger.trace("NAPTRs for " + domain + "=" - + Arrays.toString(recVals)); - return recVals; + + Arrays.toString(arrayResult)); + return arrayResult; } /** -- cgit v1.1 From 87db51656a500a85128e2eec00861d23d51b98cb Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 28 Jun 2016 23:47:49 +0200 Subject: Add a few improvements for reg-less SIP accounts - Fix contact addresses not allowing a domain/port - No failure while subscribing to MWI without an address - On timeout, don't disconnect (there's no connection anyway...) --- .../java/sip/communicator/impl/protocol/sip/ContactSipImpl.java | 2 +- .../impl/protocol/sip/OperationSetMessageWaitingSipImpl.java | 4 ++++ .../impl/protocol/sip/ProtocolProviderServiceSipImpl.java | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java index 7f30e4f..d4662dd 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ContactSipImpl.java @@ -172,7 +172,7 @@ public class ContactSipImpl public String getAddress() { SipURI sipURI = (SipURI) sipAddress.getURI(); - return sipURI.getUser() + "@" + sipURI.getHost(); + return sipURI.toString().substring(sipURI.getScheme().length() + 1); } /** diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetMessageWaitingSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetMessageWaitingSipImpl.java index 28fce28..7972ee8 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetMessageWaitingSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetMessageWaitingSipImpl.java @@ -209,6 +209,10 @@ public class OperationSetMessageWaitingSipImpl try { subscribeAddress = getSubscribeAddress(); + if (subscribeAddress == null) + { + return; + } } catch (ParseException e) { diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index a978de8..009af86 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -279,6 +279,10 @@ public class ProtocolProviderServiceSipImpl { return true; } + else if (address.toString().equals(address.getURI().getScheme() + ":" + contactId)) + { + return true; + } else { result.add(SipActivator.getResources().getI18NString( @@ -2765,6 +2769,11 @@ public class ProtocolProviderServiceSipImpl */ protected void notifyConnectionFailed() { + if (sipRegistrarConnection.isRegistrarless()) + { + return; + } + if(getRegistrationState().equals(RegistrationState.REGISTERED) && sipRegistrarConnection != null) sipRegistrarConnection.setRegistrationState( -- cgit v1.1 From 5d9f0844914bb00732b5cb82670b422230499ccb Mon Sep 17 00:00:00 2001 From: damencho Date: Thu, 30 Jun 2016 23:39:21 -0500 Subject: Adds dependency to new keyring and new repo update. Removes old handling of the repo and key. --- resources/install/build.xml | 13 ---- resources/install/debian/control.tmpl | 2 +- resources/install/debian/postinst | 129 ---------------------------------- resources/install/debian/postrm | 56 --------------- 4 files changed, 1 insertion(+), 199 deletions(-) delete mode 100644 resources/install/debian/postinst delete mode 100644 resources/install/debian/postrm diff --git a/resources/install/build.xml b/resources/install/build.xml index 9de80cf..6dc3441 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -2331,9 +2331,6 @@ todir="${debianize.dir}" overwrite="true"/> - - - @@ -2536,16 +2533,6 @@ token="/usr/lib/jni" value="$SCDIR/lib/native"/> - - - - - /dev/null 2>&1 </dev/null) - - # Don't do anything if the file is there, since that probably means - # we have already installed it - if [ -r "$SOURCELIST" ]; then - if [ ! "$REPOMATCH" ]; then - # At this point wrong configuration is active. In that case, - # just abandon the mess and recreate the file - # with the correct configuration. - printf "$SOURCES_PREAMBLE" > "$SOURCELIST" - printf "$REPOCONFIG\n" >> "$SOURCELIST" - - if [ $? -eq 0 ]; then - return 0 - fi - return 2 - fi - fi - - if [ -d "$APT_SOURCESDIR" ]; then - printf "$SOURCES_PREAMBLE" > "$SOURCELIST" - printf "$REPOCONFIG\n" >> "$SOURCELIST" - if [ $? -eq 0 ]; then - return 0 - fi - fi - return 2 -} - -## MAIN ## -install_key -create_sources_lists diff --git a/resources/install/debian/postrm b/resources/install/debian/postrm deleted file mode 100644 index 66317be..0000000 --- a/resources/install/debian/postrm +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# Jitsi, the OpenSource Java VoIP and Instant Messaging client. -# -# Copyright @ 2015 Atlassian Pty Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# sources.list setting for Jitsi updates. -REPOCONFIG="deb http://download.jitsi.org/deb unstable/" - -APT_CONFIG="`which apt-config 2> /dev/null`" - -# Parse apt configuration and return requested variable value. -apt_config_val() { - APTVAR="$1" - if [ -x "$APT_CONFIG" ]; then - "$APT_CONFIG" dump | sed -e "/^$APTVAR /"'!d' -e "s/^$APTVAR \"\(.*\)\".*/\1/" - fi -} - -# Set variables for the locations of the apt sources lists. -find_apt_sources() { - APTDIR=$(apt_config_val Dir) - APTETC=$(apt_config_val 'Dir::Etc') - APT_SOURCES="$APTDIR$APTETC$(apt_config_val 'Dir::Etc::sourcelist')" - APT_SOURCESDIR="$APTDIR$APTETC$(apt_config_val 'Dir::Etc::sourceparts')" -} - -# Remove our custom sources list file. -# Returns: -# 0 - successfully removed, or not configured -# !0 - failed to remove -clean_sources_lists() { - if [ ! "$REPOCONFIG" ]; then - return 0 - fi - - find_apt_sources - - rm -f "$APT_SOURCESDIR/jitsi.list" -} - -# Remove any Jitsi repository added by the package. -clean_sources_lists -- cgit v1.1 From 0c3dd3e1ea95b42be4fba00c375162974f1d193e Mon Sep 17 00:00:00 2001 From: Nik Date: Tue, 5 Jul 2016 22:43:44 +0200 Subject: call window can now be dragged (#279) --- src/net/java/sip/communicator/impl/gui/main/call/PreCallDialog.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/call/PreCallDialog.java b/src/net/java/sip/communicator/impl/gui/main/call/PreCallDialog.java index 76c4139..0d6206a 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/PreCallDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/PreCallDialog.java @@ -256,8 +256,12 @@ public abstract class PreCallDialog receivedCallWindow.setAlwaysOnTop(true); + // Register the JFrame so the dialog window is able to get dragged + // across the screen + ComponentMover.registerComponent(receivedCallWindow); + // prevents dialog window to get unwanted key events and when going - // on top on linux, it steals focus and if we are accidently + // on top on linux, it steals focus and if we are accidentally // writing something and pressing enter a call get answered receivedCallWindow.setFocusableWindowState(false); -- cgit v1.1 From a8b817046cb049acd51008d6466d89fedcdd0524 Mon Sep 17 00:00:00 2001 From: Mathieu Mitchell Date: Tue, 5 Jul 2016 16:57:54 -0400 Subject: Fix typo in Bandwidth (#276) --- resources/languages/resources.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 45da14a..44f0c70 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -694,7 +694,7 @@ service.gui.callinfo.AUDIO_INFO=Audio info service.gui.callinfo.VIDEO_INFO=Video info service.gui.callinfo.LOCAL_IP=Local IP / Port service.gui.callinfo.REMOTE_IP=Remote IP / Port -service.gui.callinfo.BANDWITH=Bandwith +service.gui.callinfo.BANDWITH=Bandwidth service.gui.callinfo.LOSS_RATE=Loss rate service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter -- cgit v1.1 From 3961c5df59d60e0edc0f9ab02fb07b24d122cff6 Mon Sep 17 00:00:00 2001 From: Nik Date: Tue, 5 Jul 2016 23:48:14 +0200 Subject: code clean up (#277) * code cleanup * code cleanup * code cleanup * code cleanup --- .../impl/protocol/jabber/CallPeerJabberImpl.java | 19 +-- .../jabber/CallPeerMediaHandlerJabberImpl.java | 44 +++---- .../protocol/jabber/IceUdpTransportManager.java | 112 ++++++++++++---- .../protocol/sip/CallPeerMediaHandlerSipImpl.java | 48 +++---- .../impl/protocol/sip/CallSipImpl.java | 66 +++++----- .../sip/OperationSetBasicTelephonySipImpl.java | 15 +-- .../impl/protocol/sip/sdp/SdpUtils.java | 11 +- .../protocol/media/CallPeerMediaHandler.java | 19 +-- .../service/protocol/media/TransportManager.java | 143 +++++++++++---------- 9 files changed, 269 insertions(+), 208 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java index ef78202..69af6ae 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java @@ -1610,14 +1610,17 @@ public class CallPeerJabberImpl */ public void setSenders(MediaType mediaType, SendersEnum senders) { - if (mediaType == null) - return; - else if (MediaType.AUDIO.equals(mediaType)) - this.audioSenders = senders; - else if (MediaType.VIDEO.equals(mediaType)) - this.videoSenders = senders; - else - throw new IllegalArgumentException("mediaType"); + switch(mediaType) + { + case AUDIO: + this.audioSenders = senders; + break; + case VIDEO: + this.videoSenders = senders; + break; + default: + throw new IllegalArgumentException("mediaType"); + } } /** diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java index 2c8845d..979d696 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java @@ -937,19 +937,18 @@ public class CallPeerMediaHandlerJabberImpl if (supportedTransports != null && supportedTransports.length > 0) { - for (int i = 0; i < supportedTransports.length; i++) + for(String supportedTransport : supportedTransports) { if (ProtocolProviderServiceJabberImpl. URN_XMPP_JINGLE_ICE_UDP_1. - equals(supportedTransports[i])) + equals(supportedTransport)) { - transportManager - = new IceUdpTransportManager(peer); + transportManager = new IceUdpTransportManager(peer); break; } else if (ProtocolProviderServiceJabberImpl. - URN_XMPP_JINGLE_RAW_UDP_0. - equals(supportedTransports[i])) + URN_XMPP_JINGLE_RAW_UDP_0. + equals(supportedTransport)) { transportManager = new RawUdpTransportManager(peer); @@ -1117,12 +1116,11 @@ public class CallPeerMediaHandlerJabberImpl List visualComponents = new LinkedList(); - for (int i = 0; i < remoteSSRCs.length; i++) + for(int remoteSSRC : remoteSSRCs) { - int remoteSSRC = remoteSSRCs[i]; Component visualComponent - = videoStream.getVisualComponent( - 0xFFFFFFFFL & remoteSSRC); + = videoStream.getVisualComponent( + 0xFFFFFFFFL & remoteSSRC); if (visualComponent != null) visualComponents.add(visualComponent); @@ -1605,7 +1603,7 @@ public class CallPeerMediaHandlerJabberImpl { List fmts = supportedFormats; - if(fmts.size() > 0) + if(!fmts.isEmpty()) { MediaFormat fmt = fmts.get(0); @@ -2108,21 +2106,17 @@ public class CallPeerMediaHandlerJabberImpl * TODO The transportManager is going to be changed so it may need to be * disposed of prior to the change. */ - - if (xmlns.equals( - ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_ICE_UDP_1)) + switch (xmlns) { - transportManager = new IceUdpTransportManager(peer); - } - else if (xmlns.equals( - ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0)) - { - transportManager = new RawUdpTransportManager(peer); - } - else - { - throw new IllegalArgumentException( - "Unsupported Jingle transport " + xmlns); + case ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_ICE_UDP_1: + transportManager = new IceUdpTransportManager(peer); + break; + case ProtocolProviderServiceJabberImpl.URN_XMPP_JINGLE_RAW_UDP_0: + transportManager = new RawUdpTransportManager(peer); + break; + default: + throw new IllegalArgumentException("Unsupported Jingle " + + "transport " + xmlns); } synchronized(transportManagerSyncRoot) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java index 1f4e3d8..d326b96 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java @@ -58,11 +58,21 @@ public class IceUdpTransportManager = Logger.getLogger(IceUdpTransportManager.class); /** + * Default STUN server address. + */ + protected static final String DEFAULT_STUN_SERVER_ADDRESS = "stun.jitsi.net"; + + /** + * Default STUN server port. + */ + protected static final int DEFAULT_STUN_SERVER_PORT = 3478; + + /** * The ICE Component IDs in their common order used, for example, * by DefaultStreamConnector, MediaStreamTarget. */ private static final int[] COMPONENT_IDS - = new int[] { Component.RTP, Component.RTCP }; + = new int[] { Component.RTP, Component.RTCP }; /** * This is where we keep our answer between the time we get the offer and @@ -76,15 +86,6 @@ public class IceUdpTransportManager */ protected final Agent iceAgent; - /** - * Default STUN server address. - */ - protected static final String DEFAULT_STUN_SERVER_ADDRESS = "stun.jitsi.net"; - - /** - * Default STUN server port. - */ - protected static final int DEFAULT_STUN_SERVER_PORT = 3478; /** * Creates a new instance of this transport manager, binding it to the @@ -156,7 +157,10 @@ public class IceUdpTransportManager // in case user has canceled the login window if(credentials == null) + { + logger.info("Credentials were null. User has most likely canceled the login operation"); return null; + } //extract the password the user passed us. char[] pass = credentials.getPassword(); @@ -164,7 +168,10 @@ public class IceUdpTransportManager // the user didn't provide us a password (i.e. canceled the // operation) if(pass == null) + { + logger.info("Password was null. User has most likely canceled the login operation"); return null; + } password = new String(pass); if (credentials.isPasswordPersistent()) @@ -398,13 +405,17 @@ public class IceUdpTransportManager if (selectedPair != null) { DatagramSocket streamConnectorSocket - = selectedPair.getLocalCandidate(). - getDatagramSocket(); + = selectedPair.getDatagramSocket(); if (streamConnectorSocket != null) { streamConnectorSockets[i] = streamConnectorSocket; streamConnectorSocketCount++; + logger.trace("Added a streamConnectorSocket to the array " + + "StreamConnectorSocket and increased " + + "the count of streamConnectorSocketCount by one to " + + streamConnectorSocketCount); + } } } @@ -742,20 +753,25 @@ public class IceUdpTransportManager ex); } - //let's now update the next port var as best we can: we would assume - //that all local candidates are bound on the same port and set it - //to the one just above. if the assumption is wrong the next bind - //would simply include one more bind retry. + // Attempt to minimize subsequent bind retries: see if we have allocated + // any ports from the dynamic range, and if so update the port tracker. + // Do NOT update the port tracker with non-dynamic ports (e.g. 4443 + // coming from TCP) because this will force it to revert back it its + // configured min port. When maxPort is reached, allocation will begin + // from minPort again, so we don't have to worry about wraps. try { - portTracker.setNextPort( - 1 - + stream - .getComponent(Component.RTCP) - .getLocalCandidates() - .get(0) - .getTransportAddress() - .getPort()); + int maxAllocatedPort = getMaxAllocatedPort( + stream, + portTracker.getMinPort(), + portTracker.getMaxPort()); + + if(maxAllocatedPort > 0) + { + int nextPort = 1 + maxAllocatedPort; + portTracker.setNextPort(nextPort); + logger.debug("Updating the port tracker min port: " + nextPort); + } } catch(Throwable t) { @@ -768,6 +784,48 @@ public class IceUdpTransportManager } /** + * @return the highest local port used by any of the local candidates of + * {@code iceStream}, which falls in the range [{@code min}, {@code max}]. + */ + private int getMaxAllocatedPort(IceMediaStream iceStream, int min, int max) + { + return + Math.max( + getMaxAllocatedPort( + iceStream.getComponent(Component.RTP), + min, max), + getMaxAllocatedPort( + iceStream.getComponent(Component.RTCP), + min, max)); + } + + /** + * @return the highest local port used by any of the local candidates of + * {@code component}, which falls in the range [{@code min}, {@code max}]. + */ + private int getMaxAllocatedPort(Component component, int min, int max) + { + int maxAllocatedPort = -1; + + if (component != null) + { + for (LocalCandidate candidate : component.getLocalCandidates()) + { + int candidatePort = candidate.getTransportAddress().getPort(); + + if (min <= candidatePort + && candidatePort <= max + && maxAllocatedPort < candidatePort) + { + maxAllocatedPort = candidatePort; + } + } + } + + return maxAllocatedPort; + } + + /** * Simply returns the list of local candidates that we gathered during the * harvest. * @@ -898,8 +956,12 @@ public class IceUdpTransportManager = transport.getChildExtensionsOfType( CandidatePacketExtension.class); - if (iceAgentStateIsRunning && (candidates.size() == 0)) + if (iceAgentStateIsRunning && candidates.isEmpty()) + { + logger.info("connectivity establishment has not been started " + + "because candidate list is empty"); return false; + } String media = e.getKey(); IceMediaStream stream = iceAgent.getStream(media); diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java index c4193a5..24c5f6f 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java @@ -87,7 +87,7 @@ public class CallPeerMediaHandlerSipImpl * Whether other party is able to change video quality settings. * Normally its whether we have detected existence of imageattr in sdp. */ - boolean supportQualityControls; + private boolean supportQualityControls; /** * The current quality controls for this peer media handler if any. @@ -98,7 +98,7 @@ public class CallPeerMediaHandlerSipImpl * The lock we use to make sure that we won't be processing a second * offer/answer exchange while a . */ - private Object offerAnswerLock = new Object(); + private final Object offerAnswerLock = new Object(); /** * Creates a new handler that will be managing media streams for @@ -164,7 +164,7 @@ public class CallPeerMediaHandlerSipImpl throws OperationFailedException { //Audio Media Description - Vector mediaDescs = createMediaDescriptions(); + List mediaDescs = createMediaDescriptions(); //wrap everything up in a session description String userName @@ -197,7 +197,7 @@ public class CallPeerMediaHandlerSipImpl * for reasons like - problems with device interaction, allocating ports, * etc. */ - private Vector createMediaDescriptions() + private List createMediaDescriptions() throws OperationFailedException { //Audio Media Description @@ -215,12 +215,16 @@ public class CallPeerMediaHandlerSipImpl receiveQualityPreset = qualityControls.getRemoteSendMaxPreset(); } - for (MediaType mediaType : MediaType.values()) + for (MediaType mediaType : new MediaType[] { MediaType.AUDIO , MediaType.VIDEO}) { MediaDevice dev = getDefaultDevice(mediaType); if (!isDeviceActive(dev, sendQualityPreset, receiveQualityPreset)) + { + logger.warn("No active device for " + mediaType.toString() + + " was found!"); continue; + } MediaDirection direction = dev.getDirection().and(getDirectionUserPreference(mediaType)); @@ -339,7 +343,7 @@ public class CallPeerMediaHandlerSipImpl * it is known that the other endpoint supports this * profile" and "[o]ther profiles MAY also be used." */ - updateMediaDescriptionForZrtp(mediaType, md, null); + updateMediaDescriptionForZrtp(mediaType, md); if (SrtpControl.RTP_SAVP.equals(proto) || SrtpControl.RTP_SAVPF.equals(proto)) { @@ -400,7 +404,7 @@ public class CallPeerMediaHandlerSipImpl { //create the media descriptions reflecting our current state. - Vector newMediaDescs = createMediaDescriptions(); + List newMediaDescs = createMediaDescriptions(); SessionDescription newOffer = SdpUtils.createSessionUpdateDescription( sdescToUpdate, getTransportManager().getLastUsedLocalHost(), @@ -510,7 +514,7 @@ public class CallPeerMediaHandlerSipImpl throws OperationFailedException, IllegalArgumentException { - Vector answerDescriptions + List answerDescriptions = createMediaDescriptionsForAnswer(newOffer); // wrap everything up in a session description SessionDescription newAnswer @@ -555,10 +559,11 @@ public class CallPeerMediaHandlerSipImpl boolean rejectedAvpOfferDueToSavpMandatory = false; AccountID accountID = getPeer().getProtocolProvider().getAccountID(); - int savpOption - = accountID.getAccountPropertyBoolean( - ProtocolProviderFactory.DEFAULT_ENCRYPTION, - true) + boolean useDefaultEncryption = + accountID.getAccountPropertyBoolean( + ProtocolProviderFactory.DEFAULT_ENCRYPTION , true); + + int savpOption = useDefaultEncryption ? accountID.getAccountPropertyInt( ProtocolProviderFactory.SAVP_OPTION, ProtocolProviderFactory.SAVP_OFF) @@ -638,7 +643,7 @@ public class CallPeerMediaHandlerSipImpl { mutuallySupportedFormats = null; } - else if(mediaType.equals(MediaType.VIDEO) + else if(MediaType.VIDEO.equals(mediaType) && (qualityControls != null)) { /* @@ -705,18 +710,18 @@ public class CallPeerMediaHandlerSipImpl = getTransportManager().getStreamConnector(mediaType); // check for options from remote party and set them locally - if(mediaType.equals(MediaType.VIDEO)) + if(MediaType.VIDEO.equals(mediaType)) { // update stream MediaStream stream = getStream(MediaType.VIDEO); - if(stream != null && dev != null) + if(stream != null) { List fmts = intersectFormats( getLocallySupportedFormats(dev), remoteFormats); - if(fmts.size() > 0) + if(!fmts.isEmpty()) { MediaFormat fmt = fmts.get(0); @@ -809,7 +814,7 @@ public class CallPeerMediaHandlerSipImpl { if(remoteDescriptions.size() > 1) { - if(mediaType.equals(MediaType.AUDIO)) + if(MediaType.AUDIO.equals(mediaType)) { masterStream = true; masterStreamSet = true; @@ -1192,8 +1197,7 @@ public class CallPeerMediaHandlerSipImpl */ private boolean updateMediaDescriptionForZrtp( MediaType mediaType, - MediaDescription localMd, - MediaDescription remoteMd) + MediaDescription localMd) { MediaAwareCallPeer peer = getPeer(); AccountID accountID = peer.getProtocolProvider().getAccountID(); @@ -1499,7 +1503,7 @@ public class CallPeerMediaHandlerSipImpl // check for options from remote party and set // is quality controls supported - if(mediaType.equals(MediaType.VIDEO)) + if(MediaType.VIDEO.equals(mediaType)) { supportQualityControls = SdpUtils.containsAttribute(mediaDescription, "imageattr"); @@ -1544,7 +1548,7 @@ public class CallPeerMediaHandlerSipImpl { if(remoteDescriptions.size() > 1) { - if(mediaType.equals(MediaType.AUDIO)) + if(MediaType.AUDIO.equals(mediaType)) { masterStream = true; masterStreamSet = true; @@ -1882,7 +1886,7 @@ public class CallPeerMediaHandlerSipImpl // ZRTP else if(srtpControlType == SrtpControlType.ZRTP) { - if(updateMediaDescriptionForZrtp(mediaType, localMd, remoteMd)) + if(updateMediaDescriptionForZrtp(mediaType, localMd)); { // Stop once an encryption advertisement has been chosen. return; diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java index 0471d1a..bae70a2 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java @@ -96,16 +96,9 @@ public class CallSipImpl public static final String EXTRA_HEADER_VALUE = "EXTRA_HEADER_VALUE"; /** - * When starting call we may have quality preferences we must use - * for the call. - */ - private QualityPreset initialQualityPreferences; - - /** - * A reference to the SipMessageFactory instance that we should - * use when creating requests. + * Maximum number of retransmissions that will be sent. */ - private final SipMessageFactory messageFactory; + private static final int MAX_RETRANSMISSIONS = 3; /** * The name of the property under which the user may specify the number of @@ -113,19 +106,27 @@ public class CallSipImpl * 180. */ private static final String RETRANSMITS_RINGING_INTERVAL - = "net.java.sip.communicator.impl.protocol.sip" - + ".RETRANSMITS_RINGING_INTERVAL"; + = "net.java.sip.communicator.impl.protocol.sip" + + ".RETRANSMITS_RINGING_INTERVAL"; /** - * The default amount of time (in milliseconds) for the initial interval for - * retransmissions of response 180. - */ + * The default amount of time (in milliseconds) for the initial interval for + * retransmissions of response 180. + */ private static final int DEFAULT_RETRANSMITS_RINGING_INTERVAL = 500; /** - * Maximum number of retransmissions that will be sent. + * When starting call we may have quality preferences we must use + * for the call. */ - private static final int MAX_RETRANSMISSIONS = 3; + private QualityPreset initialQualityPreferences; + + /** + * A reference to the SipMessageFactory instance that we should + * use when creating requests. + */ + private final SipMessageFactory messageFactory; + /** * The amount of time (in milliseconds) for the initial interval for @@ -405,24 +406,21 @@ public class CallSipImpl logger.trace("Looking for peer with dialog: " + dialog + "among " + getCallPeerCount() + " calls"); } - while (callPeers.hasNext()) + for (CallPeerSipImpl callPeer : getCallPeerList()) { - CallPeerSipImpl cp = callPeers.next(); - - if (cp.getDialog() == dialog) + if (callPeer.getDialog() == dialog) { if (logger.isTraceEnabled()) - logger.trace("Returning cp=" + cp); - return cp; + logger.trace("Returning cp=" + callPeer); + return callPeer; } else { if (logger.isTraceEnabled()) - logger.trace("Ignoring cp=" + cp + " because cp.dialog=" - + cp.getDialog() + " while dialog=" + dialog); + logger.trace("Ignoring cp=" + callPeer + " because cp.dialog=" + + callPeer.getDialog() + " while dialog=" + dialog); } } - return null; } @@ -467,7 +465,7 @@ public class CallSipImpl // Transport preference String forceTransport = null; javax.sip.address.URI calleeURI = calleeAddress.getURI(); - if(calleeURI.getScheme().toLowerCase().equals("sips")) + if("sips".equals(calleeURI.getScheme().toLowerCase())) { // MUST use TLS forceTransport = "TLS"; @@ -571,7 +569,7 @@ public class CallSipImpl String alternativeIMPPAddress = null; if (infoHeader != null && infoHeader.getParameter("purpose") != null - && infoHeader.getParameter("purpose").equals("impp")) + && "impp".equals(infoHeader.getParameter("purpose"))) { alternativeIMPPAddress = infoHeader.getInfo().toString(); } @@ -603,7 +601,7 @@ public class CallSipImpl { if (logger.isTraceEnabled()) logger.trace("will send ringing response: "); - if(peer.getState().equals(CallPeerState.INCOMING_CALL)) + if( CallPeerState.INCOMING_CALL.equals(peer.getState()) ) { response = messageFactory.createResponse(Response.RINGING, invite); @@ -698,10 +696,10 @@ public class CallSipImpl */ public void reInvite() throws OperationFailedException { - Iterator peers = getCallPeers(); - - while (peers.hasNext()) - peers.next().sendReInvite(); + for(CallPeerSipImpl peer : getCallPeerList()) + { + peer.sendReInvite(); + } } /** @@ -792,8 +790,8 @@ public class CallSipImpl { try { - if(!peer.getState().equals( - CallPeerState.INCOMING_CALL)) + if( !CallPeerState.INCOMING_CALL.equals( + peer.getState()) ) { timer.cancel(); } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java index 5ee32c9..fc99643 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java @@ -434,7 +434,10 @@ public class OperationSetBasicTelephonySipImpl CSeqHeader cseq = ((CSeqHeader) response.getHeader(CSeqHeader.NAME)); if (cseq == null) + { logger.error("An incoming response did not contain a CSeq header"); + return false; + } String method = cseq.getMethod(); @@ -1163,11 +1166,7 @@ public class OperationSetBasicTelephonySipImpl protocolProvider.getAccountID().getService() , 399, reasonText); } - catch(InvalidArgumentException e) - { - logger.error("Cannot create warning header", e); - } - catch(ParseException e) + catch(InvalidArgumentException | ParseException e) { logger.error("Cannot create warning header", e); } @@ -1458,11 +1457,7 @@ public class OperationSetBasicTelephonySipImpl { serverTransaction.sendResponse(accepted); } - catch (InvalidArgumentException ex) - { - failure = ex; - } - catch (SipException ex) + catch (InvalidArgumentException | SipException ex) { failure = ex; } diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java index 47c26a9..2339404 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java @@ -568,7 +568,7 @@ public class SdpUtils public static SessionDescription createSessionDescription( InetAddress localAddress, String userName, - Vector mediaDescriptions) + List mediaDescriptions) throws OperationFailedException { SessionDescription sessDescr = null; @@ -614,8 +614,9 @@ public class SdpUtils sessDescr.setConnection(c); if ( mediaDescriptions != null) - sessDescr.setMediaDescriptions(mediaDescriptions); - + { + sessDescr.setMediaDescriptions( new Vector<>(mediaDescriptions)); + } return sessDescr; } catch (SdpException exc) @@ -656,7 +657,7 @@ public class SdpUtils public static SessionDescription createSessionUpdateDescription( SessionDescription descToUpdate, InetAddress newConnectionAddress, - Vector newMediaDescriptions) + List newMediaDescriptions) throws OperationFailedException { SessionDescription update = createSessionDescription( @@ -1712,7 +1713,7 @@ public class SdpUtils * descs Vector. */ private static MediaDescription removeMediaDesc( - Vector descs, + List descs, MediaType type) { for (Iterator i = descs.iterator(); i.hasNext();) diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java index e8d168b..de2d03a 100644 --- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java +++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java @@ -374,7 +374,7 @@ public abstract class CallPeerMediaHandler> if (call == null) return; - for (MediaType mediaType : MediaType.values()) + for (MediaType mediaType : new MediaType[] {MediaType.AUDIO, MediaType.VIDEO} ) { MediaStream stream = getStream(mediaType); @@ -689,7 +689,7 @@ public abstract class CallPeerMediaHandler> return (transportManager == null) - ? null + ? 0 : transportManager.getHarvestingTime(harvesterName); } @@ -942,7 +942,9 @@ public abstract class CallPeerMediaHandler> /** * Returns the number of harvesting for this agent. * - * @return The number of harvesting for this agent. + * @return The number of harvesting for this agent. 0 if this harvester + * does not exists, if the ICE agent is null, or + * if the agent has never harvested with this harvester. */ public int getNbHarvesting() { @@ -950,7 +952,7 @@ public abstract class CallPeerMediaHandler> return (transportManager == null) - ? null + ? 0 : transportManager.getNbHarvesting(); } @@ -961,7 +963,8 @@ public abstract class CallPeerMediaHandler> * @param harvesterName The class name if the harvester. * * @return The number of harvesting time for the harvester given in - * parameter. + * parameter. 0 if this harvester does not exists, if the ICE agent is null, or if the + * agent has never harvested with this harvester. */ public int getNbHarvesting(String harvesterName) { @@ -969,7 +972,7 @@ public abstract class CallPeerMediaHandler> return (transportManager == null) - ? null + ? 0 : transportManager.getNbHarvesting(harvesterName); } @@ -1054,7 +1057,7 @@ public abstract class CallPeerMediaHandler> * Returns the total harvesting time (in ms) for all harvesters. * * @return The total harvesting time (in ms) for all the harvesters. 0 if - * the ICE agent is null, or if the agent has nevers harvested. + * the ICE agent is null, or if the agent has never harvested. */ public long getTotalHarvestingTime() { @@ -1062,7 +1065,7 @@ public abstract class CallPeerMediaHandler> return (transportManager == null) - ? null + ? 0 : transportManager.getTotalHarvestingTime(); } diff --git a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java index 7906199..a8222e0 100644 --- a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java +++ b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java @@ -107,6 +107,76 @@ public abstract class TransportManager> private static final int DEFAULT_HOLE_PUNCH_PKT_COUNT = 3; /** + * Returns the port tracker that we are supposed to use when binding ports + * for the specified {@link MediaType}. + * + * @param mediaType the media type that we want to obtain the port tracker + * for. Use null to obtain the default port tracker. + * + * @return the port tracker that we are supposed to use when binding ports + * for the specified {@link MediaType}. + */ + protected static PortTracker getPortTracker(MediaType mediaType) + { + //make sure our port numbers reflect the configuration service settings + initializePortNumbers(); + + if (mediaType != null) + { + switch (mediaType) + { + case AUDIO: + if (audioPortTracker != null) + return audioPortTracker; + else + break; + case VIDEO: + if (videoPortTracker != null) + return videoPortTracker; + else + break; + case DATA: + if (dataPortTracker != null) + return dataPortTracker; + else + break; + } + } + + return defaultPortTracker; + } + + /** + * Returns the port tracker that we are supposed to use when binding ports + * for the {@link MediaType} indicated by the string param. If we do not + * recognize the string as a valid media type, we simply return the default + * port tracker. + * + * @param mediaTypeStr the name of the media type that we want to obtain a + * port tracker for. + * + * @return the port tracker that we are supposed to use when binding ports + * for the {@link MediaType} with the specified name or the default tracker + * in case the name doesn't ring a bell. + */ + protected static PortTracker getPortTracker(String mediaTypeStr) + { + try + { + return getPortTracker(MediaType.parseString(mediaTypeStr)); + } + catch (Exception e) + { + logger.info( + "Returning default port tracker for unrecognized media type: " + + mediaTypeStr); + + return defaultPortTracker; + } + } + + + /** * The {@link MediaAwareCallPeer} whose traffic we will be taking care of. */ private U callPeer; @@ -461,7 +531,7 @@ public abstract class TransportManager> try { - StreamConnector connector = getStreamConnector(type); + final StreamConnector connector = getStreamConnector(type); if(connector.getProtocol() == StreamConnector.Protocol.TCP) return; @@ -530,7 +600,7 @@ public abstract class TransportManager> "Set traffic class for " + type + " to " + trafficClass); try { - StreamConnector connector = getStreamConnector(type); + final StreamConnector connector = getStreamConnector(type); synchronized(connector) { @@ -630,75 +700,6 @@ public abstract class TransportManager> } /** - * Returns the port tracker that we are supposed to use when binding ports - * for the specified {@link MediaType}. - * - * @param mediaType the media type that we want to obtain the port tracker - * for. Use null to obtain the default port tracker. - * - * @return the port tracker that we are supposed to use when binding ports - * for the specified {@link MediaType}. - */ - protected static PortTracker getPortTracker(MediaType mediaType) - { - //make sure our port numbers reflect the configuration service settings - initializePortNumbers(); - - if (mediaType != null) - { - switch (mediaType) - { - case AUDIO: - if (audioPortTracker != null) - return audioPortTracker; - else - break; - case VIDEO: - if (videoPortTracker != null) - return videoPortTracker; - else - break; - case DATA: - if (dataPortTracker != null) - return dataPortTracker; - else - break; - } - } - - return defaultPortTracker; - } - - /** - * Returns the port tracker that we are supposed to use when binding ports - * for the {@link MediaType} indicated by the string param. If we do not - * recognize the string as a valid media type, we simply return the default - * port tracker. - * - * @param mediaTypeStr the name of the media type that we want to obtain a - * port tracker for. - * - * @return the port tracker that we are supposed to use when binding ports - * for the {@link MediaType} with the specified name or the default tracker - * in case the name doesn't ring a bell. - */ - protected static PortTracker getPortTracker(String mediaTypeStr) - { - try - { - return getPortTracker(MediaType.parseString(mediaTypeStr)); - } - catch (Exception e) - { - logger.info( - "Returning default port tracker for unrecognized media type: " - + mediaTypeStr); - - return defaultPortTracker; - } - } - - /** * Returns the extended type of the candidate selected if this transport * manager is using ICE. * -- cgit v1.1 From 3a7de751eb8dde7a9bd0dbb66d6274d3c0b1f061 Mon Sep 17 00:00:00 2001 From: matteocampana Date: Tue, 5 Jul 2016 23:57:11 +0200 Subject: Add rtpLevelRelayType handling in ColibriBuilder class. (#261) --- .../jabber/extensions/colibri/ColibriBuilder.java | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java index 133b17c..48207c2 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java @@ -126,6 +126,13 @@ public class ColibriBuilder private Integer audioPacketDelay; /** + * Channel 'rtp-level-relay-type' option that will be used with all created + * audio channel. Possible values: mixer or translator (default). + * + */ + private RTPLevelRelayType rtpLevelRelayType; + + /** * Creates new instance of {@link ColibriBuilder} for given * conferenceState. * @@ -232,6 +239,8 @@ public class ColibriBuilder { // When audioPacketDelay is null it will clear the attribute remoteRtpChannelRequest.setPacketDelay(audioPacketDelay); + // Set rtp packet relay type for this channel + remoteRtpChannelRequest.setRTPLevelRelayType(rtpLevelRelayType); } } @@ -1093,4 +1102,28 @@ public class ColibriBuilder */ UNDEFINED; } + + /** + * Configures RTP-level relay (RFC 3550, section 2.3). + * @param rtpLevelRelayType an RTPLevelRelayType value which + * stands for the rtp level relay type that will be set on all created + * audio channels. + */ + public void setRTPLevelRelayType(RTPLevelRelayType rtpLevelRelayType) + { + this.rtpLevelRelayType = rtpLevelRelayType; + } + + /** + * Configures RTP-level relay (RFC 3550, section 2.3). + * @param rtpLevelRelayType a String value which + * stands for the rtp level relay type that will be set on all created + * audio channels. + */ + public void setRTPLevelRelayType(String rtpLevelRelayType) + { + setRTPLevelRelayType + (RTPLevelRelayType.parseRTPLevelRelayType(rtpLevelRelayType)); + } + } -- cgit v1.1 From 7510463c619b5a22da65dabd76d452ab682484a7 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Thu, 7 Jul 2016 17:15:51 +0200 Subject: Add RETRYING status to Jibri --- .../communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index 53c5c3f..0e14d96 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -339,6 +339,12 @@ public class JibriIq PENDING("pending"), /** + * The recorder has failed and the service is retrying on another + * instance. + */ + RETRYING("retrying"), + + /** * An error occurred any point during startup, recording or shutdown. */ FAILED("failed"), -- cgit v1.1 From 0acde285defe895e7917d575b8011e184edc3ac6 Mon Sep 17 00:00:00 2001 From: Joseph Frazier <1212jtraceur@gmail.com> Date: Tue, 12 Jul 2016 17:46:29 -0400 Subject: Add build instructions to CONTRIBUTING.md (#285) This makes it a little faster for new developers to get up and running. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd63c69..0867c79 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,6 +54,7 @@ in the agreement, unfortunately, we cannot accept your contribution. - Please read and follow the [code conventions](https://jitsi.org/Documentation/CodeConvention), especially the limit on 80 characters per line. - Do not reformat existing code. +- Build instructions can be found here: https://jitsi.org/Documentation/RetrievingAndBuildingTheSources ## Creating Pull Requests - Perform **one** logical change per pull request. -- cgit v1.1 From edc4ae59d0936ea7d0ae725d7819199030bcf843 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 12 Jul 2016 23:51:59 +0200 Subject: Add more links to the developer documentation --- CONTRIBUTING.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0867c79..d2e21fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,10 +42,10 @@ Found a bug and know how to fix it? Great! Please read on. ## Contributor License Agreement While Jitsi is released under the -[Apache](https://github.com/jitsi/jitsi/blob/master/LICENSE), the copyright -holder and principal creator is [Blue Jimp](http://www.bluejimp.com/). To -ensure that we can continue making Jitsi available under an open source license -and still pay our bills, we need you to sign our Apache-based contributor +[Apache License](https://github.com/jitsi/jitsi/blob/master/LICENSE), the copyright +holder and principal creator is [Atlassian](https://www.atlassian.com/). To +ensure that we can continue making Jitsi available under an open source license, +we need you to sign our Apache-based contributor license agreement as either a [corporation](https://jitsi.org/ccla) or an [individual](https://jitsi.org/icla). If you cannot accept the terms laid out in the agreement, unfortunately, we cannot accept your contribution. @@ -54,7 +54,9 @@ in the agreement, unfortunately, we cannot accept your contribution. - Please read and follow the [code conventions](https://jitsi.org/Documentation/CodeConvention), especially the limit on 80 characters per line. - Do not reformat existing code. -- Build instructions can be found here: https://jitsi.org/Documentation/RetrievingAndBuildingTheSources +- Command-Line [build instructions](https://jitsi.org/Documentation/RetrievingAndBuildingTheSources) +- How to set up [Eclipse](https://jitsi.org/Documentation/ConfigureEclipseNew) +- Read the [tutorials](https://jitsi.org/Documentation/DeveloperDocumentation) (some of this information might be a bit dated, but it is still a very useful resource) ## Creating Pull Requests - Perform **one** logical change per pull request. -- cgit v1.1 From 05e7b29dad385cf0c7ccef04fffb4e242890f069 Mon Sep 17 00:00:00 2001 From: bgrozev Date: Sat, 16 Jul 2016 06:27:51 -0500 Subject: Updates libjitsi and ice4j. (#283) --- build.xml | 6 +++--- lib/installer-exclude/ice4j-1.0.jar | Bin 471913 -> 0 bytes .../ice4j-1.1-20160706.192041-13.jar | Bin 0 -> 473184 bytes .../libjitsi-1.0-20160707.163121-175.jar | Bin 0 -> 8075571 bytes lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar | Bin 8072237 -> 0 bytes m2/pom.xml | 7 ++++++- 6 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 lib/installer-exclude/ice4j-1.0.jar create mode 100644 lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar delete mode 100644 lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar diff --git a/build.xml b/build.xml index 1be362d..ccdf34e 100644 --- a/build.xml +++ b/build.xml @@ -465,7 +465,7 @@ - + @@ -979,7 +979,7 @@ - + @@ -997,7 +997,7 @@ - + diff --git a/lib/installer-exclude/ice4j-1.0.jar b/lib/installer-exclude/ice4j-1.0.jar deleted file mode 100644 index f899c28..0000000 Binary files a/lib/installer-exclude/ice4j-1.0.jar and /dev/null differ diff --git a/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar b/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar new file mode 100644 index 0000000..5c0a83e Binary files /dev/null and b/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar differ diff --git a/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar b/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar new file mode 100644 index 0000000..bd92f39 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar differ diff --git a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar b/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar deleted file mode 100644 index fc4fff0..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-SNAPSHOT.jar and /dev/null differ diff --git a/m2/pom.xml b/m2/pom.xml index 9d299b4..9d8e3d7 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -52,7 +52,12 @@ ${project.groupId} libjitsi - 1.0-20160411.220648-140 + 1.0-20160707.163121-175 + + + ${project.groupId} + ice4j + 1.1-20160706.192041-13 -- cgit v1.1 From 1e68317fd95bacab8112a71e7e41cc7cfa105325 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 16 Jul 2016 15:00:25 +0200 Subject: Fix classpath after updating ice4j and libjitsi --- .classpath | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.classpath b/.classpath index 1e82588..3b5a7cf 100755 --- a/.classpath +++ b/.classpath @@ -30,7 +30,7 @@ - + @@ -55,7 +55,7 @@ - + -- cgit v1.1 From 236849354a2f334edbb2254a0501a76359309043 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 16 Jul 2016 15:20:17 +0200 Subject: Strip invalid characters when receiving a file Closes #156 --- .../gui/main/chat/filetransfer/ReceiveFileConversationComponent.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/filetransfer/ReceiveFileConversationComponent.java b/src/net/java/sip/communicator/impl/gui/main/chat/filetransfer/ReceiveFileConversationComponent.java index ef72a89..f5a698b 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/filetransfer/ReceiveFileConversationComponent.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/filetransfer/ReceiveFileConversationComponent.java @@ -164,6 +164,10 @@ public class ReceiveFileConversationComponent File downloadDir = null; String incomingFileName = fileTransferRequest.getFileName(); + // strip characters that are invalid on Windows and maybe other + // platforms too + incomingFileName = incomingFileName + .replaceAll("[\\\\/:*?\"<>|]", "_"); try { downloadDir = GuiActivator.getFileAccessService() -- cgit v1.1 From 789022ba3b63f6befecc9bdab4fd9d47038e9743 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 16 Jul 2016 15:52:06 +0200 Subject: Show SHA-256 thumbprint of certificate instead of MD5 Also formats hex-output in a monospaced font and wraps it. Closes #173 --- .../plugin/desktoputil/X509CertificatePanel.java | 66 ++++++++++++++++------ 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java index 9d13fe2..037b177 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java @@ -288,11 +288,11 @@ public class X509CertificatePanel addTitle(sb, R.getI18NString("service.gui.CERT_INFO_FINGERPRINTS")); try { + String sha256String = getThumbprint(certificate, "SHA-256"); String sha1String = getThumbprint(certificate, "SHA1"); - String md5String = getThumbprint(certificate, "MD5"); - addField(sb, "SHA1:", sha1String); - addField(sb, "MD5:", md5String); + addField(sb, "SHA256:", sha256String, 48); + addField(sb, "SHA1:", sha1String, 32); } catch (CertificateException e) { @@ -346,11 +346,12 @@ public class X509CertificatePanel addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN"), R.getI18NString( - "service.gui.CERT_INFO_KEY_BYTES_PRINT", + "service.gui.CERT_INFO_KEY_BITS_PRINT", new String[]{ - String.valueOf(certificate.getSignature().length), - getHex(certificate.getSignature()) + String.valueOf(certificate.getSignature().length*8), })); + addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN"), + getHex(certificate.getSignature()), 48); sb.append("\n"); } @@ -376,12 +377,43 @@ public class X509CertificatePanel */ private void addField(StringBuilder sb, String field, String value) { - sb.append("") - .append("") - .append(field).append("") - .append("").append(value).append("") - .append("\n"); + addField(sb, field, value, 0); + } + + /** + * Add a field. + * @param sb StringBuilder to append to + * @param field name of the certificate field + * @param value to print + * @param wrap force-wrap after number of characters + */ + private void addField(StringBuilder sb, String field, String value, + int wrap) + { + sb.append("") + .append(field).append(" 0) + { + sb.append(" style='font-family:monospace'>"); + for (int i = 0; i < value.length(); i++) + { + if (i % wrap == 0 && i > 0) + { + sb.append("\n"); + } + + sb.append(value.charAt(i)); + } + } + else + { + sb.append(">"); + sb.append(value); + } + + sb.append("\n"); } /** @@ -399,13 +431,13 @@ public class X509CertificatePanel try { for (byte b : raw) - f.format("%02x", b); + f.format("%02X:", b); } finally { f.close(); } - return hex.toString(); + return hex.substring(0, hex.length() - 1); } /** @@ -429,19 +461,21 @@ public class X509CertificatePanel { throw new CertificateException(e); } + byte[] encodedCert = cert.getEncoded(); StringBuilder sb = new StringBuilder(encodedCert.length * 2); Formatter f = new Formatter(sb); try { for (byte b : digest.digest(encodedCert)) - f.format("%02x", b); + f.format("%02X:", b); } finally { f.close(); } - return sb.toString(); + + return sb.substring(0, sb.length() - 1); } /** -- cgit v1.1 From b72cbffa37c082ef83a966fdc19b5efdd8c7fe47 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 16 Jul 2016 17:11:59 +0200 Subject: Remove RTP payload number from Opus (max)ptime attributes Closes #266 --- .../communicator/impl/protocol/sip/sdp/SdpUtils.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java index 2339404..e30b12d 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java @@ -456,8 +456,21 @@ public class SdpUtils while (iter.hasNext()) { Map.Entry ntry = iter.next(); - Attribute adv = sdpFactory.createAttribute(ntry.getKey(), - payloadType + " " + ntry.getValue()); + Attribute adv; + switch (ntry.getKey()) + { + // RFC7587, Sect. 7 says there's no payload number for ptime + case "ptime": + case "maxptime": + adv = sdpFactory.createAttribute(ntry.getKey(), + ntry.getValue()); + break; + default: + adv = sdpFactory.createAttribute(ntry.getKey(), + payloadType + " " + ntry.getValue()); + break; + } + mediaAttributes.add(adv); } -- cgit v1.1 From 724d5f6b3425eec7ff7c423debce36b79c1b21a7 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 25 Jul 2016 22:58:41 +0200 Subject: Update embedded JRE to 8u101 --- resources/install/installers.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/install/installers.properties b/resources/install/installers.properties index 4526b4b..309597e 100644 --- a/resources/install/installers.properties +++ b/resources/install/installers.properties @@ -13,7 +13,7 @@ windows.jre64.file=C:\\Install\\jre-7u17-windows-x64.exe # Paths to the ZIP files of private extracted Windows JRE setups to be deployed # as part of the respective setups of SIP Communicator. -windows.jre.zip=C:\\Install\\jre-8u40-windows-i586.zip -windows.jre64.zip=C:\\Install\\jre-8u40-windows-x64.zip +windows.jre.zip=C:\\Install\\jre-8u101-windows-i586.zip +windows.jre64.zip=C:\\Install\\jre-8u101-windows-x64.zip -macosx.jre=${user.home}/bin/jre1.8.0_40.jre +macosx.jre=${user.home}/bin/jre1.8.0_101.jre -- cgit v1.1 From ab528f8ab1c0cd4ab80684f6fa0f3254ed07dfc2 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 27 Jul 2016 23:33:32 +0200 Subject: Remove workaround for JDK-6483657 JRE8u101 contains a fix for this bug. --- .../impl/certificate/CertificateServiceImpl.java | 47 ---------------------- 1 file changed, 47 deletions(-) diff --git a/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java b/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java index 7bf29d1..9956785 100644 --- a/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java +++ b/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java @@ -211,49 +211,6 @@ public class CertificateServiceImpl System.getProperties().remove("javax.net.ssl.trustStorePassword"); } - /** - * Appends an index number to the alias of each entry in the KeyStore. - * - * The Windows TrustStore might contain multiple entries with the same - * "Friendly Name", which is directly used as the "Alias" for the KeyStore. - * As all operations of the KeyStore operate with these non-unique names, - * PKIX path building could fail and in the end lead to certificate warnings - * for perfectly valid certificates. - * - * @throws Exception when the aliases could not be renamed. - */ - private static int keyStoreAppendIndex(KeyStore ks) throws Exception - { - Field keyStoreSpiField = ks.getClass().getDeclaredField("keyStoreSpi"); - keyStoreSpiField.setAccessible(true); - KeyStoreSpi keyStoreSpi = (KeyStoreSpi) keyStoreSpiField.get(ks); - - if ("sun.security.mscapi.KeyStore$ROOT".equals(keyStoreSpi.getClass() - .getName())) - { - Field entriesField = - keyStoreSpi.getClass().getEnclosingClass() - .getDeclaredField("entries"); - entriesField.setAccessible(true); - Collection entries = - (Collection) entriesField.get(keyStoreSpi); - - int i = 0; - for (Object entry : entries) - { - Field aliasField = entry.getClass().getDeclaredField("alias"); - aliasField.setAccessible(true); - String alias = (String) aliasField.get(entry); - aliasField.set(entry, - alias.concat("_").concat(Integer.toString(i++))); - } - - return i; - } - - return -1; - } - // ------------------------------------------------------------------------ // Client authentication configuration // ------------------------------------------------------------------------ @@ -678,10 +635,6 @@ public class CertificateServiceImpl { ks = KeyStore.getInstance(tsType); ks.load(null, null); - int numEntries = keyStoreAppendIndex(ks); - logger.info( - "Using Windows-ROOT. Aliases sucessfully renamed on " - + numEntries + " root certificates."); } catch (Exception e) { -- cgit v1.1 From 4af4fd5fc253e115849a36a041c6b004d5b1f566 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 27 Jul 2016 23:36:08 +0200 Subject: Reformat certificate panel's signature and modulus fields --- .../plugin/desktoputil/X509CertificatePanel.java | 50 ++++++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java index 037b177..5358030 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/X509CertificatePanel.java @@ -292,7 +292,7 @@ public class X509CertificatePanel String sha1String = getThumbprint(certificate, "SHA1"); addField(sb, "SHA256:", sha256String, 48); - addField(sb, "SHA1:", sha1String, 32); + addField(sb, "SHA1:", sha1String, 72); } catch (CertificateException e) { @@ -319,13 +319,15 @@ public class X509CertificatePanel { RSAPublicKey key = (RSAPublicKey)certificate.getPublicKey(); - addField(sb, R.getI18NString("service.gui.CERT_INFO_PUB_KEY"), - R.getI18NString( - "service.gui.CERT_INFO_KEY_BYTES_PRINT", + addField(sb, + R.getI18NString("service.gui.CERT_INFO_PUB_KEY"), + R.getI18NString("service.gui.CERT_INFO_KEY_BITS_PRINT", new String[]{ - String.valueOf(key.getModulus().toByteArray().length-1), - key.getModulus().toString(16) - })); + String.valueOf( + (key.getModulus().toByteArray().length-1)*8) + }), + getHex(key.getModulus().toByteArray()), + 48); addField(sb, R.getI18NString("service.gui.CERT_INFO_EXP"), key.getPublicExponent().toString()); @@ -349,9 +351,9 @@ public class X509CertificatePanel "service.gui.CERT_INFO_KEY_BITS_PRINT", new String[]{ String.valueOf(certificate.getSignature().length*8), - })); - addField(sb, R.getI18NString("service.gui.CERT_INFO_SIGN"), - getHex(certificate.getSignature()), 48); + }), + getHex(certificate.getSignature()), + 48); sb.append("\n"); } @@ -377,7 +379,7 @@ public class X509CertificatePanel */ private void addField(StringBuilder sb, String field, String value) { - addField(sb, field, value, 0); + addField(sb, field, value, null, 0); } /** @@ -390,9 +392,29 @@ public class X509CertificatePanel private void addField(StringBuilder sb, String field, String value, int wrap) { + addField(sb, field, value, null, wrap); + } + + /** + * Add a field. + * @param sb StringBuilder to append to + * @param field name of the certificate field + * @param value to print (not wrapped) + * @param otherValue second line of value to print (wrapped) + * @param wrap force-wrap after number of characters + */ + private void addField(StringBuilder sb, String field, String value, + String otherValue, int wrap) + { sb.append("") - .append(field).append("').append(value).append("
    0) { @@ -401,7 +423,7 @@ public class X509CertificatePanel { if (i % wrap == 0 && i > 0) { - sb.append("\n"); + sb.append("
    "); } sb.append(value.charAt(i)); @@ -413,7 +435,7 @@ public class X509CertificatePanel sb.append(value); } - sb.append("\n"); + sb.append(""); } /** -- cgit v1.1 From 47d41bd3683ea08a232565ce24d88b6292967386 Mon Sep 17 00:00:00 2001 From: acastroy Date: Wed, 3 Aug 2016 00:42:22 +0000 Subject: Commit from translate.jitsi.org by user acastroy.: 1791 of 1791 strings translated (0 fuzzy). --- resources/languages/resources_es.properties | 60 +++++++++++++++++++---------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/resources/languages/resources_es.properties b/resources/languages/resources_es.properties index 2df833d..3892235 100644 --- a/resources/languages/resources_es.properties +++ b/resources/languages/resources_es.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -25,15 +36,15 @@ # from your system's language, pass the language code to ant: # ant -Duser.language=xx run -service.gui.ABOUT=&Acerca de -service.gui.ACCEPT=&Aceptar +service.gui.ABOUT=Acerca de +service.gui.ACCEPT=Aceptar service.gui.ACCOUNT=Cuenta service.gui.ACCOUNT_ME=Yo service.gui.ACCOUNT_REGISTRATION_WIZARD=Asistente para registrar una cuenta service.gui.ACCOUNTS=Cuentas -service.gui.ADD=&Agregar +service.gui.ADD=Agregar service.gui.ADD_ACCOUNT=Agregar cuenta -service.gui.ADD_CONTACT=&Agregar contacto +service.gui.ADD_CONTACT=Agregar contacto service.gui.ADD_AUTHORIZED_CONTACT=Agregar {0} a su lista de contactos service.gui.ADD_CONTACT_TO_CONTACTLIST=Agregar contacto a su lista de contactos service.gui.ADD_CONTACT_TO=&Agregar contacto a @@ -160,6 +171,8 @@ service.gui.CONNECTION=Conexión service.gui.CONNECTION_FAILED_MSG=Falló la conexión para la cuenta: Usuario: {0}, Servidor: {1}. Por favor, verifique su conexión a la red o contacte con el administrador de red para más información. service.gui.CONNECTION_EXPIRED_MSG=Actualmente está desconectado del servidor {0}. service.gui.CONTACT_NAME=ID o Número +service.gui.CONTACT_NAME_PROMPT=juana.perez@ejemplo.com +service.gui.CONTACT_NAME_INFO=Agregar una dirección de mensajería instantánea (como juana.perez@ejemplo.com) o un número de VoIP service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=El contacto {0} no soporta telefonía. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=El contacto {0} no soporta conferencias. service.gui.CONTACT_PAUSED_TYPING={0} paró de escribir un mensaje @@ -193,6 +206,8 @@ service.gui.DESKTOP_SHARING_WARNING=¿Está seguro de que desea compartir su service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Estás compartiendo su pantalla service.gui.DIALPAD=Teclado numérico service.gui.DISPLAY_NAME=Mostrar nombre +service.gui.DISPLAY_NAME_PROMPT=Juana Pérez +service.gui.DISPLAY_NAME_INFO=Agregar un nombre a este contacto. Si se deja en blanco, la dirección de de mensajería instantánea o el número de VoIP será utilizado en su lugar. (Opcional) service.gui.DISCONNECTED_STATUS=Desconectado service.gui.DND_STATUS=No molestar service.gui.DO_NOT_ASK_AGAIN=No volver a preguntar @@ -492,8 +507,10 @@ service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Presione el botón para mostrar todas las service.gui.SEARCH_STRING_CONTACT_SOURCE=Contacto buscado service.gui.SECURITY=Seguridad service.gui.SELECT_ACCOUNT=Seleccionar cuenta de usuario +service.gui.SELECT_ACCOUNT_INFO=¿Cual cuenta desea utilizar para comunicarse con este contacto? service.gui.SELECT_COLOR=Seleccionar color service.gui.SELECT_GROUP=Seleccione un grupo +service.gui.SELECT_GROUP_INFO=¿Que grupo desea usar para mostrar este contacto? (Opcional) service.gui.SELECT_GROUP_WIZARD_MSG=La lista inferior contiene todos los grupos de su lista de contactos. Seleccione a la que desea agregar el nuevo contacto. service.gui.SELECT_NO_GROUP=Sin grupo service.gui.SELECT_GROUP_WIZARD=Seleccione grupo @@ -853,6 +870,12 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=TeléfonoCasa impl.ldap.PHONE_PREFIX=Prefijo del teléfono impl.ldap.PHONE_PREFIX_EXAMPLE=Ej: 00 +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS=''{0}'' no es una dirección SIP válida. + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS=''{0}'' no es un JID de XMPP válido. + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Libreta de direcciones plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Activar búsqueda en la Libreta de Direcciones de MacOSX @@ -878,6 +901,10 @@ impl.googlecontacts.USERNAME=Nombre de cuenta impl.googlecontacts.PASSWORD=Contraseña impl.googlecontacts.PREFIX=Prefijo del teléfono impl.googlecontacts.WRONG_CREDENTIALS=Credenciales erróneas de la cuenta de Google {0} +impl.googlecontacts.OAUTH_DIALOG_TITLE=Autorización de contactos de Google +impl.googlecontacts.INSTRUCTIONS=

    Presione en el enlace de abajo para aprobar el plugin de contactos para acceder a la cuenta de Google .

    Al presionar en el enlace, se abrirá una página web en su navegador. Inicie sesión con la cuenta solicitada y apruebe el acceso. Una vez aprobado, Google le mostrará un código. Copie este código en el campo de texto de abajo y presione en 'Guardar'.

    Esta es una operación de una sola vez. se almacenarán tokens de autorización para su uso futuro.

    +impl.googlecontacts.CODE=Código: +impl.googlecontacts.HYPERLINK_TEXT=Presione aquí para aprobar el acceso a {0} # account info plugin.accountinfo.TITLE=Información de la cuenta @@ -941,7 +968,7 @@ plugin.branding.LOADING=Cargando plugin.branding.ABOUT_MENU_ENTRY=&Acerca de plugin.branding.WELCOME_MESSAGE=
    {1} se está desarrollando actualmente. La versión que está ejecutando es únicamente experimental y PUEDE QUE NO se comporte como espera. Por favor, consulte a {2} para más información.
    plugin.branding.COPYRIGHT=
    (c) 2003-2013 Copyright jitsi.org. Todos los derechos reservados. Visite https://jitsi.org.
    -plugin.branding.LICENSE=
    The Jitsi se distribuye bajo los términos de la licencia LGPL (http://www.gnu.org).
    +plugin.branding.LICENSE=
    Jitsi es distribuido bajo los terminos la licencia Apache (http://www.apache.org/licenses/LICENSE-2.0).
    plugin.busylampfield.PICKUP=Tomar llamada @@ -971,13 +998,6 @@ plugin.dictaccregwizz.NO_STRATEGIES_FOUND=No hay estrategía en el servidor plugin.dictaccregwizz.POPULATE_LIST=Generando lista plugin.dictaccregwizz.CLOSING_CONNECTION=Cerrando conexión -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Para poder usar los chat de Facebook necesita crear un "Usuario"
    desde la "Configuración de Cuenta" en Facebook.


    Nota: ¡Cuando crea un usuario debe salir de la página
    y esto puede tomar tiempo antes de que pueda iniciar sesión con el nuevo usuario!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protocolo de Chat de Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Usuario: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Usuario y Contraseña - # generalconfig plugin.generalconfig.AUTO_START=Auto - Iniciar {0} cuando arranque o reinicie el sistema plugin.generalconfig.CHATALERTS_ON_MESSAGE=Utilizar alertas en la barra de tareas / dock para llamadas entrantes y charlas @@ -1005,6 +1025,8 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Eliminar símbolos especiales plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Convertir letras a números de teléfono plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=ejemplo. +1-800-MYPHONE -> +1-800-694663 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=Utilizar todos los recursos al detectar características de un contacto plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Tasa de muestreo: plugin.generalconfig.OPUS_BITRATE=Tasa de bits media (kbps) del Encoder: @@ -1018,6 +1040,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Suponer siempre la pérdida plugin.generalconfig.SILK_SAT=Umbral de actividad de voz (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Anunciar soporte a FEC en SDP: plugin.generalconfig.RESTORE=Restaurar opciones predeterminadas +plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimizar la ventana principal en lugar de esconderla # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish @@ -1137,12 +1160,6 @@ plugin.mailbox.CONFIRM=Confirmar plugin.mailbox.DEFAULTS=Predeterminados plugin.mailbox.MAILBOX=Buzón -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protocolo para conectarse y conversar mediante el protocolo MSN. -plugin.msnaccregwizz.USERNAME=Correo: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID y Contraseña - # plugin manager plugin.pluginmanager.INSTALL=Instalar plugin.pluginmanager.UNINSTALL=Desinstalar @@ -1174,6 +1191,7 @@ plugin.sipaccregwizz.PREFERRED_TRANSPORT=Transporte preferido plugin.sipaccregwizz.ADVANCED_OPTIONS=Opciones avanzadas plugin.sipaccregwizz.PROXY_OPTIONS=Opciones del proxy plugin.sipaccregwizz.PROXY_AUTO=Configurar proxy de forma automática +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Ignorar control de seguridad del proxy, seleccione en escenarios de alta disponibilidad (use sólo si es necesario) plugin.sipaccregwizz.ENABLE_PRESENCE=Activar presencia (SIMPLE) plugin.sipaccregwizz.FORCE_P2P_PRESENCE=Forzar envío de presencia mediante peer-to-peer plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=Tiempo de sondeo de contactos desconectados (en s.) @@ -1297,7 +1315,7 @@ plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=El protocolo de servicio Zeroconf (Bonjour). plugin.zeroaccregwizz.FIRST_NAME=Nombre: plugin.zeroaccregwizz.LAST_NAME=Apellidos: -plugin.zeroaccregwizz.EMAIL=Email: +plugin.zeroaccregwizz.EMAIL=Correo: plugin.zeroaccregwizz.REMEMBER_CONTACTS=¿Recordar contactos de Bonjour? plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID y Contraseña plugin.zeroaccregwizz.USERID=User ID -- cgit v1.1 From 41e320d7ec83f34032d45241e892f4d6e44009bd Mon Sep 17 00:00:00 2001 From: paweldomas Date: Tue, 23 Aug 2016 12:45:50 -0500 Subject: Add 'removePresenceExtension' to OperationSetJitsiMeetTools --- .../impl/protocol/jabber/ChatRoomJabberImpl.java | 17 +++++++++++++++++ .../jabber/OperationSetJitsiMeetToolsJabberImpl.java | 10 ++++++++++ .../protocol/sip/OperationSetJitsiMeetToolsSipImpl.java | 10 ++++++++++ .../service/protocol/OperationSetJitsiMeetTools.java | 11 +++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java index 8a6f3ed..e3d4f12 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java @@ -1896,6 +1896,23 @@ public class ChatRoomJabberImpl } /** + * Removes given PacketExtension from the MUC presence and + * publishes it immediately. + * @param extension the PacketExtension to be removed from the MUC + * presence. + */ + public void removePresenceExtension(PacketExtension extension) + { + if (lastPresenceSent != null) + { + setPacketExtension( + lastPresenceSent, null, extension.getNamespace()); + + provider.getConnection().sendPacket(lastPresenceSent); + } + } + + /** * Returns the ids of the users that has the member role in the room. * When the room is member only, this are the users allowed to join. * @return the ids of the users that has the member role in the room. diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetJitsiMeetToolsJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetJitsiMeetToolsJabberImpl.java index 0fb6979..7ea4453 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetJitsiMeetToolsJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetJitsiMeetToolsJabberImpl.java @@ -72,6 +72,16 @@ public class OperationSetJitsiMeetToolsJabberImpl * {@inheritDoc} */ @Override + public void removePresenceExtension(ChatRoom chatRoom, + PacketExtension extension) + { + ((ChatRoomJabberImpl)chatRoom).removePresenceExtension(extension); + } + + /** + * {@inheritDoc} + */ + @Override public void setPresenceStatus(ChatRoom chatRoom, String statusMessage) { ((ChatRoomJabberImpl)chatRoom).publishPresenceStatus(statusMessage); diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetJitsiMeetToolsSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetJitsiMeetToolsSipImpl.java index 77a7fae..4997fc1 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetJitsiMeetToolsSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetJitsiMeetToolsSipImpl.java @@ -142,6 +142,16 @@ public class OperationSetJitsiMeetToolsSipImpl * {@inheritDoc} */ @Override + public void removePresenceExtension(ChatRoom chatRoom, + PacketExtension extension) + { + throw new RuntimeException("Not implemented for SIP"); + } + + /** + * {@inheritDoc} + */ + @Override public void setPresenceStatus(ChatRoom chatRoom, String statusMessage) { throw new RuntimeException("Not implemented for SIP"); diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetJitsiMeetTools.java b/src/net/java/sip/communicator/service/protocol/OperationSetJitsiMeetTools.java index 08c8cff..41af2b4 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetJitsiMeetTools.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetJitsiMeetTools.java @@ -56,6 +56,17 @@ public interface OperationSetJitsiMeetTools PacketExtension extension); /** + * Removes given PacketExtension from the multi user chat presence + * and sends presence update packet to the chat room. + * @param chatRoom the ChatRoom for which the presence will be + * updated. + * @param extension the PacketExtension to be removed from the MUC + * presence. + */ + public void removePresenceExtension(ChatRoom chatRoom, + PacketExtension extension); + + /** * Sets the status message of our MUC presence and sends presence status * update packet to the server. * @param chatRoom the ChatRoom for which the presence status -- cgit v1.1 From e46ed4c89bc891e0280a514d51ccad9072f420df Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 7 Sep 2016 11:57:08 -0500 Subject: Fixes memory leak when unavailable presence does not contain 'caps' extension. --- .../jabber/extensions/caps/EntityCapsManager.java | 77 ++++++++++------------ 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java index 56b066f..c411726 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java @@ -635,12 +635,7 @@ public class EntityCapsManager */ public void addPacketListener(XMPPConnection connection) { - PacketFilter filter - = new AndFilter( - new PacketTypeFilter(Presence.class), - new PacketExtensionFilter( - CapsPacketExtension.ELEMENT_NAME, - CapsPacketExtension.NAMESPACE)); + PacketFilter filter = new PacketTypeFilter(Presence.class); connection.addPacketListener(new CapsPacketListener(), filter); } @@ -941,48 +936,48 @@ public class EntityCapsManager */ public void processPacket(Packet packet) { + // Check it the packet indicates that the user is online. We + // will use this information to decide if we're going to send + // the discover info request. + boolean online + = (packet instanceof Presence) + && ((Presence) packet).isAvailable(); + CapsPacketExtension ext = (CapsPacketExtension) packet.getExtension( CapsPacketExtension.ELEMENT_NAME, CapsPacketExtension.NAMESPACE); - /* - * Before Version 1.4 of XEP-0115: Entity Capabilities, the 'ver' - * attribute was generated differently and the 'hash' attribute was - * absent. The 'ver' attribute in Version 1.3 represents the - * specific version of the client and thus does not provide a way to - * validate the DiscoverInfo sent by the client. If - * EntityCapsManager receives no 'hash' attribute, it will assume - * the legacy format and will not cache it because the DiscoverInfo - * to be received from the client later on will not be trustworthy. - */ - String hash = ext.getHash(); - - /* Google Talk web does not set hash but we need it to be cached */ - if(hash == null) - hash = ""; - - if (hash != null) + if(ext != null && online) { - // Check it the packet indicates that the user is online. We - // will use this information to decide if we're going to send - // the discover info request. - boolean online - = (packet instanceof Presence) - && ((Presence) packet).isAvailable(); - - if(online) - { - addUserCapsNode( - packet.getFrom(), - ext.getNode(), hash, ext.getVersion(), - ext.getExtensions(), online); - } - else - { - removeUserCapsNode(packet.getFrom()); - } + /* + * Before Version 1.4 of XEP-0115: Entity Capabilities, + * the 'ver' attribute was generated differently and the 'hash' + * attribute was absent. The 'ver' attribute in Version 1.3 + * represents the specific version of the client and thus does + * not provide a way to validate the DiscoverInfo sent by + * the client. If EntityCapsManager receives no 'hash' + * attribute, it will assume the legacy format and will not + * cache it because the DiscoverInfo to be received from + * the client later on will not be trustworthy. + */ + String hash = ext.getHash(); + + /* Google Talk web does not set hash, but we need it to + * be cached + */ + if (hash == null) + hash = ""; + + addUserCapsNode( + packet.getFrom(), + ext.getNode(), hash, ext.getVersion(), + ext.getExtensions(), online); + } + else if (!online) + { + removeUserCapsNode(packet.getFrom()); } } } -- cgit v1.1 From 94db8054a6f7de9d7af5dcc7a51273926e5427f9 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 5 Oct 2016 13:03:18 -0500 Subject: Escape to XML text fields in the JibriIq --- .../communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java index 0e14d96..8b964af 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java @@ -198,8 +198,11 @@ public class JibriIq StringBuilder xml, String attrName, String attr) { if (!StringUtils.isNullOrEmpty(attr)) + { + attr = org.jivesoftware.smack.util.StringUtils.escapeForXML(attr); xml.append(attrName).append("='") .append(attr).append("' "); + } } /** -- cgit v1.1 From 2cca1f070ccfda479a43d82a2a24ac656f8ad396 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 24 Oct 2016 22:39:39 +0200 Subject: Remove Yahoo protocol Closes #76, #293 --- README.md | 2 +- build.xml | 38 +- lib/accounts.properties.template | 41 - lib/felix.client.run.properties | 2 - lib/felix.unit.test.properties | 2 - lib/installer-exclude/ymsg_network_v0_67.jar | Bin 142376 -> 0 bytes lib/jitsi-defaults.properties | 2 - lib/testing.properties | 4 - m2/jitsi-protocol/pom.xml | 2 - resources/images/images.properties | 36 +- .../images/protocol/dict/dict-16x16-offline.png | Bin 687 -> 0 bytes resources/images/protocol/dict/dict-16x16.png | Bin 739 -> 0 bytes resources/images/protocol/dict/dict-32x32.png | Bin 1663 -> 0 bytes resources/images/protocol/dict/dict-48x48.png | Bin 3071 -> 0 bytes resources/images/protocol/dict/dict-64x64.png | Bin 4367 -> 0 bytes resources/images/protocol/ssh/ssh-connected.png | Bin 1703 -> 0 bytes resources/images/protocol/ssh/ssh-connecting.png | Bin 1657 -> 0 bytes resources/images/protocol/ssh/ssh-filetransfer.png | Bin 1725 -> 0 bytes resources/images/protocol/ssh/ssh-na.png | Bin 1719 -> 0 bytes resources/images/protocol/ssh/ssh-offline.png | Bin 1309 -> 0 bytes resources/images/protocol/ssh/ssh-online.png | Bin 1391 -> 0 bytes resources/images/protocol/ssh/ssh32x32.png | Bin 1730 -> 0 bytes resources/images/protocol/ssh/ssh48x48.png | Bin 3126 -> 0 bytes resources/images/protocol/ssh/ssh64x64.png | Bin 4327 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-away.png | Bin 728 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-busy.png | Bin 721 -> 0 bytes .../protocol/yahoo/yahoo16x16-connecting.gif | Bin 6152 -> 0 bytes .../protocol/yahoo/yahoo16x16-connecting.png | Bin 639 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-idle.png | Bin 681 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-invisible.png | Bin 742 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-lunch.png | Bin 683 -> 0 bytes resources/images/protocol/yahoo/yahoo16x16-na.png | Bin 697 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-offline.png | Bin 459 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-online.png | Bin 495 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-phone.png | Bin 766 -> 0 bytes .../images/protocol/yahoo/yahoo16x16-vacation.png | Bin 699 -> 0 bytes resources/images/protocol/yahoo/yahoo16x16.png | Bin 495 -> 0 bytes resources/images/protocol/yahoo/yahoo32x32.png | Bin 946 -> 0 bytes resources/images/protocol/yahoo/yahoo48x48.png | Bin 1338 -> 0 bytes resources/images/protocol/yahoo/yahoo64x64.png | Bin 1758 -> 0 bytes .../images/protocol/zeroconf/zeroconf-away.png | Bin 1962 -> 0 bytes .../images/protocol/zeroconf/zeroconf-dnd.png | Bin 1933 -> 0 bytes .../protocol/zeroconf/zeroconf-invisible.png | Bin 1967 -> 0 bytes .../images/protocol/zeroconf/zeroconf-offline.png | Bin 1673 -> 0 bytes .../images/protocol/zeroconf/zeroconf-online.png | Bin 1648 -> 0 bytes .../images/protocol/zeroconf/zeroconf16x16.png | Bin 1648 -> 0 bytes .../images/protocol/zeroconf/zeroconf32x32.png | Bin 1868 -> 0 bytes .../images/protocol/zeroconf/zeroconf48x48.png | Bin 3524 -> 0 bytes .../images/protocol/zeroconf/zeroconf64x64.png | Bin 4985 -> 0 bytes resources/install/debian/README.embedded-libraries | 6 - resources/install/debian/control-src.tmpl | 2 +- resources/install/debian/control.tmpl | 2 +- resources/install/debian/jitsi.1.tmpl | 2 +- resources/install/rpm/SPECS/jitsi.spec | 8 +- resources/languages/resources.properties | 8 - .../googlecontacts/GoogleContactsEntryImpl.java | 18 +- .../impl/googlecontacts/GoogleContactsQuery.java | 13 +- .../contactlist/contactsource/SourceUIContact.java | 2 - .../impl/protocol/icq/icq.provider.manifest.mf | 1 - .../yahoo/AbstractContactGroupYahooImpl.java | 40 - .../yahoo/AdHocChatRoomInvitationYahooImpl.java | 90 -- .../protocol/yahoo/AdHocChatRoomYahooImpl.java | 581 --------- .../impl/protocol/yahoo/ContactGroupYahooImpl.java | 445 ------- .../impl/protocol/yahoo/ContactYahooImpl.java | 397 ------ .../impl/protocol/yahoo/FileTransferImpl.java | 117 -- .../IncomingFileTransferRequestYahooImpl.java | 190 --- .../impl/protocol/yahoo/MessageYahooImpl.java | 48 - .../OperationSetAdHocMultiUserChatYahooImpl.java | 714 ----------- ...OperationSetBasicInstantMessagingYahooImpl.java | 649 ---------- .../yahoo/OperationSetFileTransferYahooImpl.java | 466 ------- .../OperationSetPersistentPresenceYahooImpl.java | 954 --------------- .../OperationSetTypingNotificationsYahooImpl.java | 153 --- .../impl/protocol/yahoo/ProtocolIconYahooImpl.java | 173 --- .../yahoo/ProtocolProviderFactoryYahooImpl.java | 172 --- .../yahoo/ProtocolProviderServiceYahooImpl.java | 574 --------- .../protocol/yahoo/RootContactGroupYahooImpl.java | 280 ----- .../yahoo/ServerStoredContactListYahooImpl.java | 1278 -------------------- .../yahoo/VolatileContactGroupYahooImpl.java | 97 -- .../impl/protocol/yahoo/YahooAccountID.java | 42 - .../impl/protocol/yahoo/YahooActivator.java | 145 --- .../impl/protocol/yahoo/YahooSession.java | 76 -- .../impl/protocol/yahoo/yahoo.provider.manifest.mf | 22 - .../macosx/MacOSXAddrBookContactQuery.java | 10 +- .../plugin/aimaccregwizz/aimaccregwizz.manifest.mf | 1 - .../GlobalProxyPluginActivator.java | 10 +- .../plugin/msofficecomm/Messenger.java | 6 - .../plugin/msofficecomm/msofficecomm.manifest.mf | 1 - .../plugin/yahooaccregwizz/FirstWizardPage.java | 299 ----- .../plugin/yahooaccregwizz/Resources.java | 73 -- .../yahooaccregwizz/YahooAccRegWizzActivator.java | 160 --- .../yahooaccregwizz/YahooAccountRegistration.java | 83 -- .../YahooAccountRegistrationWizard.java | 379 ------ .../yahooaccregwizz/yahooaccregwizz.manifest.mf | 33 - .../service/contactsource/ContactDetail.java | 4 +- .../googlecontacts/GoogleContactsEntry.java | 15 +- .../service/protocol/AdHocChatRoom.java | 3 +- .../service/protocol/ProtocolNames.java | 30 - .../service/protocol/protocol.provider.manifest.mf | 4 +- .../protocol/yahooconstants/YahooStatusEnum.java | 200 --- .../TestOperationSetAdHocMultiUserChat.java | 7 +- .../generic/TestOperationSetFileTransfer.java | 3 +- .../protocol/icq/icq.provider.slick.manifest.mf | 1 - .../protocol/yahoo/TestAccountInstallation.java | 233 ---- .../protocol/yahoo/TestAccountUninstallation.java | 287 ----- .../TestAccountUninstallationPersistence.java | 113 -- ...estOperationSetAdHocMultiUserChatYahooImpl.java | 182 --- .../TestOperationSetBasicInstantMessaging.java | 537 -------- .../yahoo/TestOperationSetFileTransferImpl.java | 253 ---- .../yahoo/TestOperationSetPersistentPresence.java | 582 --------- .../protocol/yahoo/TestOperationSetPresence.java | 1003 --------------- .../yahoo/TestOperationSetTypingNotifications.java | 318 ----- .../TestProtocolProviderServiceYahooImpl.java | 262 ---- .../yahoo/YahooProtocolProviderServiceLick.java | 129 -- .../slick/protocol/yahoo/YahooSlickFixture.java | 144 --- .../yahoo/yahoo.provider.slick.manifest.mf | 17 - 115 files changed, 32 insertions(+), 13244 deletions(-) delete mode 100644 lib/installer-exclude/ymsg_network_v0_67.jar delete mode 100755 resources/images/protocol/dict/dict-16x16-offline.png delete mode 100644 resources/images/protocol/dict/dict-16x16.png delete mode 100644 resources/images/protocol/dict/dict-32x32.png delete mode 100644 resources/images/protocol/dict/dict-48x48.png delete mode 100644 resources/images/protocol/dict/dict-64x64.png delete mode 100644 resources/images/protocol/ssh/ssh-connected.png delete mode 100644 resources/images/protocol/ssh/ssh-connecting.png delete mode 100644 resources/images/protocol/ssh/ssh-filetransfer.png delete mode 100644 resources/images/protocol/ssh/ssh-na.png delete mode 100644 resources/images/protocol/ssh/ssh-offline.png delete mode 100644 resources/images/protocol/ssh/ssh-online.png delete mode 100644 resources/images/protocol/ssh/ssh32x32.png delete mode 100644 resources/images/protocol/ssh/ssh48x48.png delete mode 100644 resources/images/protocol/ssh/ssh64x64.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-away.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-busy.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-connecting.gif delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-connecting.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-idle.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-invisible.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-lunch.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-na.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-offline.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-online.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-phone.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16-vacation.png delete mode 100644 resources/images/protocol/yahoo/yahoo16x16.png delete mode 100644 resources/images/protocol/yahoo/yahoo32x32.png delete mode 100644 resources/images/protocol/yahoo/yahoo48x48.png delete mode 100644 resources/images/protocol/yahoo/yahoo64x64.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf-away.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf-dnd.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf-invisible.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf-offline.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf-online.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf16x16.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf32x32.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf48x48.png delete mode 100644 resources/images/protocol/zeroconf/zeroconf64x64.png delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/AbstractContactGroupYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomInvitationYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ContactGroupYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ContactYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/FileTransferImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/IncomingFileTransferRequestYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/MessageYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetAdHocMultiUserChatYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetFileTransferYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetPersistentPresenceYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetTypingNotificationsYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolIconYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderFactoryYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/RootContactGroupYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/VolatileContactGroupYahooImpl.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/YahooAccountID.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/YahooActivator.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/YahooSession.java delete mode 100644 src/net/java/sip/communicator/impl/protocol/yahoo/yahoo.provider.manifest.mf delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/FirstWizardPage.java delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/Resources.java delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistration.java delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/yahooaccregwizz/yahooaccregwizz.manifest.mf delete mode 100644 src/net/java/sip/communicator/service/protocol/yahooconstants/YahooStatusEnum.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountInstallation.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallation.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallationPersistence.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetAdHocMultiUserChatYahooImpl.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetBasicInstantMessaging.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetFileTransferImpl.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPersistentPresence.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPresence.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetTypingNotifications.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/TestProtocolProviderServiceYahooImpl.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/YahooProtocolProviderServiceLick.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/YahooSlickFixture.java delete mode 100644 test/net/java/sip/communicator/slick/protocol/yahoo/yahoo.provider.slick.manifest.mf diff --git a/README.md b/README.md index 1e16f85..c356062 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Jitsi ===== -Jitsi is a free open-source audio/video and chat communicator that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC, Yahoo! and many other useful features. +Jitsi is a free open-source audio/video and chat communicator that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC and many other useful features. Helpful Resources ----------------- diff --git a/build.xml b/build.xml index ccdf34e..47745ef 100644 --- a/build.xml +++ b/build.xml @@ -930,11 +930,10 @@ bundle-jabber,bundle-jabber-slick,bundle-swing-ui,bundle-ui-service, bundle-phonenumbers, bundle-irc,bundle-irc-commands,bundle-plugin-ircaccregwizz, - bundle-yahoo,bundle-yahoo-slick, bundle-contactlist,meta-contactlist,meta-contactlist-slick, bundle-plugin-icqaccregwizz,bundle-plugin-jabberaccregwizz, bundle-plugin-sipaccregwizz, - bundle-plugin-yahooaccregwizz,bundle-plugin-aimaccregwizz, + bundle-plugin-aimaccregwizz, bundle-httputil,bundle-plugin-spellcheck, bundle-version-impl,bundle-shutdown-timeout,bundle-windows-clean-shutdown, bundle-growlnotification,bundle-swingnotification,bundle-galagonotification, @@ -1425,7 +1424,6 @@ javax.swing.event, javax.swing.border"/> - @@ -1536,30 +1534,6 @@ javax.swing.event, javax.swing.border"/>
    - - - - - - - - - - - - - - - - - - - @@ -1676,16 +1650,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - diff --git a/lib/accounts.properties.template b/lib/accounts.properties.template index 3845c47..3b6b540 100644 --- a/lib/accounts.properties.template +++ b/lib/accounts.properties.template @@ -189,47 +189,6 @@ accounts.jabber.CONTACT_LIST= # list of icq accounts to notify during testing (optional) accounts.reporting.JABBER_REPORT_LIST= -# YAHOO PROPERTIES - -# YAHOO ACCOUNT 1 -# The username needed to log onto the server -accounts.yahoo.account1.USER_ID= - -# The password (in plain text) needed to log the user specified in USER_ID -# on the server -accounts.yahoo.account1.PASSWORD= - -# YAHOO ACCOUNT 2 - -# The username needed to log onto the server -accounts.yahoo.account2.USER_ID= - -# The password (in plain text) needed to log the user specified in USER_ID -# on the server -accounts.yahoo.account2.PASSWORD= - -# YAHOO ACCOUNT 3 - -# The username needed to log onto the server -accounts.yahoo.account3.USER_ID= - -# The password (in plain text) needed to log the user specified in USER_ID -# on the server -accounts.yahoo.account3.PASSWORD= - -# The following describes the contact list that we will store on the yahoo -# server for the tested account implementation. The value of the CONTACT_LIST -# property must be a space separated string containing elements each of which -# is in the format: GroupName.UIN - - -# VERY IMPORTANT!!! All other users in this contact list will be removed and -# the contacts and contact groups enumerated beneath will be added instead -accounts.yahoo.CONTACT_LIST= - -# list of yahoo accounts to notify during testing (optional) -accounts.reporting.YAHOO_REPORT_LIST= - # GIBBERISH Account 1 # The username to create the first Gibberish account with. accounts.gibberish.account1.USER_ID=gibacc1 diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index 59951c3..ad9a08a 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -152,7 +152,6 @@ felix.auto.start.52= \ reference:file:sc-bundles/protocol-sip.jar \ reference:file:sc-bundles/smacklib.jar \ reference:file:sc-bundles/protocol-jabber.jar \ - reference:file:sc-bundles/protocol-yahoo.jar \ reference:file:sc-bundles/protocol-irc.jar \ reference:file:sc-bundles/reconnectplugin.jar @@ -193,7 +192,6 @@ felix.auto.start.67= \ reference:file:sc-bundles/sipaccregwizz.jar \ reference:file:sc-bundles/jabberaccregwizz.jar \ reference:file:sc-bundles/googletalkaccregwizz.jar \ - reference:file:sc-bundles/yahooaccregwizz.jar \ reference:file:sc-bundles/ircaccregwizz.jar \ reference:file:sc-bundles/contacteventhandler.jar \ reference:file:sc-bundles/notificationconfig.jar \ diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index 8c7cfa4..e8df121 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -141,7 +141,6 @@ felix.auto.start.60= \ reference:file:sc-bundles/neomedia.jar \ reference:file:sc-bundles/protocol-jabber.jar \ reference:file:sc-bundles/protocol-sip.jar \ - reference:file:sc-bundles/protocol-yahoo.jar \ reference:file:sc-bundles/protocol-mock.jar \ reference:file:sc-bundles/meta-cl.jar \ reference:file:sc-bundles/msghistory.jar \ @@ -165,7 +164,6 @@ felix.auto.start.70= \ reference:file:sc-bundles/meta-cl-slick.jar \ reference:file:sc-bundles/protocol-sip-slick.jar \ reference:file:sc-bundles/protocol-jabber-slick.jar \ - reference:file:sc-bundles/protocol-yahoo-slick.jar \ reference:file:sc-bundles/protocol-icq-slick.jar \ reference:file:sc-bundles/msghistory-slick.jar \ reference:file:sc-bundles/metahistory-slick.jar \ diff --git a/lib/installer-exclude/ymsg_network_v0_67.jar b/lib/installer-exclude/ymsg_network_v0_67.jar deleted file mode 100644 index 998358a..0000000 Binary files a/lib/installer-exclude/ymsg_network_v0_67.jar and /dev/null differ diff --git a/lib/jitsi-defaults.properties b/lib/jitsi-defaults.properties index a132d7e..ff21e05 100644 --- a/lib/jitsi-defaults.properties +++ b/lib/jitsi-defaults.properties @@ -151,8 +151,6 @@ net.java.sip.communicator.plugin.pluginmanager.SYSTEM_BUNDLES=\ net.java.sip.communicator.version,\ net.java.sip.communicator.replacement.viddler,\ net.java.sip.communicator.replacement.vimeo,\ - net.java.sip.communicator.protocol.yahoo,\ - net.java.sip.communicator.plugin.yahooaccregwizz,\ net.java.sip.communicator.replacement.youtube,\ net.java.sip.communicator.libjitsi,\ net.java.sip.communicator.provdisc.mdns,\ diff --git a/lib/testing.properties b/lib/testing.properties index 850a47c..7b5c1b8 100644 --- a/lib/testing.properties +++ b/lib/testing.properties @@ -35,10 +35,6 @@ net.java.sip.communicator.slick.runner.TEST_LIST=ConfigurationServiceLick \ # GenericProtocolProviderServiceLick because it does not add any tests. # # IcqProtocolProviderSlick because 2 of its 25 tests fail. -# -# Temporally disabling failing test -# MsnProtocolProviderSlick -# YahooProtocolProviderSlick # define all the test classes that can be run standalone, or by the diff --git a/m2/jitsi-protocol/pom.xml b/m2/jitsi-protocol/pom.xml index d61a018..d97e083 100644 --- a/m2/jitsi-protocol/pom.xml +++ b/m2/jitsi-protocol/pom.xml @@ -64,7 +64,6 @@ resources/images/protocol/googletalk/** resources/images/protocol/icq/** resources/images/protocol/jabber/** - resources/images/protocol/yahoo/** @@ -79,7 +78,6 @@ resources/images/protocol/googletalk/** resources/images/protocol/icq/** resources/images/protocol/jabber/** - resources/images/protocol/yahoo/** diff --git a/resources/images/images.properties b/resources/images/images.properties index 736cb54..643e9ca 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -411,13 +411,6 @@ service.systray.STATUS_MENU_ICON=resources/images/impl/systray/statusIcon.png service.systray.QUIT_MENU_ICON=resources/images/impl/gui/common/quit16x16.png service.systray.CONFIGURE_ICON=resources/images/impl/gui/common/configureIcon.png -# dict protocol icons -service.protocol.dict.DICT_16x16=resources/images/protocol/dict/dict-16x16.png -service.protocol.dict.DICT_32x32=resources/images/protocol/dict/dict-32x32.png -service.protocol.dict.DICT_48x48=resources/images/protocol/dict/dict-48x48.png -service.protocol.dict.DICT_64x64=resources/images/protocol/dict/dict-64x64.png -service.protocol.dict.OFFLINE_STATUS_ICON=resources/images/protocol/dict/dict-16x16-offline.png - # icq protocol icons service.protocol.icq.ICQ_16x16=resources/images/protocol/icq/icq16x16-online.png service.protocol.icq.ICQ_32x32=resources/images/protocol/icq/icq32x32.png @@ -425,33 +418,6 @@ service.protocol.icq.ICQ_48x48=resources/images/protocol/icq/icq48x48.png service.protocol.icq.ICQ_64x64=resources/images/protocol/icq/icq64x64.png service.protocol.icq.CONNECTING=resources/images/protocol/icq/cr16-action-icq_connecting-1.gif -# yahoo protocol icons -service.protocol.yahoo.YAHOO_16x16=resources/images/protocol/yahoo/yahoo16x16.png -service.protocol.yahoo.YAHOO_32x32=resources/images/protocol/yahoo/yahoo32x32.png -service.protocol.yahoo.YAHOO_48x48=resources/images/protocol/yahoo/yahoo48x48.png -service.protocol.yahoo.YAHOO_64x64=resources/images/protocol/yahoo/yahoo64x64.png - -# zeroconf protocol icons -service.protocol.zeroconf.ZEROCONF_16x16=resources/images/protocol/zeroconf/zeroconf16x16.png -service.protocol.zeroconf.ZEROCONF_32x32=resources/images/protocol/zeroconf/zeroconf32x32.png -service.protocol.zeroconf.ZEROCONF_48x48=resources/images/protocol/zeroconf/zeroconf48x48.png -service.protocol.zeroconf.ZEROCONF_64x64=resources/images/protocol/zeroconf/zeroconf64x64.png -service.protocol.zeroconf.ONLINE_STATUS_ICON=resources/images/protocol/zeroconf/zeroconf-online.png -service.protocol.zeroconf.OFFLINE_STATUS_ICON=resources/images/protocol/zeroconf/zeroconf-offline.png -service.protocol.zeroconf.DND_STATUS_ICON=resources/images/protocol/zeroconf/zeroconf-dnd.png -service.protocol.zeroconf.INVISIBLE_STATUS_ICON=resources/images/protocol/zeroconf/zeroconf-invisible.png - -# ssh protocol icons -service.protocol.ssh.SSH_16x16=resources/images/protocol/ssh/ssh-online.png -service.protocol.ssh.SSH_32x32=resources/images/protocol/ssh/ssh32x32.png -service.protocol.ssh.SSH_48x48=resources/images/protocol/ssh/ssh48x48.png -service.protocol.ssh.SSH_64x64=resources/images/protocol/ssh/ssh64x64.png -service.protocol.ssh.OFFLINE_STATUS_ICON=resources/images/protocol/ssh/ssh-offline.png -service.protocol.ssh.NA_STATUS_ICON=resources/images/protocol/ssh/ssh-na.png -service.protocol.ssh.CONNECTING_ICON=resources/images/protocol/ssh/ssh-connecting.png -service.protocol.ssh.CONNECTED_ICON=resources/images/protocol/ssh/ssh-connected.png -service.protocol.ssh.FILE_TRANSFER_ICON=resources/images/protocol/ssh/ssh-filetransfer.png - # sip protocol icons service.protocol.sip.SIP_16x16=resources/images/protocol/sip/sip16x16.png service.protocol.sip.SIP_64x64=resources/images/protocol/sip/sip64x64.png @@ -617,4 +583,4 @@ plugin.spellcheck.PERSONAL_DIR=resources/images/plugin/spellcheck/personalDictio plugin.spellcheck.WORD_INCLUDE=resources/images/plugin/spellcheck/wordInclude.png plugin.spellcheck.WORD_EXCLUDE=resources/images/plugin/spellcheck/wordExclude.png plugin.spellcheck.ENABLE=resources/images/plugin/spellcheck/enableSpellchecker.png -plugin.spellcheck.DISABLE=resources/images/plugin/spellcheck/disableSpellchecker.png \ No newline at end of file +plugin.spellcheck.DISABLE=resources/images/plugin/spellcheck/disableSpellchecker.png diff --git a/resources/images/protocol/dict/dict-16x16-offline.png b/resources/images/protocol/dict/dict-16x16-offline.png deleted file mode 100755 index f450b04..0000000 Binary files a/resources/images/protocol/dict/dict-16x16-offline.png and /dev/null differ diff --git a/resources/images/protocol/dict/dict-16x16.png b/resources/images/protocol/dict/dict-16x16.png deleted file mode 100644 index 0c79371..0000000 Binary files a/resources/images/protocol/dict/dict-16x16.png and /dev/null differ diff --git a/resources/images/protocol/dict/dict-32x32.png b/resources/images/protocol/dict/dict-32x32.png deleted file mode 100644 index 8009db2..0000000 Binary files a/resources/images/protocol/dict/dict-32x32.png and /dev/null differ diff --git a/resources/images/protocol/dict/dict-48x48.png b/resources/images/protocol/dict/dict-48x48.png deleted file mode 100644 index 1a33a27..0000000 Binary files a/resources/images/protocol/dict/dict-48x48.png and /dev/null differ diff --git a/resources/images/protocol/dict/dict-64x64.png b/resources/images/protocol/dict/dict-64x64.png deleted file mode 100644 index 8230e15..0000000 Binary files a/resources/images/protocol/dict/dict-64x64.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-connected.png b/resources/images/protocol/ssh/ssh-connected.png deleted file mode 100644 index ac168e0..0000000 Binary files a/resources/images/protocol/ssh/ssh-connected.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-connecting.png b/resources/images/protocol/ssh/ssh-connecting.png deleted file mode 100644 index 5ae7f03..0000000 Binary files a/resources/images/protocol/ssh/ssh-connecting.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-filetransfer.png b/resources/images/protocol/ssh/ssh-filetransfer.png deleted file mode 100644 index 50eca81..0000000 Binary files a/resources/images/protocol/ssh/ssh-filetransfer.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-na.png b/resources/images/protocol/ssh/ssh-na.png deleted file mode 100644 index 90e5028..0000000 Binary files a/resources/images/protocol/ssh/ssh-na.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-offline.png b/resources/images/protocol/ssh/ssh-offline.png deleted file mode 100644 index c8c429a..0000000 Binary files a/resources/images/protocol/ssh/ssh-offline.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh-online.png b/resources/images/protocol/ssh/ssh-online.png deleted file mode 100644 index e67f418..0000000 Binary files a/resources/images/protocol/ssh/ssh-online.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh32x32.png b/resources/images/protocol/ssh/ssh32x32.png deleted file mode 100644 index c873cb5..0000000 Binary files a/resources/images/protocol/ssh/ssh32x32.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh48x48.png b/resources/images/protocol/ssh/ssh48x48.png deleted file mode 100644 index a53f740..0000000 Binary files a/resources/images/protocol/ssh/ssh48x48.png and /dev/null differ diff --git a/resources/images/protocol/ssh/ssh64x64.png b/resources/images/protocol/ssh/ssh64x64.png deleted file mode 100644 index 2a62b39..0000000 Binary files a/resources/images/protocol/ssh/ssh64x64.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-away.png b/resources/images/protocol/yahoo/yahoo16x16-away.png deleted file mode 100644 index fc853f0..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-away.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-busy.png b/resources/images/protocol/yahoo/yahoo16x16-busy.png deleted file mode 100644 index 4f30abc..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-busy.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-connecting.gif b/resources/images/protocol/yahoo/yahoo16x16-connecting.gif deleted file mode 100644 index 4f07cb7..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-connecting.gif and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-connecting.png b/resources/images/protocol/yahoo/yahoo16x16-connecting.png deleted file mode 100644 index 189c45e..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-connecting.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-idle.png b/resources/images/protocol/yahoo/yahoo16x16-idle.png deleted file mode 100644 index 2c81b77..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-idle.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-invisible.png b/resources/images/protocol/yahoo/yahoo16x16-invisible.png deleted file mode 100644 index 8c8bc0c..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-invisible.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-lunch.png b/resources/images/protocol/yahoo/yahoo16x16-lunch.png deleted file mode 100644 index 3cfa10f..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-lunch.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-na.png b/resources/images/protocol/yahoo/yahoo16x16-na.png deleted file mode 100644 index 9a1f8ad..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-na.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-offline.png b/resources/images/protocol/yahoo/yahoo16x16-offline.png deleted file mode 100644 index 851bb54..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-offline.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-online.png b/resources/images/protocol/yahoo/yahoo16x16-online.png deleted file mode 100644 index eaea8e2..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-online.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-phone.png b/resources/images/protocol/yahoo/yahoo16x16-phone.png deleted file mode 100644 index c037ad1..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-phone.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16-vacation.png b/resources/images/protocol/yahoo/yahoo16x16-vacation.png deleted file mode 100644 index 02e8b1f..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16-vacation.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo16x16.png b/resources/images/protocol/yahoo/yahoo16x16.png deleted file mode 100644 index eaea8e2..0000000 Binary files a/resources/images/protocol/yahoo/yahoo16x16.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo32x32.png b/resources/images/protocol/yahoo/yahoo32x32.png deleted file mode 100644 index eed8b25..0000000 Binary files a/resources/images/protocol/yahoo/yahoo32x32.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo48x48.png b/resources/images/protocol/yahoo/yahoo48x48.png deleted file mode 100644 index 132a990..0000000 Binary files a/resources/images/protocol/yahoo/yahoo48x48.png and /dev/null differ diff --git a/resources/images/protocol/yahoo/yahoo64x64.png b/resources/images/protocol/yahoo/yahoo64x64.png deleted file mode 100644 index 827133f..0000000 Binary files a/resources/images/protocol/yahoo/yahoo64x64.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf-away.png b/resources/images/protocol/zeroconf/zeroconf-away.png deleted file mode 100644 index 8265d5a..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf-away.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf-dnd.png b/resources/images/protocol/zeroconf/zeroconf-dnd.png deleted file mode 100644 index fa1b70b..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf-dnd.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf-invisible.png b/resources/images/protocol/zeroconf/zeroconf-invisible.png deleted file mode 100644 index e3bd0cf..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf-invisible.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf-offline.png b/resources/images/protocol/zeroconf/zeroconf-offline.png deleted file mode 100644 index de37240..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf-offline.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf-online.png b/resources/images/protocol/zeroconf/zeroconf-online.png deleted file mode 100644 index be66b1b..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf-online.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf16x16.png b/resources/images/protocol/zeroconf/zeroconf16x16.png deleted file mode 100644 index be66b1b..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf16x16.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf32x32.png b/resources/images/protocol/zeroconf/zeroconf32x32.png deleted file mode 100644 index 58754b6..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf32x32.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf48x48.png b/resources/images/protocol/zeroconf/zeroconf48x48.png deleted file mode 100644 index fbae916..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf48x48.png and /dev/null differ diff --git a/resources/images/protocol/zeroconf/zeroconf64x64.png b/resources/images/protocol/zeroconf/zeroconf64x64.png deleted file mode 100644 index 6db9d49..0000000 Binary files a/resources/images/protocol/zeroconf/zeroconf64x64.png and /dev/null differ diff --git a/resources/install/debian/README.embedded-libraries b/resources/install/debian/README.embedded-libraries index 036029f..6ecff8a 100644 --- a/resources/install/debian/README.embedded-libraries +++ b/resources/install/debian/README.embedded-libraries @@ -12,12 +12,6 @@ Jingle Nodes is an XMPP Extension that enable users to share and discover P2P Media Relays that can be used to enable Voice and Video Chat via Jingle. Reason: No Debian package. -- jymsg http://jymsg9.sourceforge.net/ -This API provides a way for Java applications to connect and -use the Yahoo Instant Messenger protocol. -Damian Minkov from Jitsi team is contributor and has commit right in the project. -Reason: No Debian package. - - OrangeExtensions http://ymasory.github.com/OrangeExtensions/ A pluggable jar containing stubs for the Apple Java Extensions. Reason: No Debian package. diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index cc5f976..1bfcee4 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -92,7 +92,7 @@ Description: VoIP and Instant Messaging client _APP_NAME_ is an application that allows you to do audio/video conversations over the Internet through the SIP and XMPP/Jabber protocol, as well as chat with your friends using some of the most popular instant - messaging protocols such as SIP/SIMPLE, XMPP/Jabber, AIM/ICQ, Yahoo and others. + messaging protocols such as SIP/SIMPLE, XMPP/Jabber, AIM/ICQ and others. Package: _PACKAGE_NAME_-jni Replaces: libjitsi-jni (<< 415) diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index 135ad37..e722ff7 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -65,4 +65,4 @@ Description: VoIP and Instant Messaging client _APP_NAME_ is an application that allows you to do audio/video conversations over the Internet through the SIP and XMPP/Jabber protocol, as well as chat with your friends using some of the most popular instant - messaging protocols such as SIP/SIMPLE, XMPP/Jabber, AIM/ICQ, Yahoo and others. + messaging protocols such as SIP/SIMPLE, XMPP/Jabber, AIM/ICQ and others. diff --git a/resources/install/debian/jitsi.1.tmpl b/resources/install/debian/jitsi.1.tmpl index 5608d63..d09beb5 100644 --- a/resources/install/debian/jitsi.1.tmpl +++ b/resources/install/debian/jitsi.1.tmpl @@ -26,7 +26,7 @@ _PACKAGE_NAME_ \- the Java VoIP and Instant Messaging client .\" respectively. \fB_APP_NAME_\fP is an audio/video Internet phone and instant messenger that supports some of the most popular instant messaging and telephony -protocols such as SIP, Jabber, AIM/ICQ, Yahoo! Messenger, Bonjour, IRC +protocols such as SIP, Jabber/XMPP, AIM/ICQ, IRC and soon others like IAX. .PP .RI "An optional " uri-to-call " expression can be specified to start a call from the command-line. If _APP_NAME_ is already running then the call is handled by the running application, except when it is explicitly told to allow multiple instance launch." diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index 0d60ff7..c427c4d 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -5,9 +5,9 @@ Summary: Jitsi - Open Source Video Calls and Chat Packager: Damian Minkov Group: Applications/Internet -License: GNU Lesser General Public License +License: Apache License 2.0 URL: https://www.jitsi.org -Source0: http://download.jitsi.org/jitsi/nightly/src/%{name}-src-%{version}-%{release}.zip +Source0: https://download.jitsi.org/jitsi/nightly/src/%{name}-src-%{version}-%{release}.zip BuildRoot: %{_topdir}/buildroot AutoReqProv: no @@ -21,8 +21,8 @@ Requires: java >= 0:1.6 %description Jitsi (formerly SIP Communicator) is an audio/video and chat communicator -that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC, -Yahoo! and many other useful features. +that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC +and many other useful features. %define debug_package %{nil} diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 44f0c70..deea410 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1356,12 +1356,6 @@ plugin.whiteboard.DESELECT=Deselect plugin.whiteboard.DELETE=Delete plugin.whiteboard.PROPERTIES=Properties -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=A protocol to connect and chat on the Yahoo! Service. -plugin.yahooaccregwizz.USERNAME=Username: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID and Password - # zero accregwizz plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=The Zeroconf (Bonjour) service protocol. @@ -1726,8 +1720,6 @@ Proxy support is currently experimental and only works with some protocols. \ Check out the table below for more details: plugin.globalproxy.PROTOCOL_SUPPORT= \ \ -\ -\ \ \
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java index d4d2ed5..cf42720 100644 --- a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsEntryImpl.java @@ -43,20 +43,14 @@ public class GoogleContactsEntryImpl /** * Google Talk protocol type. */ - private static final String YAHOO_PROTOCOL = - "http://schemas.google.com/g/2005#YAHOO"; - - /** - * Google Talk protocol type. - */ private static final String AIM_PROTOCOL = "http://schemas.google.com/g/2005#AIM"; /** * Google Talk protocol type. */ - private static final String MSN_PROTOCOL = - "http://schemas.google.com/g/2005#MSN"; + private static final String SKYPE_PROTOCOL = + "http://schemas.google.com/g/2005#SKYPE"; /** * Google Talk protocol type. @@ -432,17 +426,13 @@ public class GoogleContactsEntryImpl { proto = GoogleContactsEntry.IMProtocol.GOOGLETALK; } - else if(protocol.equals(YAHOO_PROTOCOL)) - { - proto = GoogleContactsEntry.IMProtocol.YAHOO; - } else if(protocol.equals(AIM_PROTOCOL)) { proto = GoogleContactsEntry.IMProtocol.AIM; } - else if(protocol.equals(MSN_PROTOCOL)) + else if(protocol.equals(SKYPE_PROTOCOL)) { - proto = GoogleContactsEntry.IMProtocol.MSN; + proto = GoogleContactsEntry.IMProtocol.SKYPE; } else if(protocol.equals(ICQ_PROTOCOL)) { diff --git a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java index d33e4da..66ea7ad 100644 --- a/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java +++ b/src/net/java/sip/communicator/impl/googlecontacts/GoogleContactsQuery.java @@ -279,14 +279,11 @@ public class GoogleContactsQuery case ICQ: imSubCat = ContactDetail.SubCategory.ICQ; break; - case YAHOO: - imSubCat = ContactDetail.SubCategory.Yahoo; - break; case JABBER: imSubCat = ContactDetail.SubCategory.Jabber; break; - case MSN: - imSubCat = ContactDetail.SubCategory.MSN; + case SKYPE: + imSubCat = ContactDetail.SubCategory.Skype; break; case GOOGLETALK: imSubCat = ContactDetail.SubCategory.GoogleTalk; @@ -357,12 +354,6 @@ public class GoogleContactsQuery OperationSetBasicTelephony.class, ProtocolNames.JABBER); break; - case YAHOO: - supportedOpSets.add(OperationSetBasicInstantMessaging.class); - preferredProtocols.put( - OperationSetBasicInstantMessaging.class, - ProtocolNames.YAHOO); - break; default: break; } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java index 08aaf7e..1419416 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java @@ -709,11 +709,9 @@ public class SourceUIContact case AIM: case ICQ: case Jabber: - case MSN: case Yahoo: case Skype: case GoogleTalk: - case Facebook: label = subCategory.value(); break; default: diff --git a/src/net/java/sip/communicator/impl/protocol/icq/icq.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/icq/icq.provider.manifest.mf index da47277..959ae6d 100644 --- a/src/net/java/sip/communicator/impl/protocol/icq/icq.provider.manifest.mf +++ b/src/net/java/sip/communicator/impl/protocol/icq/icq.provider.manifest.mf @@ -13,5 +13,4 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.dns, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.icqconstants, - net.java.sip.communicator.service.protocol.aimconstants, net.java.sip.communicator.service.protocol.event diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/AbstractContactGroupYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/AbstractContactGroupYahooImpl.java deleted file mode 100644 index 0514c16..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/AbstractContactGroupYahooImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Yahoo implementation of the service.protocol.ContactGroup interface. There - * are two types of groups possible here. RootContactGroupYahooImpl - * which is the root node of the ContactList itself and - * ContactGroupYahooImpl which represents standard groups. The - * reason for having those 2 is that generally, Yahoo groups may not contain - * subgroups. A contact list on the other hand may not directly contain buddies. - * - * - * The reason for having an abstract class is only - being able to esily - * recognize our own (Yahoo) contacts. - * @author Damian Minkov - */ -public abstract class AbstractContactGroupYahooImpl - implements ContactGroup -{ - - -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomInvitationYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomInvitationYahooImpl.java deleted file mode 100644 index e849f6c..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomInvitationYahooImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Yahoo implementation of the AdHocChatRoomInvitation interface. - * - * @author Rupert Burchardi - * @author Valentin Martinet - */ -public class AdHocChatRoomInvitationYahooImpl - implements AdHocChatRoomInvitation -{ - /** - * Corresponding chat room instance. - */ - private AdHocChatRoom chatRoom; - /** - * The name of the inviter - */ - private String inviter; - - /** - * The invitation reason. - */ - private String reason; - - - /** - * Creates an instance of the ChatRoomInvitationMsnImpl by - * specifying the targetChatRoom, the inviter, the reason. - * - * @param targetChatRoom The AdHocChatRoom for which the invitation - * is - * @param inviter The Contact, which sent the invitation - * @param reason The Reason for the invitation - */ - public AdHocChatRoomInvitationYahooImpl( AdHocChatRoom targetChatRoom, - String inviter, - String reason) - { - this.chatRoom = targetChatRoom; - this.inviter = inviter; - this.reason = reason; - } - - /** - * Returns the corresponding chat room. - * @return The ad-hoc chat room - */ - public AdHocChatRoom getTargetAdHocChatRoom() - { - return chatRoom; - } - - /** - * Returns the corresponding inviter. - * @return The name of the inviter - */ - public String getInviter() - { - return inviter; - } - - /** - * Returns the invitation reason. - * @return the invitation reason - */ - public String getReason() - { - return reason; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomYahooImpl.java deleted file mode 100644 index 2775f6f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/AdHocChatRoomYahooImpl.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; - -/** - * Represents a Yahoo ad-hoc chat room, where multiple chat users could - * communicate in a many-to-many fashion. - * - * @author Rupert Burchardi - * @author Valentin Martinet - */ -public class AdHocChatRoomYahooImpl - implements AdHocChatRoom -{ - private static final Logger logger = Logger - .getLogger(AdHocChatRoomYahooImpl.class); - - /** - * Listeners that will be notified of changes in member status in the room - * such as member joined, left or being kicked or dropped. - */ - private Vector memberListeners - = new Vector(); - - /** - * Listeners that will be notified every time a new message is received on - * this ad-hoc chat room. - */ - private Vector messageListeners - = new Vector(); - - /** - * The protocol provider that created us - */ - private ProtocolProviderServiceYahooImpl provider = null; - - /** - * The operation set that created us. - */ - private OperationSetAdHocMultiUserChatYahooImpl opSetMuc = null; - - /** - * The list of participants of this chat room. - */ - private Hashtable participants - = new Hashtable(); - - /** - * The nickname of this chat room local user participant. - */ - private String nickname; - - /** - * The yahoo conference model of this ad-hoc chat room, its the - * representation of an ad-hoc chat room in the lib for this protocol. - */ - private YahooConference yahooConference = null; - - /** - * Creates an instance of a chat room that has been. - * - * @param multiUserChat - * MultiUserChat - * @param provider - * a reference to the currently valid jabber protocol provider. - */ - public AdHocChatRoomYahooImpl( YahooConference multiUserChat, - ProtocolProviderServiceYahooImpl provider) - { - this.yahooConference = multiUserChat; - this.provider = provider; - this.opSetMuc = (OperationSetAdHocMultiUserChatYahooImpl) provider - .getOperationSet(OperationSetAdHocMultiUserChat.class); - } - - /** - * Registers listener so that it would receive events every time a - * new message is received on this chat room. - * - * @param listener A MessageListener that would be notified every - * time a new message is received on this chat room. - */ - public void addMessageListener(AdHocChatRoomMessageListener listener) - { - synchronized (messageListeners) - { - if (!messageListeners.contains(listener)) - messageListeners.add(listener); - } - } - - /** - * Removes listener so that it won't receive any further message - * events from this room. - * - * @param listener The MessageListener to remove from this room - */ - public void removeMessageListener(AdHocChatRoomMessageListener listener) - { - synchronized (messageListeners) - { - messageListeners.remove(listener); - } - } - - /** - * Adds a listener that will be notified of changes in our status in the - * room. - * - * @param listener A participant status listener. - */ - public void addParticipantPresenceListener( - AdHocChatRoomParticipantPresenceListener listener) - { - synchronized (memberListeners) - { - if (!memberListeners.contains(listener)) - memberListeners.add(listener); - } - } - - /** - * Removes a listener that was being notified of changes in the status of - * other chat room participants. - * - * @param listener A participant status listener. - */ - public void removeParticipantPresenceListener( - AdHocChatRoomParticipantPresenceListener listener) - { - synchronized (memberListeners) - { - memberListeners.remove(listener); - } - } - - /** - * Create a Message instance for sending a simple text messages with default - * (text/plain) content type and encoding. - * - * @param messageText - * the string content of the message. - * @return Message the newly created message - */ - public Message createMessage(String messageText) - { - Message msg = new MessageYahooImpl(messageText, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, - OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, null); - return msg; - } - - /** - * Returns a List of Contacts corresponding to all members - * currently participating in this room. - * - * @return a List of Contact corresponding to all room - * members. - */ - public List getParticipants() - { - return new LinkedList(participants.values()); - } - - /** - * Updates the member list of the chat room. - * - */ - public void updateParticipantsList() - { - Iterator it = yahooConference.getMembers().iterator(); - - while (it.hasNext()) - { - YahooUser user = (YahooUser) it.next(); - Contact contact; - OperationSetPersistentPresenceYahooImpl presenceOpSet - = (OperationSetPersistentPresenceYahooImpl) this - .getParentProvider().getOperationSet( - OperationSetPersistentPresence.class); - - contact = presenceOpSet.findContactByID(user.getId()); - - if(!participants.containsKey(contact.getDisplayName())) - { - participants.put(contact.getDisplayName(), contact); - } - } - } - - /** - * Returns the identifier of this AdHocChatRoom. - * - * @return a String containing the identifier of this - * AdHocChatRoom. - */ - public String getIdentifier() - { - return yahooConference.getName(); - } - - /** - * Returns the number of participants that are currently in this ad-hoc chat - * room. - * - * @return the number of Contacts, currently participating in - * this ad-hoc room. - */ - public int getParticipantsCount() - { - return yahooConference.getMembers().size(); - } - - /** - * Returns the name of this AdHocChatRoom. - * - * @return a String containing the name of this - * AdHocChatRoom. - */ - public String getName() - { - return yahooConference.getName(); - } - - /** - * Returns the protocol provider service that created us. - * - * @return the protocol provider service that created us. - */ - public ProtocolProviderService getParentProvider() - { - return provider; - } - - /** - * Returns the local user's nickname in the context of this chat room or - * null if not currently joined. - * - * @return the nickname currently being used by the local user in the - * context of the local ad-hoc chat room. - */ - - public String getUserNickname() - { - if(nickname == null) - nickname = provider.getYahooSession().getLoginIdentity().getId(); - - return nickname; - } - - /** - * Invites another user to this room. If we're not joined nothing will - * happen. - * - * @param userAddress The identifier of the contact (email address or yahoo - * id) - * @param reason The invite reason, which is send to the invitee. - */ - public void invite(String userAddress, String reason) - { - try - { - provider.getYahooSession().extendConference(yahooConference, - userAddress, reason); - } - catch (IOException ioe) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to invite the user: " + userAddress - + " Error: " + ioe); - } - } - - /** - * Indicates whether or not this chat room is corresponding to a server - * channel. Note: Returns always false. - * - * @return Always false since system chat room can't be joined - * with current yahoo library. - */ - public boolean isSystem() - { - return false; - } - - /** - * Joins this chat room with the nickname of the local user so that the user - * would start receiving events and messages for it. - * - * @throws OperationFailedException with the corresponding code if an error - * occurs while joining the room. - */ - public void join() throws OperationFailedException - { - this.nickname = provider.getAccountID().getUserID(); - try - { - provider.getYahooSession().acceptConferenceInvite(yahooConference); - - // We don't specify a reason. - opSetMuc.fireLocalUserPresenceEvent(this, - LocalUserAdHocChatRoomPresenceChangeEvent.LOCAL_USER_JOINED, - null); - } - catch (Exception e) - { - if (logger.isDebugEnabled()) - logger.debug("Couldn't join the chat room: " - + yahooConference.getName() + e); - } - } - - /** - * Leave this chat room. Once this method is called, the user won't be - * listed as a member of the chat room any more and no further chat events - * will be delivered. Depending on the underlying protocol and - * implementation leave() might cause the room to be destroyed if it has - * been created by the local user. - */ - public void leave() - { - try - { - provider.getYahooSession().leaveConference(yahooConference); - - Iterator< Map.Entry> membersSet - = participants.entrySet().iterator(); - - while (membersSet.hasNext()) - { - Map.Entry memberEntry = membersSet.next(); - Contact participant = memberEntry.getValue(); - - fireParticipantPresenceEvent(participant, - AdHocChatRoomParticipantPresenceChangeEvent.CONTACT_LEFT, - "Local user has left the chat room."); - } - } - catch (IOException ioe) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to leave the chat room: " - + yahooConference.getName() + " Error: " + ioe); - } - - participants.clear(); - } - - /** - * Sends the message to the destination indicated by the - * to contact. - * - * @param message The Message to send. - * @throws OperationFailedException if the underlying stack is not - * registered or initialized or if the chat room is not joined. - */ - public void sendMessage(Message message) throws OperationFailedException - { - assertConnected(); - - try - { - provider.getYahooSession().sendConferenceMessage(yahooConference, - message.getContent()); - - AdHocChatRoomMessageDeliveredEvent msgDeliveredEvt - = new AdHocChatRoomMessageDeliveredEvent( - this, - new Date(), - message, - ChatRoomMessageDeliveredEvent.CONVERSATION_MESSAGE_DELIVERED); - - fireMessageEvent(msgDeliveredEvt); - } - catch (Exception e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to send a conference message."); - } - } - - /** - * Notifies all interested listeners that a - * AdHocChatRoomMessageDeliveredEvent, - * AdHocChatRoomMessageReceivedEvent or a - * AdHocChatRoomMessageDeliveryFailedEvent has been fired. - * @param evt The specific event - */ - public void fireMessageEvent(EventObject evt) - { - Iterator listeners = null; - synchronized (messageListeners) - { - listeners = new ArrayList( - messageListeners).iterator(); - } - - while (listeners.hasNext()) - { - AdHocChatRoomMessageListener listener = listeners.next(); - - if (evt instanceof AdHocChatRoomMessageDeliveredEvent) - { - listener.messageDelivered( - (AdHocChatRoomMessageDeliveredEvent) evt); - } - else if (evt instanceof AdHocChatRoomMessageReceivedEvent) - { - listener.messageReceived( - (AdHocChatRoomMessageReceivedEvent) evt); - } - else if (evt instanceof AdHocChatRoomMessageDeliveryFailedEvent) - { - listener.messageDeliveryFailed( - (AdHocChatRoomMessageDeliveryFailedEvent) evt); - } - } - } - - /** - * Creates the corresponding AdHocChatRoomParticipantPresenceChangeEvent and - * notifies all AdHocChatRoomParticipantPresenceListeners that a - * Contact has joined or left this AdHocChatRoom. - * - * @param participant the Contact that this - * @param eventID the identifier of the event - * @param eventReason the reason of the event - */ - public void fireParticipantPresenceEvent(Contact participant, String eventID, - String eventReason) - { - AdHocChatRoomParticipantPresenceChangeEvent evt - = new AdHocChatRoomParticipantPresenceChangeEvent(this, - participant, - eventID, - eventReason); - - if (logger.isTraceEnabled()) - logger.trace("Will dispatch the following ChatRoom event: " + evt); - - Iterator listeners = null; - synchronized (memberListeners) - { - listeners = new ArrayList - (memberListeners).iterator(); - } - - while (listeners.hasNext()) - { - AdHocChatRoomParticipantPresenceListener listener = listeners.next(); - - listener.participantPresenceChanged(evt); - } - } - - /** - * Finds the participant of this ad-hoc chat room corresponding to the - * given address. - * - * @param address the address to search for. - * @return the participant of this chat room corresponding to the given - * nick name. - */ - public Contact findParticipantForAddress(String address) - { - Iterator participantsIter - = this.participants.values().iterator(); - - while (participantsIter.hasNext()) - { - Contact contact = participantsIter.next(); - - if (contact.getAddress().equals(address)) - { - return contact; - } - } - - return null; - } - - /** - * Removes the specified ad-hoc chat room participant from the participants - * list of this ad-hoc chat room. - * @param participant The member, who should be removed from the ad-hoc chat room - * participants list. - */ - public void removeChatRoomParticipant(Contact participant) - { - if(participant == null) - return; - - participants.remove(participant.getDisplayName()); - - fireParticipantPresenceEvent(participant, - AdHocChatRoomParticipantPresenceChangeEvent.CONTACT_LEFT, null); - } - - /** - * Adds a participant to the ad-hoc chat room participant list. - * @param participant The participant, who should be added to the ad-hoc - * chat room participant list. - */ - public void addChatRoomParticipant(Contact participant) - { - if (participant == null) - return; - - if (!participants.containsKey(participant.getDisplayName())) - { - participants.put(participant.getDisplayName(), participant); - - fireParticipantPresenceEvent(participant, - AdHocChatRoomParticipantPresenceChangeEvent.CONTACT_JOINED, - null); - } - } - - /** - * Returns the yahoo conference model of this chat room. - * @return The yahoo conference. - */ - public YahooConference getYahooConference() - { - return yahooConference; - } - - /** - * Utility method throwing an exception if the stack is not properly - * initialized. - * @throws java.lang.IllegalStateException if the underlying stack is - * not registered and initialized. - */ - private void assertConnected() throws IllegalStateException - { - if (provider == null) - throw new IllegalStateException( - "The provider must be non-null and signed on the " - +"service before being able to communicate."); - if (!provider.isRegistered()) - throw new IllegalStateException( - "The provider must be signed on the service before " - +"being able to communicate."); - } - - /** - * Determines whether this chat room should be stored in the configuration - * file or not. If the chat room is persistent it still will be shown after a - * restart in the chat room list. A non-persistent chat room will be only in - * the chat room list until the the program is running. - * - * @return true if this chat room is persistent, false otherwise - */ - public boolean isPersistent() - { - return false; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ContactGroupYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ContactGroupYahooImpl.java deleted file mode 100644 index 1f73aac..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ContactGroupYahooImpl.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import ymsg.network.*; - -/** - * The Yahoo implementation of the ContactGroup interface. Intances of this class - * (contrary to RootContactGroupYahooImpl) may only contain buddies - * and cannot have sub groups. Note that instances of this class only use the - * corresponding smack source group for reading their names and only - * initially fill their buddies java.util.List with - * the ContactYahooImpl objects corresponding to those contained in the source - * group at the moment it is being created. They would, however, never try to - * sync or update their contents ulteriorly. This would have to be done through - * the addContact()/removeContact() methods. - * The content of buddies is created on creating of the group and when the smack - * source group is changed. - * - * @author Damian Minkov - * @author Emil Ivov - */ -public class ContactGroupYahooImpl - extends AbstractContactGroupYahooImpl -{ - private final Map buddies - = new Hashtable(); - - private boolean isResolved = false; - - /** - * The Yahoo Group corresponding to this contact group. - */ - private YahooGroup yahooGroup = null; - - /** - * a list that would always remain empty. We only use it so that we're able - * to extract empty iterators - */ - private final List dummyGroupsList - = new LinkedList(); - - private String tempId = null; - - private final ServerStoredContactListYahooImpl ssclCallback; - - /** - * Creates an Yahoo group using the specified YahooGroup as - * a source. The newly created group will always return the name of the - * underlying RosterGroup and would thus automatically adapt to changes. - * It would, however, not receive or try to poll for modifications of the - * buddies it contains and would therefore have to be updated manually by - * ServerStoredContactListImpl update will only be done if source group - * is changed. - - * @param yahooGroup the Yahoo Group correspoinding to the group - * @param groupMembers the group members that we should add to the group. - * @param ssclCallback a callback to the server stored contact list - * we're creating. - * @param isResolved a boolean indicating whether or not the group has been - * resolved against the server. - */ - ContactGroupYahooImpl( - YahooGroup yahooGroup, - Vector groupMembers, - ServerStoredContactListYahooImpl ssclCallback, - boolean isResolved) - { - this.yahooGroup = yahooGroup; - this.isResolved = isResolved; - this.ssclCallback = ssclCallback; - - for (YahooUser yahooUser : groupMembers) - { - //only add the contact if it doesn't already exist in some other - //group. this would be necessary if Yahoo! one day start allowing - //the same contact in more than one group, which is not quite - //unlikely since most of the other protocols do it. - if(ssclCallback.findContactByYahooUser(yahooUser) != null) - { - continue; - } - - - addContact( - new ContactYahooImpl(yahooUser,ssclCallback, true, true)); - } - } - - ContactGroupYahooImpl( String id, - ServerStoredContactListYahooImpl ssclCallback) - { - this.tempId = id; - this.isResolved = false; - this.ssclCallback = ssclCallback; - } - - - /** - * Returns the number of Contact members of this - * ContactGroup - * - * @return an int indicating the number of Contacts, - * members of this ContactGroup. - */ - public int countContacts() - { - return buddies.size(); - } - - /** - * Returns a reference to the root group which in Yahoo is the parent of - * any other group since the protocol does not support subgroups. - * @return a reference to the root group. - */ - public ContactGroup getParentContactGroup() - { - return ssclCallback.getRootGroup(); - } - - /** - * Adds the specified contact to the end of this group. - * @param contact the new contact to add to this group - */ - void addContact(ContactYahooImpl contact) - { - buddies.put(contact.getAddress().toLowerCase(), contact); - } - - - /** - * Removes the specified contact from this contact group - * @param contact the contact to remove. - */ - void removeContact(ContactYahooImpl contact) - { - buddies.remove(contact.getAddress().toLowerCase()); - } - - /** - * Returns an Iterator over all contacts, member of this - * ContactGroup. - * - * @return a java.util.Iterator over all contacts inside this - * ContactGroup. In case the group doesn't contain any - * memebers it will return an empty iterator. - */ - public Iterator contacts() - { - return buddies.values().iterator(); - } - - /** - * Returns the Contact with the specified address or - * identifier. - * @param id the addres or identifier of the Contact we are - * looking for. - * @return the Contact with the specified id or address. - */ - public Contact getContact(String id) - { - return this.findContact(id); - } - - /** - * Returns the name of this group. - * @return a String containing the name of this group. - */ - public String getGroupName() - { - if(isResolved) - return ServerStoredContactListYahooImpl - .replaceIllegalChars(yahooGroup.getName()); - else - return tempId; - } - - /** - * Determines whether the group may contain subgroups or not. - * - * @return always false since only the root group may contain subgroups. - */ - public boolean canContainSubgroups() - { - return false; - } - - /** - * Returns the subgroup with the specified index (i.e. always null since - * this group may not contain subgroups). - * - * @param index the index of the ContactGroup to retrieve. - * @return always null - */ - public ContactGroup getGroup(int index) - { - return null; - } - - /** - * Returns the subgroup with the specified name. - * @param groupName the name of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(String groupName) - { - return null; - } - - /** - * Returns an empty iterator. Subgroups may only be present in the root - * group. - * - * @return an empty iterator - */ - public Iterator subgroups() - { - return dummyGroupsList.iterator(); - } - - /** - * Returns the number of subgroups contained by this group, which is - * always 0 since sub groups in the protocol may only be contained - * by the root group - RootContactGroupImpl. - * @return a 0 int. - */ - public int countSubgroups() - { - return 0; - } - - /** - * Returns a hash code value for the object, which is actually the hashcode - * value of the groupname. - * - * @return a hash code value for this ContactGroup. - */ - @Override - public int hashCode() - { - return getGroupName().hashCode(); - } - - /** - * Indicates whether some other object is "equal to" this group. - * - * @param obj the reference object with which to compare. - * @return true if this object is the same as the obj - * argument; false otherwise. - */ - @Override - public boolean equals(Object obj) - { - if( obj == this ) - return true; - - if (obj == null - || !(obj instanceof ContactGroupYahooImpl) ) - return false; - - if(!((ContactGroup)obj).getGroupName().equals(getGroupName())) - return false; - - if(getProtocolProvider() != ((ContactGroup)obj).getProtocolProvider()) - return false; - - //since Yahoo does not support having two groups with the same name - // at this point we could bravely state that the groups are the same - // and not bother to compare buddies. (gotta check that though) - return true; - } - - /** - * Returns the protocol provider that this group belongs to. - * @return a reference to the ProtocolProviderService instance that this - * ContactGroup belongs to. - */ - public ProtocolProviderService getProtocolProvider() - { - return this.ssclCallback.getParentProvider(); - } - - /** - * Returns a string representation of this group, in the form - * YahooGroup.GroupName[size]{ buddy1.toString(), buddy2.toString(), ...}. - * @return a String representation of the object. - */ - @Override - public String toString() - { - StringBuffer buff = new StringBuffer("YahooGroup."); - buff.append(getGroupName()); - buff.append(", childContacts="+countContacts()+":["); - - Iterator contacts = contacts(); - while (contacts.hasNext()) - { - Contact contact = contacts.next(); - buff.append(contact.toString()); - if(contacts.hasNext()) - buff.append(", "); - } - return buff.append("]").toString(); - } - - /** - * Returns the contact encapsulating with the spcieified name or - * null if no such contact was found. - * - * @param id the id for the contact we're looking for. - * @return the ContactYahooImpl corresponding to the specified - * screnname or null if no such contact existed. - */ - ContactYahooImpl findContact(String id) - { - if(id == null) - return null; - return (ContactYahooImpl)buddies.get(id.toLowerCase()); - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - public boolean isPersistent() - { - return true; - } - - /** - * Returns null as no persistent data is required and the contact address is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact group has been resolved against - * the server. Unresolved group are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts and groups to their corresponding on-line - * buddies. - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Resolve this contact group against the specified group - * @param yahooGroup the server stored group - */ - @SuppressWarnings("unchecked") //jymsg legacy code - void setResolved(YahooGroup yahooGroup) - { - if(isResolved) - return; - - this.isResolved = true; - - this.yahooGroup = yahooGroup; - - Vector contacts = yahooGroup.getMembers(); - for (YahooUser item : contacts) - { - ContactYahooImpl contact = - ssclCallback.findContactById(item.getId()); - if(contact != null) - { - contact.setResolved(item); - - ssclCallback.fireContactResolved(this, contact); - } - else - { - ContactYahooImpl newContact = - new ContactYahooImpl(item, ssclCallback, true, true); - addContact(newContact); - - ssclCallback.fireContactAdded(this, newContact); - } - } - } - - /** - * Returns a String that uniquely represnets the group. In this we - * use the name of the group as an identifier. This may cause problems - * though, in clase the name is changed by some other application between - * consecutive runs of the sip-communicator. - * - * @return a String representing this group in a unique and persistent - * way. - */ - public String getUID() - { - return getGroupName(); - } - - /** - * The source group we are encapsulating - * @return YahooGroup - */ - YahooGroup getSourceGroup() - { - return yahooGroup; - } - - /** - * Change the source group - * change the buddies - * - * @param newGroup YahooGroup - */ - void setSourceGroup(YahooGroup newGroup) - { - this.yahooGroup = newGroup; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ContactYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ContactYahooImpl.java deleted file mode 100644 index b23ee3d..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ContactYahooImpl.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.yahooconstants.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; - -/** - * The Yahoo implementation of the service.protocol.Contact interface. - * @author Damian Minkov - * @author Emil Ivov - */ -public class ContactYahooImpl - extends AbstractContact -{ - private static final Logger logger = - Logger.getLogger(ContactYahooImpl.class); - - private YahooUser contact = null; - private byte[] image = null; - private PresenceStatus status = YahooStatusEnum.OFFLINE; - private ServerStoredContactListYahooImpl ssclCallback = null; - private boolean isPersistent = false; - private boolean isResolved = false; - private boolean isVolatile = false; - - private String yahooID = null; - private String id = null; - - private String statusMessage = null; - - /** - * Creates an YahooContactImpl with custom yahooID - * @param yahooID sets the contact Id if its different from the YahooUser id - * @param contact the contact object that we will be encapsulating. - * @param ssclCallback a reference to the ServerStoredContactListImpl - * instance that created us. - * @param isPersistent determines whether this contact is persistent or not. - * @param isResolved specifies whether the contact has been resolved against - * the server contact list - */ - ContactYahooImpl( - String yahooID, - YahooUser contact, - ServerStoredContactListYahooImpl ssclCallback, - boolean isPersistent, - boolean isResolved) - { - this.yahooID = yahooID; - - this.contact = contact; - this.ssclCallback = ssclCallback; - this.isPersistent = isPersistent; - this.isResolved = isResolved; - - if(contact != null) - id = contact.getId(); - else if(yahooID != null) - id = YahooSession.getYahooUserID(yahooID); - } - - /** - * Creates an YahooContactImpl - * @param contact the contact object that we will be encapsulating. - * @param ssclCallback a reference to the ServerStoredContactListImpl - * instance that created us. - * @param isPersistent determines whether this contact is persistent or not. - * @param isResolved specifies whether the contact has been resolved against - * the server contact list - */ - ContactYahooImpl( - YahooUser contact, - ServerStoredContactListYahooImpl ssclCallback, - boolean isPersistent, - boolean isResolved) - { - this(null, contact, ssclCallback, isPersistent, isResolved); - } - - /** - * Creates volatile or unresolved contact - */ - ContactYahooImpl( - String id, - ServerStoredContactListYahooImpl ssclCallback, - boolean isResolved, - boolean isPersistent, - boolean isVolatile) - { - this.yahooID = id; - this.ssclCallback = ssclCallback; - this.isPersistent = isPersistent; - this.isResolved = isResolved; - this.isVolatile = isVolatile; - - if(id != null) - this.id = YahooSession.getYahooUserID(yahooID); - } - - /** - * Returns the Yahoo Userid of this contact - * @return the Yahoo Userid of this contact - */ - public String getAddress() - { - // if the contact is volatile or with custom id return it - if(yahooID != null) - return yahooID; - // otherwise return the supplied contact id - else - return contact.getId(); - } - - /** - * Returns the custom yahooID if set - */ - String getYahooID() - { - return yahooID; - } - - /** - * Returns the contact Id. - * If contact missing the yahooID without @yahoo.com part is returned - */ - String getID() - { - return id; - } - - /** - * Returns whether the contact is volatile. - */ - boolean isVolatile() - { - return isVolatile; - } - - /** - * Returns an avatar if one is already present or null in case it - * is not in which case it the method also queues the contact for image - * updates. - * - * @return the avatar of this contact or null if no avatar is - * currently available. - */ - public byte[] getImage() - { - return getImage(true); - } - - /** - * Returns a reference to the image assigned to this contact. If no image - * is present and the retrieveIfNecessary flag is true, we schedule the - * image for retrieval from the server. - * - * @param retrieveIfNecessary specifies whether the method should queue - * this contact for avatar update from the server. - * - * @return a reference to the image currently stored by this contact. - */ - public byte[] getImage(boolean retrieveIfNecessary) - { - try - { - if(retrieveIfNecessary) - { - if(ssclCallback.getParentProvider() == null - || !ssclCallback.getParentProvider().isRegistered()) - { - throw new IllegalStateException( - "The provider must be signed on the service before " - +"being able to communicate."); - } - - YahooSession ses = ssclCallback.getParentProvider(). - getYahooSession(); - if(image == null && ses != null) - ses.requestPicture(id); - } - } - catch (Exception e) - { - if (logger.isInfoEnabled()) - logger.info("Error requesting image!", e); - } - - if(logger.isDebugEnabled()) - logger.debug("returning picture " + image); - - return image; - } - - /** - * Used to set the image of the contact if it is updated - * - * @param image a photo/avatar associated with this contact. - */ - protected void setImage(byte[] image) - { - if (logger.isInfoEnabled()) - logger.info("setting image " + image); - - this.image = image; - } - - /** - * Returns a string representation of this contact, containing most of its - * representative details. - * - * @return a string representation of this contact. - */ - @Override - public String toString() - { - StringBuffer buff = new StringBuffer("YahooContact[ id="); - buff.append(getAddress()).append("]"); - - return buff.toString(); - } - - /** - * Sets the status that this contact is currently in. The method is to - * only be called as a result of a status update received from the server. - * - * @param status the YahooStatusEnum that this contact is currently in. - */ - void updatePresenceStatus(PresenceStatus status) - { - this.status = status; - } - - /** - * Returns the status of the contact as per the last status update we've - * received for it. Note that this method is not to perform any network - * operations and will simply return the status received in the last - * status update message. If you want a reliable way of retrieving someone's - * status, you should use the queryContactStatus() method in - * OperationSetPresence. - * @return the PresenceStatus that we've received in the last status update - * pertaining to this contact. - */ - public PresenceStatus getPresenceStatus() - { - return status; - } - - /** - * Returns a String that could be used by any user interacting modules for - * referring to this contact. An alias is not necessarily unique but is - * often more human readable than an address (or id). - * @return a String that can be used for referring to this contact when - * interacting with the user. - */ - public String getDisplayName() - { - return getAddress(); - } - - /** - * Returns a reference to the contact group that this contact is currently - * a child of or null if the underlying protocol does not suppord persistent - * presence. - * @return a reference to the contact group that this contact is currently - * a child of or null if the underlying protocol does not suppord persistent - * presence. - */ - public ContactGroup getParentContactGroup() - { - return ssclCallback.findContactGroup(this); - } - - - /** - * Returns a reference to the protocol provider that created the contact. - * @return a refererence to an instance of the ProtocolProviderService - */ - public ProtocolProviderService getProtocolProvider() - { - return ssclCallback.getParentProvider(); - } - - /** - * Determines whether or not this contact is being stored by the server. - * Non persistent contacts are common in the case of simple, non-persistent - * presence operation sets. They could however also be seen in persistent - * presence operation sets when for example we have received an event - * from someone not on our contact list. Non persistent contacts are - * volatile even when coming from a persistent presence op. set. They would - * only exist until the application is closed and will not be there next - * time it is loaded. - * @return true if the contact is persistent and false otherwise. - */ - public boolean isPersistent() - { - return isPersistent; - } - - /** - * Specifies whether this contact is to be considered persistent or not. The - * method is to be used _only_ when a non-persistent contact has been added - * to the contact list and its encapsulated VolatileBuddy has been repalced - * with a standard buddy. - * @param persistent true if the buddy is to be considered persistent and - * false for volatile. - */ - void setPersistent(boolean persistent) - { - this.isPersistent = persistent; - } - - /** - * Resolve this contact against the given entry - * @param entry the server stored entry - */ - void setResolved(YahooUser entry) - { - if(isResolved) - return; - - this.isResolved = true; - contact = entry; - isVolatile = false; - } - - /** - * Returns the persistent data - * @return the persistent data - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this contact has been resolved against the - * server. Unresolved contacts are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped contacts to their on-line buddies. - * @return true if the contact has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - public void setPersistentData(String persistentData) - { - } - - /** - * Get source contact - * @return YahooContact - */ - YahooUser getSourceContact() - { - return contact; - } - - /** - * Return the current status message of this contact. - * - * @return the current status message - */ - public String getStatusMessage() - { - return statusMessage; - } - - /** - * Sets the current status message for this contact - * @param statusMessage the message - */ - protected void setStatusMessage(String statusMessage) - { - this.statusMessage = statusMessage; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/FileTransferImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/FileTransferImpl.java deleted file mode 100644 index 3f42079..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/FileTransferImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Filetransfer imeplementation for yahoo. - * @author Damian Minkov - */ -public class FileTransferImpl - extends AbstractFileTransfer - -{ - private ProtocolProviderServiceYahooImpl yahooProvider; - private String id = null; - private Contact contact = null; - private File file = null; - private int direction = -1; - private long transferedBytes; - - public FileTransferImpl(ProtocolProviderServiceYahooImpl yahooProvider, - String id, Contact contact, File file, int direction) - { - this.yahooProvider = yahooProvider; - this.id = id; - this.contact = contact; - this.file = file; - this.direction = direction; - } - - /** - * Cancels this file transfer. When this method is called transfer should - * be interrupted. - */ - @Override - public void cancel() - { - yahooProvider.getYahooSession().cancelRunningFileTransfer(id); - } - - /** - * Returns the number of bytes already transfered through this file transfer. - * - * @return the number of bytes already transfered through this file transfer - */ - @Override - public long getTransferedBytes() - { - return transferedBytes; - } - - /** - * Uniquie ID that is identifying the FileTransfer - * if the request has been accepted. - * - * @return the id. - */ - public String getID() - { - return id; - } - - /** - * The file transfer direction. - * @return returns the direction of the file transfer : IN or OUT. - */ - public int getDirection() - { - return direction; - } - - /** - * Returns the file that is transfered. - * - * @return the file - */ - public File getLocalFile() - { - return file; - } - - /** - * Returns the contact that we are transfering files with. - * @return the contact. - */ - public Contact getContact() - { - return contact; - } - - /** - * @param transferedBytes the transferedBytes to set - */ - public void setTransferedBytes(long transferedBytes) - { - this.transferedBytes = transferedBytes; - } - -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/IncomingFileTransferRequestYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/IncomingFileTransferRequestYahooImpl.java deleted file mode 100644 index 25561d0..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/IncomingFileTransferRequestYahooImpl.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; - -/** - * Implementation of the incoming file transfer request. - * - * @author Damian Minkov - */ -public class IncomingFileTransferRequestYahooImpl - implements IncomingFileTransferRequest -{ - private String id; - - /** - * The yahoo provider. - */ - private ProtocolProviderServiceYahooImpl yahooProvider; - - private final OperationSetFileTransferYahooImpl fileTransferOpSet; - - private Contact sender; - - private Date date; - - private String fileName; - - private long fileSize; - - public IncomingFileTransferRequestYahooImpl( - ProtocolProviderServiceYahooImpl yahooProvider, - OperationSetFileTransferYahooImpl fileTransferOpSet, - Contact sender, - Date date, - String fileName, - String fileSize, - String id) - { - this.yahooProvider = yahooProvider; - this.fileTransferOpSet = fileTransferOpSet; - this.sender = sender; - this.date = date; - this.fileName = fileName; - - try - { - this.fileSize = Long.valueOf(fileSize); - } - catch (NumberFormatException e) - {} - - this.id = id; - } - - /** - * Unique ID that is identifying the request and then the FileTransfer - * if the request has been accepted. - * - * @return the id. - */ - public String getID() - { - return id; - } - - /** - * Returns a String that represents the name of the file that is being - * received. - * If there is no name, returns null. - * @return a String that represents the name of the file - */ - public String getFileName() - { - return fileName; - } - - /** - * Returns a String that represents the description of the file that is - * being received. - * If there is no description available, returns null. - * - * @return a String that represents the description of the file - */ - public String getFileDescription() - { - return ""; - } - - /** - * Returns a long that represents the size of the file that is being - * received. - * If there is no file size available, returns null. - * - * @return a long that represents the size of the file - */ - public long getFileSize() - { - return fileSize; - } - - /** - * Returns a String that represents the name of the sender of the file - * being received. - * If there is no sender name available, returns null. - * - * @return a String that represents the name of the sender - */ - public Contact getSender() - { - return sender; - } - - /** - * Function called to accept and receive the file. - * - * @param file the file to accept - * @return the FileTransfer object managing the transfer - */ - public FileTransfer acceptFile(File file) - { - AbstractFileTransfer incomingTransfer = null; - - incomingTransfer = - new FileTransferImpl(yahooProvider, - id, sender, file, FileTransfer.IN); - - yahooProvider.getYahooSession().fileTransferAccept(id, file); - - FileTransferCreatedEvent event - = new FileTransferCreatedEvent(incomingTransfer, new Date()); - - fileTransferOpSet.fireFileTransferCreated(event); - - incomingTransfer.fireStatusChangeEvent( - FileTransferStatusChangeEvent.PREPARING); - - return incomingTransfer; - } - - /** - * Function called to refuse the file. - */ - public void rejectFile() - { - yahooProvider.getYahooSession().fileTransferReject(id); - - fileTransferOpSet.fireFileTransferRequestRejected( - new FileTransferRequestEvent( - fileTransferOpSet, this, this.getDate())); - } - - /** - * @return the date - */ - public Date getDate() - { - return date; - } - - /** - * Returns the thumbnail contained in this request. - * - * @return the thumbnail contained in this request - */ - public byte[] getThumbnail() - { - return null; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/MessageYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/MessageYahooImpl.java deleted file mode 100644 index e35a3c1..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/MessageYahooImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; - -/** - * A simple implementation of the Message interface. Right now the - * message only supports test contents and no binary data. - * - * @author Damian Minkov - * @author Lubomir Marinov - */ -public class MessageYahooImpl - extends AbstractMessage -{ - - /** - * Creates an instance of this Message with the specified parameters. - * - * @param content the text content of the message. - * @param contentType a MIME string indicating the content type of the - * content String. - * @param contentEncoding a MIME String indicating the content encoding of - * the content String. - * @param subject the subject of the message or null for empty. - */ - public MessageYahooImpl(String content, String contentType, - String contentEncoding, String subject) - { - super(content, contentType, contentEncoding, subject); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetAdHocMultiUserChatYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetAdHocMultiUserChatYahooImpl.java deleted file mode 100644 index dd5f73f..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetAdHocMultiUserChatYahooImpl.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; -import ymsg.network.event.*; - -/** - * A Yahoo implementation of the ad-hoc multi user chat operation set. - * - * @author Rupert Burchardi - * @author Valentin Martinet - * @author Yana Stamcheva - */ -public class OperationSetAdHocMultiUserChatYahooImpl -implements OperationSetAdHocMultiUserChat -{ - private static final Logger logger = - Logger.getLogger(OperationSetAdHocMultiUserChatYahooImpl.class); - - /** - * A list of listeners subscribed for invitations multi user chat events. - */ - private final List invitationListeners - = new Vector(); - - /** - * A list of listeners subscribed for events indicating rejection of a multi - * user chat invitation sent by us. - */ - private final List - invitationRejectionListeners - = new Vector(); - - /** - * Listeners that will be notified of changes in our status in the room such - * as us being kicked, banned, or granted admin permissions. - */ - private final List presenceListeners - = new Vector(); - - /** - * A list of the rooms that are currently open by this account. - */ - private final Hashtable chatRoomCache - = new Hashtable(); - - /** - * The currently valid Yahoo protocol provider service implementation. - */ - private final ProtocolProviderServiceYahooImpl yahooProvider; - - /** - * The operation set for the basic instant messaging, provides some message - * format functions. - */ - private final OperationSetBasicInstantMessagingYahooImpl opSetBasic; - - /** - * Instantiates the user operation set with a currently valid instance of - * the Yahoo protocol provider. - * - * @param yahooProvider a currently valid instance of - * ProtocolProviderServiceYahooImpl. - */ - OperationSetAdHocMultiUserChatYahooImpl( - ProtocolProviderServiceYahooImpl yahooProvider) - { - this.yahooProvider = yahooProvider; - - yahooProvider - .addRegistrationStateChangeListener(new RegistrationStateListener()); - - opSetBasic = - (OperationSetBasicInstantMessagingYahooImpl) yahooProvider - .getOperationSet(OperationSetBasicInstantMessaging.class); - } - - /** - * Adds a listener to invitation notifications. - * - * @param listener An invitation listener. - */ - public void addInvitationListener(AdHocChatRoomInvitationListener listener) - { - synchronized (invitationListeners) - { - if (!invitationListeners.contains(listener)) - invitationListeners.add(listener); - } - } - - /** - * Removes a listener that was being notified of changes in our status in a - * room such as us being kicked, banned or dropped. - * - * @param listener the LocalUserAdHocChatRoomPresenceListener. - */ - public void removeInvitationListener( - AdHocChatRoomInvitationListener listener) - { - synchronized (invitationListeners) - { - invitationListeners.remove(listener); - } - } - - /** - * Subscribes listener so that it would receive events indicating - * rejection of a multi user chat invitation that we've sent earlier. - * - * @param listener the listener that we'll subscribe for invitation - * rejection events. - */ - - public void addInvitationRejectionListener( - AdHocChatRoomInvitationRejectionListener listener) - { - synchronized (invitationRejectionListeners) - { - if (!invitationRejectionListeners.contains(listener)) - invitationRejectionListeners.add(listener); - } - } - - /** - * Removes listener from the list of invitation listeners - * registered to receive invitation rejection events. - * - * @param listener the invitation listener to remove. - */ - public void removeInvitationRejectionListener( - AdHocChatRoomInvitationRejectionListener listener) - { - synchronized (invitationRejectionListeners) - { - invitationRejectionListeners.remove(listener); - } - } - - /** - * Adds a listener that will be notified of changes in our status in a chat - * room such as us being kicked, banned or dropped. - * - * @param listener the LocalUserAdHocChatRoomPresenceListener. - */ - public void addPresenceListener( - LocalUserAdHocChatRoomPresenceListener listener) - { - synchronized (presenceListeners) - { - if (!presenceListeners.contains(listener)) - presenceListeners.add(listener); - } - } - - /** - * Removes a listener that was being notified of changes in our status in a - * room such as us being kicked, banned or dropped. - * - * @param listener the LocalUserChatRoomPresenceListener. - */ - public void removePresenceListener( - LocalUserAdHocChatRoomPresenceListener listener) - { - synchronized (presenceListeners) - { - presenceListeners.remove(listener); - } - } - - /** - * Creates a room with the named roomName and according to the - * specified roomProperties on the server that this protocol - * provider is currently connected to. Note the roomProperties also contain - * users that we like to invite to the chatRoom, this is required in the - * yahoo protocol. - * - * @param roomName the name of the AdHocChatRoom to create. - * @param roomProperties properties specifying how the room should be - * created. - * - * @throws OperationFailedException if the room couldn't be created for some - * reason (e.g. room already exists; user already joined to an - * existent room or user has no permissions to create a chat - * room). - * - * @return ChatRoom the chat room that we've just created. - */ - public AdHocChatRoom createAdHocChatRoom(String roomName, - Map roomProperties) - throws OperationFailedException - { - return createAdHocChatRoom(roomName, (String[]) null, ""); - } - - /** - * Creates an ad-hoc room with the named adHocRoomName and in - * including to the specified contacts. When the method returns the - * ad-hoc room the local user will have joined it. - * - * @return the ad-hoc room that has been just created - * @param adHocRoomName the name of the room to be created - * @param contacts the list of contacts ID - * @param reason the reason for contacts' invitation - * @throws OperationFailedException if the room couldn't be created for - * some reason - */ - public AdHocChatRoom createAdHocChatRoom( String adHocRoomName, - List contacts, - String reason) - throws OperationFailedException - { - String[] contactsToInvite = new String[contacts.size()]; - for(int i=0; iadHocRoomName and in - * including to the specified contacts. When the method returns the - * ad-hoc room the local user will have joined it. - * - * @param roomName name of the chatroom - * @param invitedContacts contacts to be invited to this room - * @param reason reason of this invitation - * @return AdHocChatRoom the ad-hoc room that has been just created - * @throws OperationFailedException - */ - private AdHocChatRoom createAdHocChatRoom( - String roomName, - String[] invitedContacts, - String reason) - throws OperationFailedException - { - if (invitedContacts == null) - invitedContacts = new String[0]; - - AdHocChatRoom chatRoom = null; - - try - { - YahooConference conference = - yahooProvider.getYahooSession().createConference( - invitedContacts, // users invited to this conference - reason, // invite message / topic - yahooProvider.getYahooSession().getLoginIdentity()); - - chatRoom = createLocalChatRoomInstance(conference); - } - catch (Exception e) - { - String errorMessage - = "Failed to create chat room with name: " + roomName; - - if (logger.isDebugEnabled()) - logger.debug(errorMessage, e); - throw new OperationFailedException(errorMessage, - OperationFailedException.CHAT_ROOM_NOT_JOINED, e); - } - chatRoom.join(); - return chatRoom; - } - - /** - * Creates a AdHocChatRoom instance from the specified Yahoo - * conference. - * - * @param yahooConference The chat room model from the yahoo lib. - * - * @return AdHocChatRoom the chat room that we've just created. - */ - private AdHocChatRoomYahooImpl createLocalChatRoomInstance( - YahooConference yahooConference) - { - synchronized (chatRoomCache) - { - AdHocChatRoomYahooImpl newChatRoom - = new AdHocChatRoomYahooImpl(yahooConference, yahooProvider); - - chatRoomCache.put(yahooConference.getName(), newChatRoom); - - return newChatRoom; - } - } - - /** - * Creates a AdHocChatRoom instance (where the inviter is - * represented by inviterID parameter) from the specified Yahoo conference. - * - * @param yahooConference The chat room model from the yahoo lib. - * @param inviterID inviter's Yahoo ID which has to be added as room member - * - * @return AdHocChatRoom the chat room that we've just created. - */ - private AdHocChatRoomYahooImpl createLocalChatRoomInstance( - YahooConference yahooConference, String inviterID) - { - synchronized (chatRoomCache) - { - AdHocChatRoomYahooImpl newChatRoom - = new AdHocChatRoomYahooImpl(yahooConference, yahooProvider); - - OperationSetPersistentPresenceYahooImpl opSetPresence = - (OperationSetPersistentPresenceYahooImpl) yahooProvider - .getOperationSet(OperationSetPersistentPresence.class); - - newChatRoom.addChatRoomParticipant( - opSetPresence.findContactByID(inviterID)); - chatRoomCache.put(yahooConference.getName(), newChatRoom); - - return newChatRoom; - } - } - - /** - * Returns the AdHocChatRoomYahooImpl corresponding to the given - * conference if such exists, otherwise returns null. - * - * @param conference the YahooConference, for which we're searching - * correspondence - * @return the AdHocChatRoomYahooImpl corresponding to the given - * conference if such exists, otherwise returns null - */ - private AdHocChatRoomYahooImpl getLocalChatRoomInstance( - YahooConference conference) - { - synchronized (chatRoomCache) - { - for (AdHocChatRoomYahooImpl chatRoom : chatRoomCache.values()) - { - if (chatRoom.getYahooConference().equals(conference)) - return chatRoom; - } - } - - return null; - } - - /** - * Informs the sender of an invitation that we decline their invitation. - * - * @param invitation the connection to use for sending the rejection. - * @param rejectReason the reason to reject the given invitation - */ - public void rejectInvitation(AdHocChatRoomInvitation invitation, - String rejectReason) - { - AdHocChatRoomYahooImpl chatRoom = - (AdHocChatRoomYahooImpl) invitation.getTargetAdHocChatRoom(); - - try - { - yahooProvider.getYahooSession().declineConferenceInvite( - chatRoom.getYahooConference(), rejectReason); - } - catch (IOException e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to reject Invitation: " + e); - } - } - - /** - * Delivers a AdHocChatRoomInvitationReceivedEvent to all - * registered AdHocChatRoomInvitationListeners. - * - * @param targetChatRoom the room that invitation refers to - * @param inviter the inviter that sent the invitation - * @param reason the reason why the inviter sent the invitation - */ - public void fireInvitationEvent(AdHocChatRoom targetChatRoom, - String inviter, String reason) - { - AdHocChatRoomInvitationYahooImpl invitation = - new AdHocChatRoomInvitationYahooImpl(targetChatRoom, inviter, - reason); - - AdHocChatRoomInvitationReceivedEvent evt = - new AdHocChatRoomInvitationReceivedEvent(this, invitation, - new Date(System.currentTimeMillis())); - - Iterable listeners; - synchronized (invitationListeners) - { - listeners - = new ArrayList( - invitationListeners); - } - - for (AdHocChatRoomInvitationListener listener : listeners) - listener.invitationReceived(evt); - } - - /** - * Delivers a AdHocChatRoomInvitationRejectedEvent to all - * registered AdHocChatRoomInvitationRejectionListeners. - * - * @param sourceChatRoom the room that invitation refers to - * @param invitee the name of the invitee that rejected the invitation - * @param reason the reason of the rejection - */ - public void fireInvitationRejectedEvent(AdHocChatRoom sourceChatRoom, - String invitee, String reason) - { - AdHocChatRoomInvitationRejectedEvent evt = - new AdHocChatRoomInvitationRejectedEvent( - this, sourceChatRoom, invitee, - reason, new Date(System.currentTimeMillis())); - - Iterable listeners; - synchronized (invitationRejectionListeners) - { - listeners - = new ArrayList( - invitationRejectionListeners); - } - - for (AdHocChatRoomInvitationRejectionListener listener : listeners) - listener.invitationRejected(evt); - } - - /** - * Delivers a LocalUserAdHocChatRoomPresenceChangeEvent to all - * registered LocalUserAdHocChatRoomPresenceListeners. - * - * @param chatRoom the ChatRoom which has been joined, left, etc. - * @param eventType the type of this event; one of LOCAL_USER_JOINED, - * LOCAL_USER_LEFT, etc. - * @param reason the reason - */ - public void fireLocalUserPresenceEvent(AdHocChatRoom chatRoom, - String eventType, String reason) - { - LocalUserAdHocChatRoomPresenceChangeEvent evt = - new LocalUserAdHocChatRoomPresenceChangeEvent( - this, chatRoom, eventType, - reason); - - Iterable listeners; - synchronized (presenceListeners) - { - listeners = - new ArrayList( - presenceListeners); - } - - for (LocalUserAdHocChatRoomPresenceListener listener : listeners) - listener.localUserAdHocPresenceChanged(evt); - } - - /** - * Create a Message instance for sending arbitrary MIME-encoding content. - * - * @param content content value - * @param contentType the MIME-type for content - * @param contentEncoding encoding used for content - * @param subject a String subject or null for now - * subject. - * @return the newly created message. - * @throws UnsupportedEncodingException missing utf-8 in platform we use. - */ - private Message createMessage(byte[] content, String contentType, - String contentEncoding, String subject) - throws UnsupportedEncodingException - { - return new MessageYahooImpl(new String(content, "UTF-8"), contentType, - contentEncoding, subject); - } - - /** - * Creates a message by a given message text. - * - * @param messageText The message text. - * @return the newly created message. - */ - public Message createMessage(String messageText) - { - return new MessageYahooImpl(messageText, - OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE, - OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, null); - } - - /** - * Our listener that will tell us when we're registered to yahoo network. - * - */ - private class RegistrationStateListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenever a - * change in the registration state of the corresponding provider had - * occurred. - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (evt.getNewState() == RegistrationState.REGISTERED) - { - yahooProvider.getYahooSession().addSessionListener( - new YahooMessageListener()); - } - } - } - - /** - * Our group chat message listener, it extends the SessionAdapter from the - * the Yahoo library. - * - */ - private class YahooMessageListener - extends SessionAdapter - { - - @Override - public void conferenceInviteDeclinedReceived(SessionConferenceEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Group Chat invite declined received. " - + ev.toString()); - try - { - AdHocChatRoom chatRoom = getLocalChatRoomInstance(ev.getRoom()); - - fireInvitationRejectedEvent(chatRoom, ev.getFrom(), ev - .getMessage()); - } - catch (Exception e) - { - if (logger.isDebugEnabled()) - logger.debug("Error: " + e); - } - } - - @Override - public void conferenceInviteReceived(SessionConferenceEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Conference Invite Received: " + ev.toString()); - - try - { - AdHocChatRoom chatRoom = getLocalChatRoomInstance(ev.getRoom()); - - if (chatRoom == null) - { - chatRoom = - createLocalChatRoomInstance(ev.getRoom(), ev.getFrom()); - - fireInvitationEvent( - chatRoom, ev.getFrom(), ev.getMessage()); - } - - } - catch (Exception e) - { - if (logger.isDebugEnabled()) - logger.debug("Error: " + e); - } - } - - @Override - public void conferenceLogoffReceived(SessionConferenceEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Conference Logoff Received: " + ev.toString()); - - try - { - AdHocChatRoomYahooImpl chatRoom - = getLocalChatRoomInstance(ev.getRoom()); - - if (chatRoom != null) - { - Contact participant = - chatRoom.findParticipantForAddress(ev.getFrom()); - - chatRoom.removeChatRoomParticipant(participant); - } - } - catch (Exception e) - { - logger - .debug("Failed to remove a user from the chat room. " + e); - } - } - - @Override - public void conferenceLogonReceived(SessionConferenceEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Conference Logon Received: " + ev.toString()); - - try - { - AdHocChatRoomYahooImpl chatRoom - = getLocalChatRoomInstance(ev.getRoom()); - - if (chatRoom != null) - { - OperationSetPersistentPresenceYahooImpl presenceOpSet = - (OperationSetPersistentPresenceYahooImpl) chatRoom - .getParentProvider().getOperationSet( - OperationSetPersistentPresence.class); - - Contact participant = - presenceOpSet.findContactByID(ev.getFrom()); - - chatRoom.addChatRoomParticipant(participant); - } - } - catch (Exception e) - { - if (logger.isDebugEnabled()) - logger.debug("Failed to add a user to the chat room. " + e); - } - } - - @Override - public void conferenceMessageReceived(SessionConferenceEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Conference Message Received: " + ev.toString()); - - try - { - String formattedMessage = ev.getMessage(); - if (logger.isDebugEnabled()) - logger.debug("original message received : " + formattedMessage); - - formattedMessage = opSetBasic.decodeMessage(formattedMessage); - if (logger.isDebugEnabled()) - logger.debug("formatted Message : " + formattedMessage); - // As no indications in the protocol is it html or not. No harm - // to set all messages html - doesn't affect the appearance of - // the gui - - Message newMessage = - createMessage( - formattedMessage.getBytes("UTF-8"), - OperationSetBasicInstantMessaging.HTML_MIME_TYPE, - OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING, - null); - - AdHocChatRoomYahooImpl chatRoom = - getLocalChatRoomInstance(ev.getRoom()); - - if (chatRoom != null) - { - Contact member = - chatRoom.findParticipantForAddress(ev.getFrom()); - - AdHocChatRoomMessageReceivedEvent msgReceivedEvent = - new AdHocChatRoomMessageReceivedEvent( - chatRoom, - member, - new Date(), - newMessage, - AdHocChatRoomMessageReceivedEvent - .CONVERSATION_MESSAGE_RECEIVED); - - chatRoom.fireMessageEvent(msgReceivedEvent); - } - } - catch (Exception e) - { - logger - .debug("Error while receiving a multi user chat message: " - + e); - } - - } - - @Override - public void connectionClosed(SessionEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Connection Closed: " + ev.toString()); - } - } - - public List getAdHocChatRooms() - { - return new ArrayList(chatRoomCache.values()); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java deleted file mode 100644 index 84059de..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetBasicInstantMessagingYahooImpl.java +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; -import java.util.regex.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.event.*; -import ymsg.support.*; - -/** - * A straightforward implementation of the basic instant messaging operation - * set. - * - * @author Damian Minkov - * @author Symphorien Wanko - * @author Keio Kraaner - */ -public class OperationSetBasicInstantMessagingYahooImpl - extends AbstractOperationSetBasicInstantMessaging - implements OperationSetInstantMessageFiltering -{ - /** - * Logger for this class - */ - private static final Logger logger = - Logger.getLogger(OperationSetBasicInstantMessagingYahooImpl.class); - - /** - * Yahoo has limit of message length. If exceeded - * message is not delivered and no notification is received for that. - */ - private static final int MAX_MESSAGE_LENGTH = 800; // 949 - - /** - * A regexp that is used to escape some chars in messages. - */ - private static final Pattern MESSAGE_CHARS_ESCAPE = Pattern.compile("([.()^&$*|])"); - - /** - * A list of filters registered for message events. - */ - private final List eventFilters = new ArrayList(); - - /** - * The provider that created us. - */ - private ProtocolProviderServiceYahooImpl yahooProvider = null; - - /** - * Message decoder allows to convert Yahoo formated messages, which can - * contains some specials characters, to HTML or to plain text. - */ - private final MessageDecoder messageDecoder = new MessageDecoder(); - - /** - * A reference to the persistent presence operation set that we use - * to match incoming messages to Contacts and vice versa. - */ - private OperationSetPersistentPresenceYahooImpl opSetPersPresence = null; - private static final Pattern FONT_SIZE_0_PATTERN = Pattern.compile("("); - private static final Pattern FONT_SIZE_INT_PATTERN = Pattern.compile("("); - - /** - * Creates an instance of this operation set. - * @param provider a ref to the ProtocolProviderServiceImpl - * that created us and that we'll use for retrieving the underlying aim - * connection. - */ - OperationSetBasicInstantMessagingYahooImpl( - ProtocolProviderServiceYahooImpl provider) - { - this.yahooProvider = provider; - provider.addRegistrationStateChangeListener( - new RegistrationStateListener()); - } - - /** - * Determines wheter the protocol provider (or the protocol itself) support - * sending and receiving offline messages. Most often this method would - * return true for protocols that support offline messages and false for - * those that don't. It is however possible for a protocol to support these - * messages and yet have a particular account that does not (i.e. feature - * not enabled on the protocol server). In cases like this it is possible - * for this method to return true even when offline messaging is not - * supported, and then have the sendMessage method throw an - * OperationFailedException with code - OFFLINE_MESSAGES_NOT_SUPPORTED. - * - * @return true if the protocol supports offline messages and - * false otherwise. - */ - public boolean isOfflineMessagingSupported() - { - return true; - } - - /** - * Determines wheter the protocol supports the supplied content type - * - * @param contentType the type we want to check - * @return true if the protocol supports it and - * false otherwise. - */ - public boolean isContentTypeSupported(String contentType) - { - if(contentType.equals(DEFAULT_MIME_TYPE) || - contentType.equals(HTML_MIME_TYPE)) - return true; - else - return false; - } - - @Override - public Message createMessage(String content, String contentType, - String encoding, String subject) - { - return new MessageYahooImpl(content, contentType, encoding, subject); - } - - /** - * Sends the message to the destination indicated by the - * to contact. - * - * @param to the Contact to send message to - * @param message the Message to send. - * @throws IllegalStateException if the underlying stack is - * not registered and initialized. - * @throws IllegalArgumentException if to is not an - * instance of ContactImpl. - */ - public void sendInstantMessage(Contact to, Message message) - throws IllegalStateException, IllegalArgumentException - { - assertConnected(); - - if( !(to instanceof ContactYahooImpl) ) - throw new IllegalArgumentException( - "The specified contact is not a Yahoo contact." - + to); - - try - { - String toUserID = ((ContactYahooImpl) to).getID(); - - MessageDeliveredEvent msgDeliveryPendingEvt = - new MessageDeliveredEvent(message, to, new Date()); - - MessageDeliveredEvent[] msgDeliveryPendingEvts = messageDeliveryPendingTransform(msgDeliveryPendingEvt); - - if (msgDeliveryPendingEvts == null || msgDeliveryPendingEvts.length == 0) - return; - - for (MessageDeliveredEvent event : msgDeliveryPendingEvts) - { - byte[] msgBytesToBeSent = - event.getSourceMessage().getContent().trim() - .getBytes("UTF-8"); - - // split the message in parts with max allowed length - // and send them all - do - { - if (msgBytesToBeSent.length > MAX_MESSAGE_LENGTH) - { - byte[] tmp1 = new byte[MAX_MESSAGE_LENGTH]; - System.arraycopy(msgBytesToBeSent, 0, tmp1, 0, - MAX_MESSAGE_LENGTH); - - byte[] tmp2 = - new byte[msgBytesToBeSent.length - - MAX_MESSAGE_LENGTH]; - System.arraycopy(msgBytesToBeSent, MAX_MESSAGE_LENGTH, - tmp2, 0, tmp2.length); - - msgBytesToBeSent = tmp2; - - yahooProvider.getYahooSession().sendMessage(toUserID, - new String(tmp1, "UTF-8")); - } - else - { - yahooProvider.getYahooSession().sendMessage(toUserID, - new String(msgBytesToBeSent, "UTF-8")); - } - - MessageDeliveredEvent msgDeliveredEvt = - new MessageDeliveredEvent(message, to, new Date()); - - if (msgDeliveredEvt != null) - fireMessageEvent(msgDeliveredEvt); - } - while (msgBytesToBeSent.length > MAX_MESSAGE_LENGTH); - } - } - catch (IOException ex) - { - logger.fatal("Cannot Send Message! " + ex.getMessage()); - MessageDeliveryFailedEvent evt = - new MessageDeliveryFailedEvent( - message, - to, - MessageDeliveryFailedEvent.NETWORK_FAILURE); - - if (evt != null) - fireMessageEvent(evt); - } - } - - /** - * Utility method throwing an exception if the stack is not properly - * initialized. - * @throws IllegalStateException if the underlying stack is - * not registered and initialized. - */ - private void assertConnected() throws IllegalStateException - { - if (yahooProvider == null) - throw new IllegalStateException( - "The provider must be non-null and signed on the " - +"service before being able to communicate."); - if (!yahooProvider.isRegistered()) - throw new IllegalStateException( - "The provider must be signed on the service before " - +"being able to communicate."); - } - - /** - * Our listener that will tell us when we're registered to - */ - private class RegistrationStateListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenver - * a change in the registration state of the corresponding provider had - * occurred. - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (logger.isDebugEnabled()) - logger.debug("The provider changed state from: " - + evt.getOldState() - + " to: " + evt.getNewState()); - - if (evt.getNewState() == RegistrationState.REGISTERED) - { - opSetPersPresence = - (OperationSetPersistentPresenceYahooImpl) yahooProvider - .getOperationSet(OperationSetPersistentPresence.class); - - yahooProvider.getYahooSession(). - addSessionListener(new YahooMessageListener()); - } - } - } - - /** - * Delivers the specified event to all registered message listeners. - * @param evt the EventObject that we'd like delivered to all - * registered message listerners. - */ - @Override - protected void fireMessageEvent(EventObject evt) - { - // check if this event should be filtered out - Iterator filters; - synchronized (eventFilters) - { - filters = new ArrayList(eventFilters).iterator(); - } - // return if a filter has filtered this event out - boolean filtered = false; - while (filters.hasNext()) - { - try - { - if (filters.next().filterEvent(evt)) - { - filtered = true; - } - } - catch(Exception exc) - { - logger.error("An exception occurred while filtering an event.", - exc); - } - } - - if (filtered) - { - if (logger.isTraceEnabled()) - logger.trace("Message event filtered."); - return; - } - - super.fireMessageEvent(evt); - } - - /** - * This class provides methods to listen for yahoo events which interest us. - */ - private class YahooMessageListener - extends SessionAdapter - { - /** - * Overrides messageReceived from SessionAdapter, - * called when we receive a new intant message. - * - * @param ev Event with information on the received message - */ - @Override - public void messageReceived(SessionEvent ev) - { - handleNewMessage(ev); - } - - /** - * Overrides offlineMessageReceived from SessionAdapter, - * called when we receive a message which has been sent to us - * when we were offline. - * - * @param ev Event with information on the received message - */ - @Override - public void offlineMessageReceived(SessionEvent ev) - { - handleNewMessage(ev); - } - - /** - * Overrides newMailReceived from SessionAdapter, - * called when yahoo alert us that there is a new message in our mailbox. - * There is two types of notification, the first one provides only - * the number of unread mails and the second gives informations about - * a precise new mail. Here, we care about only the second case in which - * we should always have the email of the sender of the mail. - * - * @param ev Event with information on the received email - */ - @Override - public void newMailReceived(SessionNewMailEvent ev) - { - // why, if I provide mail@yahoo.FR when registering my account, - // SC later tells me that my email address is mail@yahoo.COM ?? - // because of this users will always be sent on yahoo.com mail - // login page rather than their usual (yahoo.XXX) login page. - String myEmail = yahooProvider.getAccountID().getAccountAddress(); - - // we don't process incoming email event without source address. - // it allows us to avoid some spams - if ((ev.getEmailAddress() == null) - || (ev.getEmailAddress().indexOf('@') < 0)) - { - return; - } - - String yahooMailLogon = "http://mail." - + myEmail.substring(myEmail.indexOf('@') + 1); - - yahooMailLogon = "    " - + yahooMailLogon + ""; - - // FIXME Escape HTML! - String newMail = YahooActivator.getResources().getI18NString( - "service.gui.NEW_MAIL", - new String[]{ev.getFrom(), - "<" + ev.getEmailAddress() + ">", - ev.getSubject(), - "    "+yahooMailLogon}) ; - - Message newMailMessage = new MessageYahooImpl( - newMail, - HTML_MIME_TYPE, - DEFAULT_MIME_ENCODING, - null); - - Contact sourceContact = opSetPersPresence. - findContactByID(ev.getEmailAddress()); - - if (sourceContact == null) - { - if (logger.isDebugEnabled()) - logger.debug("received a new mail from an unknown contact: " - + ev.getFrom() - + " <" + ev.getEmailAddress() + ">"); - //create the volatile contact - sourceContact = opSetPersPresence - .createVolatileContact(ev.getEmailAddress()); - } - MessageReceivedEvent msgReceivedEvt - = new MessageReceivedEvent( - newMailMessage, sourceContact, new Date(), - MessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED); - - fireMessageEvent(msgReceivedEvt); - } - - /** - * Handle incoming message by creating an appropriate Sip Communicator - * Message and firing a MessageReceivedEvent - * to interested listeners. - * - * @param ev The original SessionEvent which noticed us - * of an incoming message. - */ - private void handleNewMessage(SessionEvent ev) - { - if (logger.isDebugEnabled()) - logger.debug("Message received : " + ev); - - // to keep things simple, we can decodeToText() - //String formattedMessage = processLinks( - // messageDecoder.decodeToText(ev.getMessage())); - - String formattedMessage = ev.getMessage(); - if (logger.isDebugEnabled()) - logger.debug("original message received : " + formattedMessage); - - formattedMessage = decodeMessage(formattedMessage); - - if (logger.isDebugEnabled()) - logger.debug("formatted Message : " + formattedMessage); - // As no indications in the protocol is it html or not. No harm - // to set all messages html - doesn't affect the appearance of the - // gui - Message newMessage = - createMessage(formattedMessage, HTML_MIME_TYPE, - DEFAULT_MIME_ENCODING, null); - - Contact sourceContact = opSetPersPresence. - findContactByID(ev.getFrom()); - - if(sourceContact == null) - { - if (logger.isDebugEnabled()) - logger.debug("received a message from an unknown contact: " - + ev.getFrom()); - //create the volatile contact - sourceContact = opSetPersPresence - .createVolatileContact(ev.getFrom()); - } - - MessageReceivedEvent msgReceivedEvt - = new MessageReceivedEvent( - newMessage, sourceContact , new Date()); - - // msgReceivedEvt = messageReceivedTransform(msgReceivedEvt); - - if (msgReceivedEvt != null) - fireMessageEvent(msgReceivedEvt); - } - } - - /** - * Decode the received chat message. - * If the message contains \u001b the following text is decoded by - * the MessageDecoder of yahoo api - * Then make http links clickable and fix the font size of html code - * - * @param message the chat message - * @return a decoded message. - */ - String decodeMessage(String message) - { - message = messageDecoder.decodeToHTML(message); - message = processLinks(message); - message = - FONT_SIZE_0_PATTERN.matcher(message) - .replaceAll("$1 $2 size=\"10\">"); - message = - FONT_SIZE_INT_PATTERN.matcher(message) - .replaceAll("$1 $2 style=\"font-size: $3px;\">"); - return message; - } - - /** - * Format links in the given message. Skips all links, which are already in - * HTML format and converts all other links. - * - * @param message The source message string. - * @return The message string with properly formatted links. - */ - public String processLinks(String message) - { - StringBuffer msgBuffer = new StringBuffer(); - - // We match two groups of Strings. The first group is the group of any - // String. The second group is a well formatted HTML link. - Pattern p = Pattern.compile("(.*?)(|))", - Pattern.CASE_INSENSITIVE); - - Matcher m = p.matcher(message); - - int lastMatchIndex = 0; - while (m.find()) - { - lastMatchIndex = m.end(); - - String matchGroup1 = m.group(1); - String matchGroup2 = m.group(2); - - String formattedString = formatLinksToHTML(matchGroup1); - - m.appendReplacement(msgBuffer, - replaceSpecialRegExpChars(formattedString) + matchGroup2); - } - - String tailString = message.substring(lastMatchIndex); - - String formattedTailString = formatLinksToHTML(tailString); - - msgBuffer.append(formattedTailString); - - return msgBuffer.toString(); - } - - /** - * Replaces some chars that are special in a regular expression. - * - * @param text The initial text. - * @return the formatted text - */ - private static String replaceSpecialRegExpChars(String text) - { - return MESSAGE_CHARS_ESCAPE.matcher(text).replaceAll("\\\\$1"); - } - - /** - * Goes through the given text and converts all links to HTML links. - *

    - * For example all occurrences of http://jitsi.org/ will be - * replaced by - * http://jitsi.org/. The same is true for all strings - * starting with "www". - * - * @param text the text on which the regular expression would be performed - * @return the initial text containing only HTML links - */ - private static String formatLinksToHTML(String text) - { - String wwwURL = "(www\\." + // Matches the "www" string. - "[^/?#<\"'\\s]+" + // Matches at least one char of - // any type except / ? # < " ' - // and space. - "[\\.]" + // Matches the second point of the link. - "[^?#<\"'\\s]+" + // Matches at least one char of - // any type except ? # < " ' - // and space. - "(\\?[^#<\"'\\s]*)?" + - "(#.*)?)"; - - String protocolURL - = "([^\"'<>:/?#\\s]+" + // Matches at least one char of - // any type except " ' < > : / ? # - // and space. - "://" + // Matches the :// delimiter in links - "[^/?#<\"'\\s]*" + // Matches any number of times any char - // except / ? # < " ' and space. - "[^?#<\"'\\s]*" + // Matches any number of times any char - // except ? # < " ' and space. - "(\\?[^#<\"'\\s]*)?" + - "(#.*)?)"; - - String url = '(' + wwwURL + '|' + protocolURL + ')'; - - Pattern p = Pattern.compile(url, Pattern.CASE_INSENSITIVE); - - Matcher m = p.matcher(text); - - StringBuffer linkBuffer = new StringBuffer(); - - while (m.find()) - { - String linkGroup = m.group(); - - String replacement; - if (linkGroup.startsWith("www")) - { - replacement = "" + linkGroup + ""; - } - else - { - replacement = "" + linkGroup + ""; - } - - m.appendReplacement(linkBuffer, - replaceSpecialRegExpChars(replacement)); - } - - m.appendTail(linkBuffer); - - return linkBuffer.toString(); - } - - /** - * Registers an EventFilter with this operation set so that - * events, that do not need processing, are filtered out. - * - * @param filter the EventFilter to register. - */ - public void addEventFilter(EventFilter filter) - { - synchronized(eventFilters) - { - if(!eventFilters.contains(filter)) - { - eventFilters.add(filter); - } - } - } - - /** - * Unregisteres an EventFilter so that it won't check any more - * if an event should be filtered out. - * - * @param filter the EventFilter to unregister. - */ - public void removeEventFilter(EventFilter filter) - { - synchronized(eventFilters) - { - eventFilters.remove(filter); - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetFileTransferYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetFileTransferYahooImpl.java deleted file mode 100644 index 85f25b1..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetFileTransferYahooImpl.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.event.*; - -/** - * The Yahoo protocol filetransfer OperationSet. - * - * @author Damian Minkov - */ -public class OperationSetFileTransferYahooImpl - implements OperationSetFileTransfer, - SessionFileTransferListener -{ - /** - * The logger for this class. - */ - private static final Logger logger = - Logger.getLogger(OperationSetFileTransferYahooImpl.class); - - /** - * The provider that created us. - */ - private final ProtocolProviderServiceYahooImpl yahooProvider; - - /** - * A list of listeners registered for file transfer events. - */ - private ArrayList fileTransferListeners - = new ArrayList(); - - /** - * A list of active fileTransfers. - */ - private Hashtable activeFileTransfers - = new Hashtable(); - - /** - * Constructor - * @param provider is the provider that created us - */ - public OperationSetFileTransferYahooImpl( - ProtocolProviderServiceYahooImpl provider) - { - this.yahooProvider = provider; - - provider.addRegistrationStateChangeListener( - new RegistrationStateListener()); - } - - /** - * Sends a file transfer request to the given toContact by - * specifying the local and remote file path and the fromContact, - * sending the file. - * - * @param toContact the contact that should receive the file - * @param file the file to send - * - * @return the transfer object - * - * @throws IllegalStateException if the protocol provider is not registered - * or connected - * @throws IllegalArgumentException if some of the arguments doesn't fit the - * protocol requirements - */ - public FileTransfer sendFile( Contact toContact, - File file) - throws IllegalStateException, - IllegalArgumentException - { - try - { - assertConnected(); - - if(file.length() > getMaximumFileLength()) - throw new IllegalArgumentException( - "File length exceeds the allowed one for this protocol"); - - ArrayList filesToSend = new ArrayList(); - filesToSend.add(file.getCanonicalPath()); - Date sentDate = new Date(); - String id = yahooProvider.getYahooSession().sendFiles( - filesToSend, toContact.getAddress()); - - FileTransferImpl ft = - new FileTransferImpl(yahooProvider, - id, toContact, file, FileTransfer.OUT); - - // Notify all interested listeners that a file transfer has been - // created. - FileTransferCreatedEvent event - = new FileTransferCreatedEvent(ft, sentDate); - - fireFileTransferCreated(event); - - ft.fireStatusChangeEvent(FileTransferStatusChangeEvent.PREPARING); - - return ft; - } - catch(IOException e) - { - logger.error("Cannot send fileTransfer", e); - return null; - } - } - - /** - * Sends a file transfer request to the given toContact by - * specifying the local and remote file path and the fromContact, - * sending the file. - * - * @param toContact the contact that should receive the file - * @param fromContact the contact sending the file - * @param remotePath the remote file path - * @param localPath the local file path - * - * @return the transfer object - * - * @throws IllegalStateException if the protocol provider is not registered - * or connected - * @throws IllegalArgumentException if some of the arguments doesn't fit the - * protocol requirements - */ - public FileTransfer sendFile( Contact toContact, - Contact fromContact, - String remotePath, - String localPath) - throws IllegalStateException, - IllegalArgumentException - { - return this.sendFile(toContact, new File(localPath)); - } - - /** - * Adds the given FileTransferListener that would listen for - * file transfer requests and created file transfers. - * - * @param listener the FileTransferListener to add - */ - public void addFileTransferListener( - FileTransferListener listener) - { - synchronized(fileTransferListeners) - { - if(!fileTransferListeners.contains(listener)) - { - this.fileTransferListeners.add(listener); - } - } - } - - /** - * Removes the given FileTransferListener that listens for - * file transfer requests and created file transfers. - * - * @param listener the FileTransferListener to remove - */ - public void removeFileTransferListener( - FileTransferListener listener) - { - synchronized(fileTransferListeners) - { - this.fileTransferListeners.remove(listener); - } - } - - /** - * Utility method throwing an exception if the stack is not properly - * initialized. - * @throws java.lang.IllegalStateException if the underlying stack is - * not registered and initialized. - */ - private void assertConnected() - throws IllegalStateException - { - if (yahooProvider == null) - throw new IllegalStateException( - "The provider must be non-null and signed on the " - +"service before being able to send a file."); - else if (!yahooProvider.isRegistered()) - throw new IllegalStateException( - "The provider must be signed on the service before " - +"being able to send a file."); - } - - /** - * Delivers the file transfer to all registered listeners. - * - * @param event the FileTransferEvent that we'd like delivered to - * all registered file transfer listeners. - */ - void fireFileTransferCreated(FileTransferCreatedEvent event) - { - activeFileTransfers.put( - event.getFileTransfer().getID(), event.getFileTransfer()); - - Iterator listeners = null; - synchronized (fileTransferListeners) - { - listeners = new ArrayList - (fileTransferListeners).iterator(); - } - - while (listeners.hasNext()) - { - FileTransferListener listener = listeners.next(); - listener.fileTransferCreated(event); - } - } - - /** - * Delivers the specified event to all registered file transfer listeners. - * - * @param event the EventObject that we'd like delivered to all - * registered file transfer listeners. - */ - void fireFileTransferRequestRejected(FileTransferRequestEvent event) - { - Iterator listeners = null; - synchronized (fileTransferListeners) - { - listeners = new ArrayList - (fileTransferListeners).iterator(); - } - - while (listeners.hasNext()) - { - FileTransferListener listener = listeners.next(); - - listener.fileTransferRequestRejected(event); - } - } - - /** - * Delivers the specified event to all registered file transfer listeners. - * - * @param event the EventObject that we'd like delivered to all - * registered file transfer listeners. - */ - private void fireFileTransferRequest(FileTransferRequestEvent event) - { - Iterator listeners = null; - synchronized (fileTransferListeners) - { - listeners = new ArrayList - (fileTransferListeners).iterator(); - } - - while (listeners.hasNext()) - { - FileTransferListener listener = listeners.next(); - - listener.fileTransferRequestReceived(event); - } - } - - /** - * Delivers the specified event to all registered file transfer listeners. - * - * @param event the EventObject that we'd like delivered to all - * registered file transfer listeners. - */ - void fireFileTransferRequestCanceled(FileTransferRequestEvent event) - { - Iterator listeners = null; - synchronized (fileTransferListeners) - { - listeners = new ArrayList - (fileTransferListeners).iterator(); - } - - while (listeners.hasNext()) - { - FileTransferListener listener = listeners.next(); - - listener.fileTransferRequestCanceled(event); - } - } - - private int getStateMapping(int s) - { - switch(s) - { - case SessionFileTransferEvent.REFUSED : - return FileTransferStatusChangeEvent.REFUSED; - case SessionFileTransferEvent.CANCEL : - return FileTransferStatusChangeEvent.CANCELED; - case SessionFileTransferEvent.FAILED : - return FileTransferStatusChangeEvent.FAILED; - case SessionFileTransferEvent.IN_PROGRESS : - return FileTransferStatusChangeEvent.IN_PROGRESS; - case SessionFileTransferEvent.RECEIVED : - return FileTransferStatusChangeEvent.COMPLETED; - case SessionFileTransferEvent.SENT : - return FileTransferStatusChangeEvent.COMPLETED; - default: return FileTransferStatusChangeEvent.WAITING; - } - } - - /** - * Starting point for incoming filetransfer. - * @param ev - */ - public void fileTransferRequestReceived(SessionFileTransferEvent ev) - { - OperationSetPersistentPresenceYahooImpl opSetPersPresence - = (OperationSetPersistentPresenceYahooImpl) - yahooProvider.getOperationSet( - OperationSetPersistentPresence.class); - - Contact sender = opSetPersPresence.findContactByID(ev.getFrom()); - - if(sender == null) - return; - - Date recvDate = new Date(); - - for(int i = 0; i < ev.getFileNames().size(); i++) - { - String fileName = ev.getFileNames().get(i); - String fileSize = ev.getFileSizes().get(i); - - IncomingFileTransferRequest req = - new IncomingFileTransferRequestYahooImpl( - yahooProvider, this, sender, recvDate, - fileName, fileSize, - ev.getId()); - - activeFileTransfers.put(ev.getId(), req); - fireFileTransferRequest( - new FileTransferRequestEvent(this, req, recvDate)); - } - } - - /** - * Status changed for filetransfer. - * @param ev - */ - public void statusChanged(SessionFileTransferEvent ev) - { - if(ev.getId() == null) - return; - - Object ftObj = activeFileTransfers.get(ev.getId()); - - if(ftObj == null) - { - logger.warn("File Transfer or request not found. " + ev.getId() + "/ " + ev.getState()); - return; - } - - int newState = ev.getState(); - - if(newState == SessionFileTransferEvent.CANCEL - || newState == SessionFileTransferEvent.FAILED - || newState == SessionFileTransferEvent.RECEIVED - || newState == SessionFileTransferEvent.REFUSED - || newState == SessionFileTransferEvent.SENT) - { - // this is an final state so remove it from active filetransfers - activeFileTransfers.remove(ev.getId()); - } - - if(ftObj instanceof IncomingFileTransferRequest) - { - if(newState == SessionFileTransferEvent.REFUSED) - { - IncomingFileTransferRequestYahooImpl req = - (IncomingFileTransferRequestYahooImpl)ftObj; - fireFileTransferRequestCanceled( - new FileTransferRequestEvent(this, req, req.getDate())); - return; - } - } - - if(!(ftObj instanceof FileTransferImpl)) - { - logger.warn("File Transfer not found." + ftObj); - return; - } - - FileTransferImpl ft = (FileTransferImpl)ftObj; - - if( newState == SessionFileTransferEvent.IN_PROGRESS) - { - // if we start sending progress fire that we are in progress - if(ev.getProgress() == 0) - ft.fireStatusChangeEvent( - FileTransferStatusChangeEvent.IN_PROGRESS); - - ft.setTransferedBytes(ev.getProgress()); - ft.fireProgressChangeEvent( - System.currentTimeMillis(), ev.getProgress()); - } - else - ft.fireStatusChangeEvent(getStateMapping(newState)); - } - - /** - * Returns the maximum file length supported by the protocol in bytes. - * Supports up to 256MB. - * - * @return the file length that is supported. - */ - public long getMaximumFileLength() - { - return 268435456l;// = 256*1024*1024; - } - - /** - * Our listener that will tell us when we're registered to - */ - private class RegistrationStateListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenever - * a change in the registration state of the corresponding provider had - * occurred. - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (logger.isDebugEnabled()) - logger.debug("The provider changed state from: " - + evt.getOldState() - + " to: " + evt.getNewState()); - - if (evt.getNewState() == RegistrationState.REGISTERED) - { - yahooProvider.getYahooSession().addSessionFileListener( - OperationSetFileTransferYahooImpl.this); - } - else if (evt.getNewState() == RegistrationState.UNREGISTERED) - { - YahooSession ys = yahooProvider.getYahooSession(); - if(ys != null) - ys.removeSessionFileListener( - OperationSetFileTransferYahooImpl.this); - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetPersistentPresenceYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetPersistentPresenceYahooImpl.java deleted file mode 100644 index a99bdb7..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetPersistentPresenceYahooImpl.java +++ /dev/null @@ -1,954 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.yahooconstants.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; -import ymsg.network.event.*; - -/** - * The Yahoo implementation of a Persistent Presence Operation set. This class - * manages our own presence status as well as subscriptions for the presence - * status of our buddies. It also offers methods for retrieving and modifying - * the buddy contact list and adding listeners for changes in its layout. - * - * @author Damian Minkov - */ -public class OperationSetPersistentPresenceYahooImpl - extends AbstractOperationSetPersistentPresence -{ - private static final Logger logger = - Logger.getLogger(OperationSetPersistentPresenceYahooImpl.class); - - /** - * Contains our current status message. Note that this field would only - * be changed once the server has confirmed the new status message and - * not immediately upon setting a new one.. - */ - private String currentStatusMessage = ""; - - /** - * The presence status that we were last notified of entering. - * The initial one is OFFLINE - */ - private PresenceStatus currentStatus = YahooStatusEnum.OFFLINE; - - /** - * Sometimes status changes are received before the contact list is inited - * here we store such events so we can show them correctly - */ -// private Hashtable earlyStatusChange = new Hashtable(); - - /** - * The array list we use when returning from the getSupportedStatusSet() - * method. - */ - private static final List supportedPresenceStatusSet = new ArrayList(); - static{ - supportedPresenceStatusSet.add(YahooStatusEnum.AVAILABLE); - supportedPresenceStatusSet.add(YahooStatusEnum.BE_RIGHT_BACK); - supportedPresenceStatusSet.add(YahooStatusEnum.BUSY); - supportedPresenceStatusSet.add(YahooStatusEnum.IDLE); - supportedPresenceStatusSet.add(YahooStatusEnum.INVISIBLE); - supportedPresenceStatusSet.add(YahooStatusEnum.NOT_AT_DESK); - supportedPresenceStatusSet.add(YahooStatusEnum.NOT_AT_HOME); - supportedPresenceStatusSet.add(YahooStatusEnum.NOT_IN_OFFICE); - supportedPresenceStatusSet.add(YahooStatusEnum.OFFLINE); - supportedPresenceStatusSet.add(YahooStatusEnum.ON_THE_PHONE); - supportedPresenceStatusSet.add(YahooStatusEnum.ON_VACATION); - supportedPresenceStatusSet.add(YahooStatusEnum.OUT_TO_LUNCH); - supportedPresenceStatusSet.add(YahooStatusEnum.STEPPED_OUT); - } - - /** - * A map containing bindings between SIP Communicator's yahoo presence status - * instances and Yahoo status codes - */ - private static final Map scToYahooModesMappings - = new Hashtable(); - static{ - scToYahooModesMappings.put(YahooStatusEnum.AVAILABLE, - StatusConstants.STATUS_AVAILABLE); - scToYahooModesMappings.put(YahooStatusEnum.BE_RIGHT_BACK, - StatusConstants.STATUS_BRB); - scToYahooModesMappings.put(YahooStatusEnum.BUSY, - StatusConstants.STATUS_BUSY); - scToYahooModesMappings.put(YahooStatusEnum.IDLE, - StatusConstants.STATUS_IDLE); - scToYahooModesMappings.put(YahooStatusEnum.INVISIBLE, - StatusConstants.STATUS_INVISIBLE); - scToYahooModesMappings.put(YahooStatusEnum.NOT_AT_DESK, - StatusConstants.STATUS_NOTATDESK); - scToYahooModesMappings.put(YahooStatusEnum.NOT_AT_HOME, - StatusConstants.STATUS_NOTATHOME); - scToYahooModesMappings.put(YahooStatusEnum.NOT_IN_OFFICE, - StatusConstants.STATUS_NOTINOFFICE); - scToYahooModesMappings.put(YahooStatusEnum.OFFLINE, - StatusConstants.STATUS_OFFLINE); - scToYahooModesMappings.put(YahooStatusEnum.ON_THE_PHONE, - StatusConstants.STATUS_ONPHONE); - scToYahooModesMappings.put(YahooStatusEnum.ON_VACATION, - StatusConstants.STATUS_ONVACATION); - scToYahooModesMappings.put(YahooStatusEnum.OUT_TO_LUNCH, - StatusConstants.STATUS_OUTTOLUNCH); - scToYahooModesMappings.put(YahooStatusEnum.STEPPED_OUT, - StatusConstants.STATUS_STEPPEDOUT); - } - - /** - * The server stored contact list that will be encapsulating smack's - * buddy list. - */ - private ServerStoredContactListYahooImpl ssContactList = null; - - /** - * Listens for events that are fired while registering to server. - * After we are registered instance is cleared and never used. - */ - private EarlyEventListener earlyEventListener = null; - - /** - * Status events are received before subscription one. - * And when subscription is received we deliver - * and the status events. - */ - private StatusUpdater statusUpdater = new StatusUpdater(); - - public OperationSetPersistentPresenceYahooImpl( - ProtocolProviderServiceYahooImpl provider) - { - super(provider); - - ssContactList = new ServerStoredContactListYahooImpl( this , provider); - - parentProvider.addRegistrationStateChangeListener( - new RegistrationStateListener()); - } - - /** - * Registers a listener that would receive events upong changes in server - * stored groups. - * - * @param listener a ServerStoredGroupChangeListener impl that would - * receive events upong group changes. - */ - @Override - public void addServerStoredGroupChangeListener(ServerStoredGroupListener - listener) - { - ssContactList.addGroupListener(listener); - } - - /** - * Creates a group with the specified name and parent in the server - * stored contact list. - * - * @param parent the group where the new group should be created - * @param groupName the name of the new group to create. - * @throws OperationFailedException if such group already exists - */ - public void createServerStoredContactGroup(ContactGroup parent, - String groupName) - throws OperationFailedException - { - assertConnected(); - - if (!parent.canContainSubgroups()) - throw new IllegalArgumentException( - "The specified contact group cannot contain child groups. Group:" - + parent ); - - ssContactList.createGroup(groupName); - } - - /** - * Creates a non persistent contact for the specified address. This would - * also create (if necessary) a group for volatile contacts that would not - * be added to the server stored contact list. The volatile contact would - * remain in the list until it is really added to the contact list or - * until the application is terminated. - * @param id the address of the contact to create. - * @return the newly created volatile ContactImpl - */ - public ContactYahooImpl createVolatileContact(String id) - { - return ssContactList.createVolatileContact(id); - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @param parentGroup the group where the unresolved contact is supposed - * to belong to. - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData, - ContactGroup parentGroup) - { - if(! (parentGroup instanceof ContactGroupYahooImpl || - parentGroup instanceof RootContactGroupYahooImpl) ) - throw new IllegalArgumentException( - "Argument is not an yahoo contact group (group=" - + parentGroup + ")"); - - ContactYahooImpl contact = - ssContactList.createUnresolvedContact(parentGroup, address); - - contact.setPersistentData(persistentData); - - return contact; - } - - /** - * Creates and returns a unresolved contact from the specified - * address and persistentData. - * - * @param address an identifier of the contact that we'll be creating. - * @param persistentData a String returned Contact's getPersistentData() - * method during a previous run and that has been persistently stored - * locally. - * @return the unresolved Contact created from the specified - * address and persistentData - */ - public Contact createUnresolvedContact(String address, - String persistentData) - { - return createUnresolvedContact( address - , persistentData - , getServerStoredContactListRoot()); - } - - /** - * Creates and returns a unresolved contact group from the specified - * address and persistentData. - * - * @param groupUID an identifier, returned by ContactGroup's - * getGroupUID, that the protocol provider may use in order to create - * the group. - * @param persistentData a String returned ContactGroups's - * getPersistentData() method during a previous run and that has been - * persistently stored locally. - * @param parentGroup the group under which the new group is to be - * created or null if this is group directly underneath the root. - * @return the unresolved ContactGroup created from the - * specified uid and persistentData - */ - public ContactGroup createUnresolvedContactGroup(String groupUID, - String persistentData, ContactGroup parentGroup) - { - return ssContactList.createUnresolvedContactGroup(groupUID); - } - - /** - * Returns a reference to the contact with the specified ID in case we - * have a subscription for it and null otherwise/ - * - * @param contactID a String identifier of the contact which we're - * seeking a reference of. - * @return a reference to the Contact with the specified - * contactID or null if we don't have a subscription for the - * that identifier. - */ - public Contact findContactByID(String contactID) - { - return ssContactList.findContactById(contactID); - } - - /** - * Returns the status message that was confirmed by the serfver - * - * @return the last status message that we have requested and the aim - * server has confirmed. - */ - public String getCurrentStatusMessage() - { - return currentStatusMessage; - } - - /** - * Returns the protocol specific contact instance representing the local - * user. - * - * @return the Contact (address, phone number, or uin) that the Provider - * implementation is communicating on behalf of. - */ - public Contact getLocalContact() - { - return null; - } - - /** - * Returns a PresenceStatus instance representing the state this provider - * is currently in. - * - * @return the PresenceStatus last published by this provider. - */ - public PresenceStatus getPresenceStatus() - { - return currentStatus; - } - - /** - * Returns the root group of the server stored contact list. - * - * @return the root ContactGroup for the ContactList stored by this - * service. - */ - public ContactGroup getServerStoredContactListRoot() - { - return ssContactList.getRootGroup(); - } - - /** - * Returns the set of PresenceStatus objects that a user of this service - * may request the provider to enter. - * - * @return Iterator a PresenceStatus array containing "enterable" status - * instances. - */ - public Iterator getSupportedStatusSet() - { - return supportedPresenceStatusSet.iterator(); - } - - /** - * Removes the specified contact from its current parent and places it - * under newParent. - * - * @param contactToMove the Contact to move - * @param newParent the ContactGroup where Contact - * would be placed. - */ - public void moveContactToGroup(Contact contactToMove, - ContactGroup newParent) - { - assertConnected(); - - if( !(contactToMove instanceof ContactYahooImpl) ) - throw new IllegalArgumentException( - "The specified contact is not an yahoo contact." + contactToMove); - if( !(newParent instanceof ContactGroupYahooImpl) ) - throw new IllegalArgumentException( - "The specified group is not an yahoo contact group." - + newParent); - - ssContactList.moveContact((ContactYahooImpl)contactToMove, - (ContactGroupYahooImpl)newParent); - } - - /** - * Requests the provider to enter into a status corresponding to the - * specified paramters. - * - * @param status the PresenceStatus as returned by - * getRequestableStatusSet - * @param statusMessage the message that should be set as the reason to - * enter that status - * @throws IllegalArgumentException if the status requested is not a - * valid PresenceStatus supported by this provider. - * @throws IllegalStateException if the provider is not currently - * registered. - * @throws OperationFailedException with code NETWORK_FAILURE if - * publishing the status fails due to a network error. - */ - public void publishPresenceStatus(PresenceStatus status, - String statusMessage) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - assertConnected(); - - if (!(status instanceof YahooStatusEnum)) - throw new IllegalArgumentException( - status + " is not a valid Yahoo status"); - - if(status.equals(YahooStatusEnum.OFFLINE)) - { - parentProvider.unregister(); - return; - } - - try - { - if(statusMessage != null && statusMessage.length() != 0) - { - boolean isAvailable = false; - - if(status.equals(YahooStatusEnum.AVAILABLE)) - isAvailable = true; - - // false - away - // true - available - parentProvider.getYahooSession(). - setStatus(statusMessage, isAvailable); - } - - parentProvider.getYahooSession().setStatus( - scToYahooModesMappings.get(status).longValue()); - - fireProviderStatusChangeEvent(currentStatus, status); - } - catch(IOException ex) - { - throw new OperationFailedException("Failed to set Status", - OperationFailedException.NETWORK_FAILURE); - } - } - - /** - * Get the PresenceStatus for a particular contact. - * - * @param contactIdentifier the identifier of the contact whose status - * we're interested in. - * @return PresenceStatus the PresenceStatus of the specified - * contact - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * retrieving the status fails due to errors experienced during - * network communication - */ - public PresenceStatus queryContactStatus(String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - - ContactYahooImpl contact = ssContactList.findContactById(contactIdentifier); - if(contact == null) - { - if (logger.isInfoEnabled()) - logger.info("Contact not found id :" + contactIdentifier); - return null; - } - else - return yahooStatusToPresenceStatus(contact.getSourceContact().getStatus()); - } - - /** - * Removes the specified group from the server stored contact list. - * - * @param group the group to remove. - */ - public void removeServerStoredContactGroup(ContactGroup group) - { - assertConnected(); - - if( !(group instanceof ContactGroupYahooImpl) ) - throw new IllegalArgumentException( - "The specified group is not an yahoo contact group: " + group); - - ssContactList.removeGroup(((ContactGroupYahooImpl)group)); - } - - /** - * Removes the specified group change listener so that it won't receive - * any further events. - * - * @param listener the ServerStoredGroupChangeListener to remove - */ - @Override - public void removeServerStoredGroupChangeListener(ServerStoredGroupListener - listener) - { - ssContactList.removeGroupListener(listener); - } - - /** - * Renames the specified group from the server stored contact list. - * - * @param group the group to rename. - * @param newName the new name of the group. - */ - public void renameServerStoredContactGroup(ContactGroup group, - String newName) - { - assertConnected(); - - if( !(group instanceof ContactGroupYahooImpl) ) - throw new IllegalArgumentException( - "The specified group is not an yahoo contact group: " + group); - - throw new UnsupportedOperationException("Renaming group not supported!"); - //ssContactList.renameGroup((ContactGroupYahooImpl)group, newName); - } - - /** - * Handler for incoming authorization requests. - * - * @param handler an instance of an AuthorizationHandler for - * authorization requests coming from other users requesting - * permission add us to their contact list. - */ - public void setAuthorizationHandler(AuthorizationHandler handler) - { - ssContactList.setAuthorizationHandler(handler); - - // we got a handler. Lets process if something has came - // during login process - if(earlyEventListener != null) - { - earlyEventListener.processEarlyAuthorizations(); - earlyEventListener = null; - } - } - - /** - * Persistently adds a subscription for the presence status of the - * contact corresponding to the specified contactIdentifier and indicates - * that it should be added to the specified group of the server stored - * contact list. - * - * @param parent the parent group of the server stored contact list - * where the contact should be added.

    - * @param contactIdentifier the contact whose status updates we are - * subscribing for. - * @throws IllegalArgumentException if contact or - * parent are not a contact known to the underlying protocol - * provider. - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(ContactGroup parent, String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - assertConnected(); - - if(! (parent instanceof ContactGroupYahooImpl) ) - throw new IllegalArgumentException( - "Argument is not an yahoo contact group (group=" + parent + ")"); - - ssContactList.addContact((ContactGroupYahooImpl)parent, contactIdentifier); - } - - /** - * Adds a subscription for the presence status of the contact - * corresponding to the specified contactIdentifier. - * - * @param contactIdentifier the identifier of the contact whose status - * updates we are subscribing for.

    - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * subscribing fails due to errors experienced during network - * communication - */ - public void subscribe(String contactIdentifier) throws - IllegalArgumentException, IllegalStateException, - OperationFailedException - { - assertConnected(); - - ssContactList.addContact(contactIdentifier); - } - - /** - * Removes a subscription for the presence status of the specified - * contact. - * - * @param contact the contact whose status updates we are unsubscribing - * from. - * @throws IllegalArgumentException if contact is not a contact - * known to the underlying protocol provider - * @throws IllegalStateException if the underlying protocol provider is - * not registered/signed on a public service. - * @throws OperationFailedException with code NETWORK_FAILURE if - * unsubscribing fails due to errors experienced during network - * communication - */ - public void unsubscribe(Contact contact) throws IllegalArgumentException, - IllegalStateException, OperationFailedException - { - assertConnected(); - - if(! (contact instanceof ContactYahooImpl) ) - throw new IllegalArgumentException( - "Argument is not an yahoo contact (contact=" + contact + ")"); - - ssContactList.removeContact((ContactYahooImpl)contact); - } - - /** - * Converts the specified yahoo status to one of the status fields of the - * YahooStatusEnum class. - * - * @param status the yahoo Status - * @return a PresenceStatus instance representation of the yahoo Status - * parameter. The returned result is one of the YahooStatusEnum fields. - */ - YahooStatusEnum yahooStatusToPresenceStatus(long status) - { - if(status == StatusConstants.STATUS_AVAILABLE) - return YahooStatusEnum.AVAILABLE; - else if(status == StatusConstants.STATUS_BRB) - return YahooStatusEnum.BE_RIGHT_BACK; - else if(status == StatusConstants.STATUS_BUSY) - return YahooStatusEnum.BUSY; - else if(status == StatusConstants.STATUS_NOTATHOME) - return YahooStatusEnum.NOT_AT_HOME; - else if(status == StatusConstants.STATUS_NOTATDESK) - return YahooStatusEnum.NOT_AT_DESK; - else if(status == StatusConstants.STATUS_NOTINOFFICE) - return YahooStatusEnum.NOT_IN_OFFICE; - else if(status == StatusConstants.STATUS_ONPHONE) - return YahooStatusEnum.ON_THE_PHONE; - else if(status == StatusConstants.STATUS_ONVACATION) - return YahooStatusEnum.ON_VACATION; - else if(status == StatusConstants.STATUS_OUTTOLUNCH) - return YahooStatusEnum.OUT_TO_LUNCH; - else if(status == StatusConstants.STATUS_STEPPEDOUT) - return YahooStatusEnum.STEPPED_OUT; - else if(status == StatusConstants.STATUS_INVISIBLE) - return YahooStatusEnum.INVISIBLE; - else if(status == StatusConstants.STATUS_IDLE) - return YahooStatusEnum.IDLE; - else if(status == StatusConstants.STATUS_OFFLINE) - return YahooStatusEnum.OFFLINE; - // Yahoo supports custom statuses so if such is set just return available - else - return YahooStatusEnum.AVAILABLE; - } - - /** - * Utility method throwing an exception if the stack is not properly - * initialized. - * @throws java.lang.IllegalStateException if the underlying stack is - * not registered and initialized. - */ - private void assertConnected() throws IllegalStateException - { - if (parentProvider == null) - throw new IllegalStateException( - "The provider must be non-null and signed on the yahoo " - +"service before being able to communicate."); - if (!parentProvider.isRegistered()) - throw new IllegalStateException( - "The provider must be signed on the yahoo service before " - +"being able to communicate."); - } - - /** - * Notify all provider presence listeners of the corresponding event change - * - * @param oldStatus - * the status our stack had so far - * @param newStatus - * the status we have from now on - */ - @Override - protected void fireProviderStatusChangeEvent( - PresenceStatus oldStatus, - PresenceStatus newStatus) - { - if (!oldStatus.equals(newStatus)) - { - currentStatus = newStatus; - - super.fireProviderStatusChangeEvent(oldStatus, newStatus); - } - } - - /** - * Statuses have been received durring login process - * so we will init them once we are logged in - */ - private void initContactStatuses() - { - YahooGroup[] groups = parentProvider.getYahooSession().getGroups(); - - for (YahooGroup item : groups) - { - @SuppressWarnings("unchecked") - Iterable members = item.getMembers(); - - for (YahooUser user : members) - { - ContactYahooImpl sourceContact = - ssContactList.findContactById(user.getId()); - - if(sourceContact != null) - handleContactStatusChange(sourceContact, user); - } - } - } - - /** - * Our listener that will tell us when we're registered to server - * and is ready to accept us as a listener. - */ - private class RegistrationStateListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenever - * a change in the registration state of the corresponding provider had - * occurred. - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (logger.isDebugEnabled()) - logger.debug("The yahoo provider changed state from: " - + evt.getOldState() - + " to: " + evt.getNewState()); - - if(evt.getNewState() == RegistrationState.REGISTERING) - { - // add new listener waiting for events during login process - earlyEventListener - = new EarlyEventListener(parentProvider.getYahooSession()); - } - else if(evt.getNewState() == RegistrationState.REGISTERED) - { - parentProvider.getYahooSession(). - addSessionListener(new StatusChangedListener()); - - ssContactList.setYahooSession(parentProvider.getYahooSession()); - - initContactStatuses(); - - addSubscriptionListener(statusUpdater); - - if(earlyEventListener != null) - { - earlyEventListener.dispose(); - earlyEventListener = null; - } - } - else if(evt.getNewState() == RegistrationState.UNREGISTERED - || evt.getNewState() == RegistrationState.AUTHENTICATION_FAILED - || evt.getNewState() == RegistrationState.CONNECTION_FAILED) - { - //since we are disconnected, we won't receive any further status - //updates so we need to change by ourselves our own status as - //well as set to offline all contacts in our contact list that - //were online - PresenceStatus oldStatus = currentStatus; - currentStatus = YahooStatusEnum.OFFLINE; - - fireProviderStatusChangeEvent(oldStatus, currentStatus); - - removeSubscriptionListener(statusUpdater); - - //send event notifications saying that all our buddies are - //offline. The protocol does not implement top level buddies - //nor subgroups for top level groups so a simple nested loop - //would be enough. - Iterator groupsIter = - getServerStoredContactListRoot().subgroups(); - while(groupsIter.hasNext()) - { - ContactGroup group = groupsIter.next(); - Iterator contactsIter = group.contacts(); - - while(contactsIter.hasNext()) - { - ContactYahooImpl contact - = (ContactYahooImpl)contactsIter.next(); - - PresenceStatus oldContactStatus - = contact.getPresenceStatus(); - - if(!oldContactStatus.isOnline()) - continue; - - contact.updatePresenceStatus(YahooStatusEnum.OFFLINE); - - fireContactPresenceStatusChangeEvent( - contact - , contact.getParentContactGroup() - , oldContactStatus, YahooStatusEnum.OFFLINE); - } - } - - // clear listener - if(earlyEventListener != null) - { - earlyEventListener.dispose(); - earlyEventListener = null; - } - } - } - } - - private void handleContactStatusChange(YahooUser yFriend) - { - ContactYahooImpl sourceContact = - ssContactList.findContactById(yFriend.getId()); - - if(sourceContact == null) - { - if(parentProvider.getAccountID().getUserID(). - equals(yFriend.getId())) - { - // thats my own status - if (logger.isTraceEnabled()) - logger.trace("Own status changed to " + yFriend.getStatus()); - PresenceStatus oldStatus = currentStatus; - currentStatus = - yahooStatusToPresenceStatus(yFriend.getStatus()); - fireProviderStatusChangeEvent(oldStatus, currentStatus); - - return; - } - // strange - else - return; - } - - handleContactStatusChange(sourceContact, yFriend); - } - - void handleContactStatusChange(ContactYahooImpl sourceContact, YahooUser yFriend) - { - PresenceStatus oldStatus - = sourceContact.getPresenceStatus(); - - PresenceStatus newStatus = yahooStatusToPresenceStatus(yFriend.getStatus()); - - // statuses maybe the same and only change in status message - sourceContact.setStatusMessage(yFriend.getCustomStatusMessage()); - - // when old and new status are the same do nothing - no change - if(oldStatus.equals(newStatus)) - { - if (logger.isDebugEnabled()) - logger.debug("old(" + oldStatus + ") and new("+ newStatus + ") statuses are the same!"); - return; - } - - sourceContact.updatePresenceStatus(newStatus); - - ContactGroup parent - = ssContactList.findContactGroup(sourceContact); - - if (logger.isDebugEnabled()) - logger.debug("Will Dispatch the contact status event."); - fireContactPresenceStatusChangeEvent(sourceContact, parent, - oldStatus, newStatus); - } - - private class StatusChangedListener - extends SessionAdapter - { - @Override - public void friendsUpdateReceived(SessionFriendEvent evt) - { - if (logger.isDebugEnabled()) - logger.debug("Received a status update for contact " + evt); - - if(evt.getFriend() != null) - { - handleContactStatusChange(evt.getFriend()); - } - else if(evt.getFriends() != null) - { - YahooUser[] yfs = evt.getFriends(); - for (int i = 0; i < yfs.length; i++) - handleContactStatusChange(yfs[i]); - } - } - } - - /** - * Updates the statuses of newly created persistent contacts - */ - private class StatusUpdater - extends SubscriptionAdapter - { - @Override - public void subscriptionCreated(SubscriptionEvent evt) - { - ContactYahooImpl contact = - (ContactYahooImpl)evt.getSourceContact(); - - if(!contact.isPersistent() || !contact.isResolved()) - return; - - handleContactStatusChange(contact, contact.getSourceContact()); - } - } - - private class EarlyEventListener - extends SessionAdapter - { - private final List receivedAuthorizations - = new Vector(); - - /** - * The YahooSession this instance is listening to because - * the YahooSession isn't available in - * parentProvider after - * {@link RegistrationState#UNREGISTERED} and then this listener cannot - * be removed. - */ - private final YahooSession yahooSession; - - public EarlyEventListener(YahooSession yahooSession) - { - this.yahooSession = yahooSession; - this.yahooSession.addSessionListener(this); - } - - @Override - public void authorizationReceived(SessionAuthorizationEvent ev) - { - if(ev.isAuthorizationRequest()) - { - if (logger.isTraceEnabled()) - logger.trace("authorizationRequestReceived from " + - ev.getFrom()); - receivedAuthorizations.add(ev); - } - } - - public void dispose() - { - yahooSession.removeSessionListener(this); - } - - public void processEarlyAuthorizations() - { - for (SessionAuthorizationEvent e : receivedAuthorizations) - { - ssContactList.processAuthorizationRequest(e); - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetTypingNotificationsYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetTypingNotificationsYahooImpl.java deleted file mode 100644 index 81e266a..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/OperationSetTypingNotificationsYahooImpl.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.event.*; - -/** - * Maps SIP Communicator typing notifications to those going and coming from - * smack lib. - * - * @author Damian Minkov - */ -public class OperationSetTypingNotificationsYahooImpl - extends AbstractOperationSetTypingNotifications -{ - private static final Logger logger = - Logger.getLogger(OperationSetTypingNotificationsYahooImpl.class); - - /** - * An active instance of the opSetPersPresence operation set. We're using - * it to map incoming events to contacts in our contact list. - */ - private OperationSetPersistentPresenceYahooImpl opSetPersPresence = null; - - /** - * @param provider a ref to the ProtocolProviderServiceImpl - * that created us and that we'll use for retrieving the underlying aim - * connection. - */ - OperationSetTypingNotificationsYahooImpl( - ProtocolProviderServiceYahooImpl provider) - { - super(provider); - - provider.addRegistrationStateChangeListener(new ProviderRegListener()); - } - - /** - * Sends a notification to notifiedContatct that we have entered - * typingState. - * - * @param notifiedContact the Contact to notify - * @param typingState the typing state that we have entered. - * - * @throws java.lang.IllegalStateException if the underlying stack is - * not registered and initialized. - * @throws java.lang.IllegalArgumentException if notifiedContact is - * not an instance belonging to the underlying implementation. - */ - public void sendTypingNotification(Contact notifiedContact, int typingState) - throws IllegalStateException, IllegalArgumentException - { - assertConnected(); - - if( !(notifiedContact instanceof ContactYahooImpl) ) - throw new IllegalArgumentException( - "The specified contact is not an yahoo contact." - + notifiedContact); - - if(typingState == OperationSetTypingNotifications.STATE_TYPING) - { - - parentProvider.getYahooSession(). - keyTyped(notifiedContact.getAddress(), - parentProvider.getAccountID().getUserID()); - } - else - if(typingState == OperationSetTypingNotifications.STATE_STOPPED || - typingState == OperationSetTypingNotifications.STATE_PAUSED) - { - parentProvider.getYahooSession(). - stopTyping(notifiedContact.getAddress(), - parentProvider.getAccountID().getUserID()); - } - } - - private class TypingListener - extends SessionAdapter - { - @Override - public void notifyReceived(SessionNotifyEvent evt) - { - if(evt.isTyping()) - { - String typingUserID = evt.getFrom(); - - if(typingUserID != null) - { - Contact sourceContact = - opSetPersPresence.findContactByID(typingUserID); - - if(sourceContact == null) - return; - - // typing on - fireTypingNotificationsEvent( - sourceContact, - (evt.getMode() == 1) ? STATE_TYPING : STATE_STOPPED); - } - } - } - } - - /** - * Our listener that will tell us when we're registered and - * ready to accept us as a listener. - */ - private class ProviderRegListener - implements RegistrationStateChangeListener - { - /** - * The method is called by a ProtocolProvider implementation whenever - * a change in the registration state of the corresponding provider had - * occurred. - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - if (logger.isDebugEnabled()) - logger.debug("The provider changed state from: " - + evt.getOldState() - + " to: " + evt.getNewState()); - if (evt.getNewState() == RegistrationState.REGISTERED) - { - opSetPersPresence = - (OperationSetPersistentPresenceYahooImpl) parentProvider - .getOperationSet(OperationSetPersistentPresence.class); - - parentProvider - .getYahooSession().addSessionListener(new TypingListener()); - } - } - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolIconYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolIconYahooImpl.java deleted file mode 100644 index 34befc9..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolIconYahooImpl.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Represents the Yahoo protocol icon. Implements the ProtocolIcon - * interface in order to provide an Yahoo icon image in two different sizes. - * - * @author Yana Stamcheva - */ -public class ProtocolIconYahooImpl - implements ProtocolIcon -{ - private static Logger logger = Logger.getLogger(ProtocolIconYahooImpl.class); - - private static ResourceManagementService resourcesService; - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconsTable - = new Hashtable(); - static - { - iconsTable.put(ProtocolIcon.ICON_SIZE_16x16, - getImageInBytes("service.protocol.yahoo.YAHOO_16x16")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_32x32, - getImageInBytes("service.protocol.yahoo.YAHOO_32x32")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_48x48, - getImageInBytes("service.protocol.yahoo.YAHOO_48x48")); - - iconsTable.put(ProtocolIcon.ICON_SIZE_64x64, - getImageInBytes("service.protocol.yahoo.YAHOO_64x64")); - } - - /** - * A hash table containing the protocol icon in different sizes. - */ - private static Hashtable iconPathsTable - = new Hashtable(); - static - { - iconPathsTable.put(ProtocolIcon.ICON_SIZE_16x16, - getResources().getImagePath("service.protocol.yahoo.YAHOO_16x16")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_32x32, - getResources().getImagePath("service.protocol.yahoo.YAHOO_32x32")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_48x48, - getResources().getImagePath("service.protocol.yahoo.YAHOO_48x48")); - - iconPathsTable.put(ProtocolIcon.ICON_SIZE_64x64, - getResources().getImagePath("service.protocol.yahoo.YAHOO_64x64")); - } - - /** - * Implements the ProtocolIcon.getSupportedSizes() method. Returns - * an iterator to a set containing the supported icon sizes. - * @return an iterator to a set containing the supported icon sizes - */ - public Iterator getSupportedSizes() - { - return iconsTable.keySet().iterator(); - } - - /** - * Returns TRUE if a icon with the given size is supported, FALSE-otherwise. - */ - public boolean isSizeSupported(String iconSize) - { - return iconsTable.containsKey(iconSize); - } - - /** - * Returns the icon image in the given size. - * @param iconSize the icon size; one of ICON_SIZE_XXX constants - */ - public byte[] getIcon(String iconSize) - { - return iconsTable.get(iconSize); - } - - /** - * Returns a path to the icon with the given size. - * @param iconSize the size of the icon we're looking for - * @return the path to the icon with the given size - */ - public String getIconPath(String iconSize) - { - return iconPathsTable.get(iconSize); - } - - /** - * Returns the icon image used to represent the protocol connecting state. - * @return the icon image used to represent the protocol connecting state - */ - public byte[] getConnectingIcon() - { - return getImageInBytes("yahooConnectingIcon"); - } - - /** - * Returns the byte representation of the image corresponding to the given - * identifier. - * - * @param imageID the identifier of the image - * @return the byte representation of the image corresponding to the given - * identifier. - */ - public static byte[] getImageInBytes(String imageID) - { - InputStream in = getResources().getImageInputStream(imageID); - - if (in == null) - return null; - byte[] image = null; - try - { - image = new byte[in.available()]; - - in.read(image); - } - catch (IOException e) - { - logger.error("Failed to load image:" + imageID, e); - } - - return image; - } - - public static ResourceManagementService getResources() - { - if (resourcesService == null) - { - ServiceReference serviceReference = YahooActivator.getBundleContext() - .getServiceReference(ResourceManagementService.class.getName()); - - if(serviceReference == null) - return null; - - resourcesService = (ResourceManagementService) - YahooActivator.getBundleContext().getService(serviceReference); - } - - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderFactoryYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderFactoryYahooImpl.java deleted file mode 100644 index 358286c..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderFactoryYahooImpl.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -import org.osgi.framework.*; - -/** - * The Yahoo implementation of the ProtocolProviderFactory. - * @author Damian Minkov - */ -public class ProtocolProviderFactoryYahooImpl - extends ProtocolProviderFactory -{ - - /** - * Creates an instance of the ProtocolProviderFactoryYahooImpl. - */ - protected ProtocolProviderFactoryYahooImpl() - { - super(YahooActivator.getBundleContext(), ProtocolNames.YAHOO); - } - - /** - * Initializes and creates an account corresponding to the specified - * accountProperties and registers the resulting ProtocolProvider in the - * context BundleContext parameter. This method has a persistent - * effect. Once created the resulting account will remain installed until - * removed through the uninstall account method. - * - * @param userIDStr the user identifier for the new account - * @param accountProperties a set of protocol (or implementation) - * specific properties defining the new account. - * @return the AccountID of the newly created account - */ - @Override - public AccountID installAccount( String userIDStr, - Map accountProperties) - { - BundleContext context - = YahooActivator.getBundleContext(); - if (context == null) - throw new NullPointerException("The specified BundleContext was null"); - - if (userIDStr == null) - throw new NullPointerException("The specified AccountID was null"); - - if (accountProperties == null) - throw new NullPointerException("The specified property map was null"); - - accountProperties.put(USER_ID, userIDStr); - - AccountID accountID = new YahooAccountID(userIDStr, accountProperties); - - //make sure we haven't seen this account id before. - if( registeredAccounts.containsKey(accountID) ) - throw new IllegalStateException( - "An account for id " + userIDStr + " was already installed!"); - - //first store the account and only then load it as the load generates - //an osgi event, the osgi event triggers (through the UI) a call to - //the register() method and it needs to access the configuration service - //and check for a password. - this.storeAccount(accountID, false); - - accountID = loadAccount(accountProperties); - - return accountID; - } - - @Override - protected AccountID createAccountID(String userID, Map accountProperties) - { - return new YahooAccountID(userID, accountProperties); - } - - @Override - protected ProtocolProviderService createService(String userID, - AccountID accountID) - { - ProtocolProviderServiceYahooImpl service = - new ProtocolProviderServiceYahooImpl(); - - service.initialize(userID, accountID); - return service; - } - - @Override - public void modifyAccount( ProtocolProviderService protocolProvider, - Map accountProperties) - throws NullPointerException - { - BundleContext context - = YahooActivator.getBundleContext(); - - if (context == null) - throw new NullPointerException( - "The specified BundleContext was null"); - - if (protocolProvider == null) - throw new NullPointerException( - "The specified Protocol Provider was null"); - - YahooAccountID accountID - = (YahooAccountID) protocolProvider.getAccountID(); - - // If the given accountID doesn't correspond to an existing account - // we return. - if(!registeredAccounts.containsKey(accountID)) - return; - - ServiceRegistration registration = registeredAccounts.get(accountID); - - // kill the service - if (registration != null) - registration.unregister(); - - if (accountProperties == null) - throw new NullPointerException( - "The specified property map was null"); - - accountProperties.put(USER_ID, accountID.getUserID()); - - if (!accountProperties.containsKey(PROTOCOL)) - accountProperties.put(PROTOCOL, ProtocolNames.YAHOO); - - accountID.setAccountProperties(accountProperties); - - // First store the account and only then load it as the load generates - // an osgi event, the osgi event triggers (trhgough the UI) a call to - // the register() method and it needs to acces the configuration service - // and check for a password. - this.storeAccount(accountID); - - Hashtable properties = new Hashtable(); - properties.put(PROTOCOL, ProtocolNames.YAHOO); - properties.put(USER_ID, accountID.getUserID()); - - ((ProtocolProviderServiceYahooImpl)protocolProvider) - .initialize(accountID.getUserID(), accountID); - - // We store again the account in order to store all properties added - // during the protocol provider initialization. - this.storeAccount(accountID); - - registration - = context.registerService( - ProtocolProviderService.class.getName(), - protocolProvider, - properties); - - registeredAccounts.put(accountID, registration); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java deleted file mode 100644 index 264aaab..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ProtocolProviderServiceYahooImpl.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; - -import net.java.sip.communicator.service.dns.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; -import ymsg.network.event.*; - -/** - * An implementation of the protocol provider service over the Yahoo protocol - * - * @author Damian Minkov - */ -public class ProtocolProviderServiceYahooImpl - extends AbstractProtocolProviderService -{ - /** - * This class logger. - */ - private static final Logger logger = - Logger.getLogger(ProtocolProviderServiceYahooImpl.class); - - /** - * The current yahoo session. - */ - private YahooSession yahooSession = null; - - /** - * indicates whether or not the provider is initialized and ready for use. - */ - private boolean isInitialized = false; - - /** - * We use this to lock access to initialization. - */ - private final Object initializationLock = new Object(); - - /** - * The identifier of the account that this provider represents. - */ - private AccountID accountID = null; - - /** - * Used when we need to re-register - */ - private SecurityAuthority authority = null; - - /** - * The persistent presence operations set. - */ - private OperationSetPersistentPresenceYahooImpl persistentPresence = null; - - /** - * Typing notifications operations set. - */ - private OperationSetTypingNotificationsYahooImpl typingNotifications = null; - - /** - * The logo corresponding to the msn protocol. - */ - private ProtocolIconYahooImpl yahooIcon - = new ProtocolIconYahooImpl(); - - /** - * The connection listener. - */ - private YahooConnectionListener connectionListener = null; - - /** - * Returns the state of the registration of this protocol provider - * @return the RegistrationState that this provider is - * currently in or null in case it is in a unknown state. - */ - public RegistrationState getRegistrationState() - { - if(yahooSession != null && - yahooSession.getSessionStatus() == StatusConstants.MESSAGING) - return RegistrationState.REGISTERED; - else - return RegistrationState.UNREGISTERED; - } - - /** - * Starts the registration process. Connection details such as - * registration server, user name/number are provided through the - * configuration service through implementation specific properties. - * - * @param authority the security authority that will be used for resolving - * any security challenges that may be returned during the - * registration or at any moment while wer're registered. - * @throws OperationFailedException with the corresponding code it the - * registration fails for some reason (e.g. a networking error or an - * implementation problem). - */ - public void register(final SecurityAuthority authority) - throws OperationFailedException - { - if(authority == null) - throw new IllegalArgumentException( - "The register method needs a valid non-null authority impl " - + " in order to be able and retrieve passwords."); - - this.authority = authority; - - connectAndLogin(authority, SecurityAuthority.AUTHENTICATION_REQUIRED); - } - - /** - * Connects and logins to the server - * @param authority SecurityAuthority - * @param authReasonCode the authentication reason code, which should - * indicate why are making an authentication request - * @throws OperationFailedException if login parameters - * as server port are not correct - */ - private void connectAndLogin( SecurityAuthority authority, - int authReasonCode) - throws OperationFailedException - { - synchronized(initializationLock) - { - //verify whether a password has already been stored for this account - String password = YahooActivator. - getProtocolProviderFactory().loadPassword(getAccountID()); - - // If the password hasn't been saved or the reason is one of those - // listed below we need to ask the user for credentials again. - if (password == null - || authReasonCode == SecurityAuthority.WRONG_PASSWORD - || authReasonCode == SecurityAuthority.WRONG_USERNAME) - { - //create a default credentials object - UserCredentials credentials = new UserCredentials(); - credentials.setUserName(getAccountID().getUserID()); - - //request a password from the user - credentials = authority.obtainCredentials( - getAccountID().getDisplayName(), - credentials, - authReasonCode); - - // in case user has canceled the login window - if(credentials == null) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, ""); - return; - } - - //extract the password the user passed us. - char[] pass = credentials.getPassword(); - - // the user didn't provide us a password (canceled the operation) - if(pass == null) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, ""); - return; - } - password = new String(pass); - - if (credentials.isPasswordPersistent()) - { - YahooActivator.getProtocolProviderFactory() - .storePassword(getAccountID(), password); - } - } - - yahooSession = new YahooSession(); - connectionListener = new YahooConnectionListener(); - yahooSession.addSessionListener(connectionListener); - - try - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.REGISTERING, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - - yahooSession.login(getAccountID().getUserID(), password); - - if(yahooSession.getSessionStatus()==StatusConstants.MESSAGING) - { - persistentPresence.fireProviderStatusChangeEvent( - persistentPresence.getPresenceStatus(), - persistentPresence.yahooStatusToPresenceStatus( - yahooSession.getStatus())); - - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.REGISTERED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - } - else - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - } - } - catch (LoginRefusedException ex) - { - if(ex.getStatus() == StatusConstants.STATUS_BADUSERNAME) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.AUTHENTICATION_FAILED, - RegistrationStateChangeEvent.REASON_NON_EXISTING_USER_ID, - null); - - reregister(SecurityAuthority.WRONG_USERNAME); - } - else if(ex.getStatus() == StatusConstants.STATUS_BAD) - { - YahooActivator.getProtocolProviderFactory() - .storePassword(getAccountID(), null); - - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.AUTHENTICATION_FAILED, - RegistrationStateChangeEvent.REASON_AUTHENTICATION_FAILED, - null); - - // Try to re-register and ask the user to retype the password. - reregister(SecurityAuthority.WRONG_PASSWORD); - } - else if(ex.getStatus() == StatusConstants.STATUS_LOCKED) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.AUTHENTICATION_FAILED, - RegistrationStateChangeEvent.REASON_RECONNECTION_RATE_LIMIT_EXCEEDED, - null); - } - } - catch (IOException ex) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - } - catch (DnssecRuntimeException ex) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, null); - } - } - } - - /** - * Reconnects if fails fire connection failed. - * @param reasonCode the appropriate SecurityAuthority reasonCode, - * which would specify the reason for which we're re-calling the login. - */ - void reregister(int reasonCode) - { - try - { - connectAndLogin(authority, reasonCode); - } - catch (OperationFailedException ex) - { - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - } - } - - /** - * Ends the registration of this protocol provider with the service. - */ - public void unregister() - { - unregisterInternal(true); - } - - /** - * Unregister and fire the event if requested - * @param fireEvent boolean - */ - void unregisterInternal(boolean fireEvent) - { - RegistrationState currRegState = getRegistrationState(); - - if(fireEvent) - fireRegistrationStateChanged( - currRegState, - RegistrationState.UNREGISTERING, - RegistrationStateChangeEvent.REASON_USER_REQUEST, - null); - - try - { - if(connectionListener != null && yahooSession != null) - { - yahooSession.removeSessionListener(connectionListener); - connectionListener = null; - } - - if((yahooSession != null) - && (yahooSession.getSessionStatus() == StatusConstants.MESSAGING)) - yahooSession.logout(); - } - catch(Exception ex) - { - logger.error("Cannot logout! ", ex); - } - - yahooSession = null; - - if(fireEvent) - fireRegistrationStateChanged( - currRegState, - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_USER_REQUEST, - null); - } - - /* - * (non-Javadoc) - * - * @see net.java.sip.communicator.service.protocol.ProtocolProviderService# - * isSignallingTransportSecure() - */ - public boolean isSignalingTransportSecure() - { - return false; - } - - /** - * Returns the "transport" protocol of this instance used to carry the - * control channel for the current protocol service. - * - * @return The "transport" protocol of this instance: TCP. - */ - public TransportProtocol getTransportProtocol() - { - return TransportProtocol.TCP; - } - - /** - * Returns the short name of the protocol that the implementation of this - * provider is based upon (like SIP, Msn, ICQ/AIM, or others for - * example). - * - * @return a String containing the short name of the protocol this - * service is taking care of. - */ - public String getProtocolName() - { - return ProtocolNames.YAHOO; - } - - /** - * Initialized the service implementation, and puts it in a sate where it - * could interoperate with other services. It is strongly recomended that - * properties in this Map be mapped to property names as specified by - * AccountProperties. - * - * @param screenname the account id/uin/screenname of the account that - * we're about to create - * @param accountID the identifier of the account that this protocol - * provider represents. - * - * @see net.java.sip.communicator.service.protocol.AccountID - */ - protected void initialize(String screenname, - AccountID accountID) - { - synchronized(initializationLock) - { - this.accountID = accountID; - - addSupportedOperationSet( - OperationSetInstantMessageTransform.class, - new OperationSetInstantMessageTransformImpl()); - - //initialize the presence operationset - persistentPresence - = new OperationSetPersistentPresenceYahooImpl(this); - addSupportedOperationSet( - OperationSetPersistentPresence.class, - persistentPresence); - //register it once again for those that simply need presence - addSupportedOperationSet( - OperationSetPresence.class, - persistentPresence); - - //initialize the IM operation set - addSupportedOperationSet( - OperationSetBasicInstantMessaging.class, - new OperationSetBasicInstantMessagingYahooImpl(this)); - - //initialize the multi user chat operation set - addSupportedOperationSet( - OperationSetAdHocMultiUserChat.class, - new OperationSetAdHocMultiUserChatYahooImpl(this)); - - //initialize the typing notifications operation set - typingNotifications - = new OperationSetTypingNotificationsYahooImpl(this); - addSupportedOperationSet( - OperationSetTypingNotifications.class, - typingNotifications); - - addSupportedOperationSet( - OperationSetFileTransfer.class, - new OperationSetFileTransferYahooImpl(this)); - - isInitialized = true; - } - } - - /** - * Makes the service implementation close all open sockets and release - * any resources that it might have taken and prepare for - * shutdown/garbage collection. - */ - public void shutdown() - { - synchronized(initializationLock){ - unregisterInternal(false); - yahooSession = null; - isInitialized = false; - } - } - - /** - * Returns true if the provider service implementation is initialized and - * ready for use by other services, and false otherwise. - * - * @return true if the provider is initialized and ready for use and false - * otherwise - */ - public boolean isInitialized() - { - return isInitialized; - } - - /** - * Returns the AccountID that uniquely identifies the account represented - * by this instance of the ProtocolProviderService. - * @return the id of the account represented by this provider. - */ - public AccountID getAccountID() - { - return accountID; - } - - /** - * Returns the YahooSessionopened by this provider - * @return a reference to the Session last opened by this - * provider. - */ - YahooSession getYahooSession() - { - return yahooSession; - } - - /** - * Creates a RegistrationStateChange event corresponding to the specified - * old and new states and notifies all currently registered listeners. - * - * @param oldState the state that the provider had before the change - * occurred - * @param newState the state that the provider is currently in. - * @param reasonCode a value corresponding to one of the REASON_XXX fields - * of the RegistrationStateChangeEvent class, indicating the reason for - * this state transition. - * @param reason a String further explaining the reason code or null if - * no such explanation is necessary. - */ - @Override - public void fireRegistrationStateChanged( RegistrationState oldState, - RegistrationState newState, - int reasonCode, - String reason) - { - if(newState.equals(RegistrationState.UNREGISTERED)) - { - unregisterInternal(false); - yahooSession = null; - } - - super.fireRegistrationStateChanged(oldState, newState, reasonCode, reason); - } - - /** - * Listens when we are logged in the server - * or incoming exception in the lib impl. - */ - private class YahooConnectionListener - extends SessionAdapter - { - /** - * Yahoo has logged us off the system, or the connection was lost - * - * @param ev the event - */ - @Override - public void connectionClosed(SessionEvent ev) - { - if(isRegistered()) - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.CONNECTION_FAILED, - RegistrationStateChangeEvent.REASON_NOT_SPECIFIED, null); - } - - /** - * Some exception has occurred in stack. - * @param ev - */ - @Override - public void inputExceptionThrown(SessionExceptionEvent ev) - { - if(ev.getException() instanceof YMSG9BadFormatException) - { - logger.error("Yahoo protocol exception occured exception", - ev.getException()); - logger.error("Yahoo protocol exception occured exception cause", - ev.getException().getCause()); - } - else - logger.error( - "Yahoo protocol exception occured", ev.getException()); - - unregisterInternal(false); - if(isRegistered()) - fireRegistrationStateChanged( - getRegistrationState(), - RegistrationState.UNREGISTERED, - RegistrationStateChangeEvent.REASON_INTERNAL_ERROR, null); - } - } - - /** - * Returns the yahoo protocol icon. - * @return the yahoo protocol icon - */ - public ProtocolIcon getProtocolIcon() - { - return yahooIcon; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/RootContactGroupYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/RootContactGroupYahooImpl.java deleted file mode 100644 index 856bb30..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/RootContactGroupYahooImpl.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * A dummy ContactGroup implementation representing the ContactList root for - * Yahoo contact lists. - * @author Damian Minkov - */ -public class RootContactGroupYahooImpl - extends AbstractContactGroupYahooImpl -{ - private String ROOT_CONTACT_GROUP_NAME = "ContactListRoot"; - private List subGroups = new LinkedList(); - private boolean isResolved = false; - - /** - * An empty list that we use when returning an iterator. - */ - private List dummyContacts = new LinkedList(); - - private final ProtocolProviderServiceYahooImpl protocolProvider; - - /** - * Creates a ContactGroup instance. - */ - RootContactGroupYahooImpl(ProtocolProviderServiceYahooImpl protocolProvider) - { - this.protocolProvider = protocolProvider; - } - - /** - * The ContactListRoot is the only group that can contain subgroups. - * - * @return true (always) - */ - public boolean canContainSubgroups() - { - return true; - } - - /** - * Returns the name of this group which is always - * ROOT_CONTACT_GROUP_NAME. - * - * @return a String containing the name of this group. - */ - public String getGroupName() - { - return ROOT_CONTACT_GROUP_NAME; - } - - /** - * Adds the specified group to the end of the list of sub groups. - * @param group the group to add. - */ - void addSubGroup(ContactGroupYahooImpl group) - { - subGroups.add(group); - } - - /** - * Removes the specified from the list of sub groups - * @param group the group to remove. - */ - void removeSubGroup(ContactGroupYahooImpl group) - { - removeSubGroup(subGroups.indexOf(group)); - } - - /** - * Removes the sub group with the specified index. - * @param index the index of the group to remove - */ - void removeSubGroup(int index) - { - subGroups.remove(index); - } - - /** - * Returns the number of subgroups contained by this - * RootContactGroupImpl. - * - * @return an int indicating the number of subgroups that this - * ContactGroup contains. - */ - public int countSubgroups() - { - return subGroups.size(); - } - - /** - * Returns null as this is the root contact group. - * @return null as this is the root contact group. - */ - public ContactGroup getParentContactGroup() - { - return null; - } - - /** - * Returns the subgroup with the specified index. - * - * @param index the index of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(int index) - { - return subGroups.get(index); - } - - /** - * Returns the subgroup with the specified name. - * @param groupName the name of the ContactGroup to retrieve. - * @return the ContactGroup with the specified index. - */ - public ContactGroup getGroup(String groupName) - { - Iterator subgroups = subgroups(); - while (subgroups.hasNext()) - { - ContactGroup grp = subgroups.next(); - - if (grp.getGroupName().equals(groupName)) - return grp; - } - - return null; - } - - /** - * Returns an iterator over the sub groups that this - * ContactGroup contains. - * - * @return a java.util.Iterator over the ContactGroup - * children of this group (i.e. subgroups). - */ - public Iterator subgroups() - { - return subGroups.iterator(); - } - - /** - * Returns the number, which is always 0, of Contact members - * of this ContactGroup - * @return an int indicating the number of Contacts, members - * of this ContactGroup. - */ - public int countContacts() - { - return dummyContacts.size(); - } - - /** - * Returns an Iterator over all contacts, member of this - * ContactGroup. - * @return a java.util.Iterator over all contacts inside this - * ContactGroup - */ - public Iterator contacts() - { - return dummyContacts.iterator(); - } - - /** - * Returns the Contact with the specified address or - * identifier. - * @param id the addres or identifier of the Contact we are - * looking for. - * @return the Contact with the specified id or address. - */ - public Contact getContact(String id) - { - //no contacts in the root group for this yahoo impl. - return null; - } - - - /** - * Returns a string representation of the root contact group that contains - * all subgroups and subcontacts of this group. - * - * @return a string representation of this root contact group. - */ - @Override - public String toString() - { - StringBuffer buff = new StringBuffer(getGroupName()); - buff.append(".subGroups=" + countSubgroups() + ":\n"); - - Iterator subGroups = subgroups(); - while (subGroups.hasNext()) - { - ContactGroup group = subGroups.next(); - buff.append(group.toString()); - if (subGroups.hasNext()) - buff.append("\n"); - } - return buff.toString(); - } - - /** - * Returns the protocol provider that this group belongs to. - * @return a regerence to the ProtocolProviderService instance that this - * ContactGroup belongs to. - */ - public ProtocolProviderService getProtocolProvider() - { - return protocolProvider; - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - public boolean isPersistent() - { - return true; - } - - /** - * Returns null as no persistent data is required and the group name is - * sufficient for restoring the contact. - *

    - * @return null as no such data is needed. - */ - public String getPersistentData() - { - return null; - } - - /** - * Determines whether or not this group has been resolved against the - * server. Unresolved groups are used when initially loading a contact - * list that has been stored in a local file until the presence operation - * set has managed to retrieve all the contact list from the server and has - * properly mapped groups to their on-line buddies. - * @return true if the group has been resolved (mapped against a buddy) - * and false otherwise. - */ - public boolean isResolved() - { - return isResolved; - } - - /** - * Returns a String that uniquely represnets the group. In this we - * use the name of the group as an identifier. This may cause problems - * though, in clase the name is changed by some other application between - * consecutive runs of the sip-communicator. - * - * @return a String representing this group in a unique and persistent - * way. - */ - public String getUID() - { - return getGroupName(); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java deleted file mode 100644 index 6bfb239..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/ServerStoredContactListYahooImpl.java +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; -import ymsg.network.*; -import ymsg.network.event.*; - -/** - * This class encapsulates the Roster class. Once created, it will - * register itself as a listener to the encapsulated Roster and modify it's - * local copy of Contacts and ContactGroups every time an event is generated - * by the underlying framework. The class would also generate - * corresponding sip-communicator events to all events coming from smack. - * - * @author Damian Minkov - * @author Emil Ivov - */ -public class ServerStoredContactListYahooImpl -{ - private static final Logger logger = - Logger.getLogger(ServerStoredContactListYahooImpl.class); - - /** - * If there is no group and we add contact with no parent - * a default group is created with name : DEFAULT_GROUP_NAME - */ - private static final String DEFAULT_GROUP_NAME = "General"; - - /** - * The root contagroup. The container for all yahoo buddies and groups. - */ - private final RootContactGroupYahooImpl rootGroup; - - /** - * The operation set that created us and that we could use when dispatching - * subscription events. - */ - private final OperationSetPersistentPresenceYahooImpl parentOperationSet; - - /** - * The provider that is on top of us. - */ - private final ProtocolProviderServiceYahooImpl yahooProvider; - - private YahooSession yahooSession = null; - - /** - * Listeners that would receive event notifications for changes in group - * names or other properties, removal or creation of groups. - */ - private Vector serverStoredGroupListeners - = new Vector(); - - private ContactListModListenerImpl contactListModListenerImpl - = new ContactListModListenerImpl(); - - /** - * Handler for incoming authorization requests. - */ - private AuthorizationHandler handler = null; - - private Hashtable addedCustomYahooIds - = new Hashtable(); - - /** - * Creates a ServerStoredContactList wrapper for the specified BuddyList. - * - * @param parentOperationSet the operation set that created us and that - * we could use for dispatching subscription events - * @param provider the provider that has instantiated us. - */ - ServerStoredContactListYahooImpl( - OperationSetPersistentPresenceYahooImpl parentOperationSet, - ProtocolProviderServiceYahooImpl provider) - { - //We need to init these as early as possible to ensure that the provider - //and the operationsset would not be null in the incoming events. - this.parentOperationSet = parentOperationSet; - - this.yahooProvider = provider; - this.rootGroup = new RootContactGroupYahooImpl(this.yahooProvider); - } - - /** - * Handler for incoming authorization requests. - * - * @param handler an instance of an AuthorizationHandler for - * authorization requests coming from other users requesting - * permission add us to their contact list. - */ - public void setAuthorizationHandler(AuthorizationHandler handler) - { - this.handler = handler; - } - - /** - * Returns the root group of the contact list. - * - * @return the root ContactGroup for the ContactList - */ - public ContactGroup getRootGroup() - { - return rootGroup; - } - - /** - * Registers the specified group listener so that it would receive events - * on group modification/creation/destruction. - * @param listener the ServerStoredGroupListener to register for group - * events - */ - void addGroupListener(ServerStoredGroupListener listener) - { - synchronized(serverStoredGroupListeners) - { - if(!serverStoredGroupListeners.contains(listener)) - serverStoredGroupListeners.add(listener); - } - } - - /** - * Removes the specified group listener so that it won't receive further - * events on group modification/creation/destruction. - * @param listener the ServerStoredGroupListener to unregister - */ - void removeGroupListener(ServerStoredGroupListener listener) - { - synchronized(serverStoredGroupListeners) - { - this.serverStoredGroupListeners.remove(listener); - } - } - - /** - * Creates the corresponding event and notifies all - * ServerStoredGroupListeners that the source group has been - * removed, changed, renamed or whatever happened to it. - * @param group the ContactGroup that has been created/modified/removed - * @param eventID the id of the event to generate. - */ - private void fireGroupEvent(ContactGroupYahooImpl group, int eventID) - { - //bail out if no one's listening - if(parentOperationSet == null){ - if (logger.isDebugEnabled()) - logger.debug("No presence op. set available. Bailing out."); - return; - } - - ServerStoredGroupEvent evt = new ServerStoredGroupEvent( - group - , eventID - , parentOperationSet.getServerStoredContactListRoot() - , yahooProvider - , parentOperationSet); - - if (logger.isTraceEnabled()) - logger.trace("Will dispatch the following grp event: " + evt); - - Iterable listeners; - synchronized (serverStoredGroupListeners) - { - listeners - = new ArrayList( - serverStoredGroupListeners); - } - - for (ServerStoredGroupListener listener : listeners) - { - try{ - if (eventID == ServerStoredGroupEvent.GROUP_REMOVED_EVENT) - listener.groupRemoved(evt); - else if (eventID == ServerStoredGroupEvent.GROUP_RENAMED_EVENT) - listener.groupNameChanged(evt); - else if (eventID == ServerStoredGroupEvent.GROUP_CREATED_EVENT) - listener.groupCreated(evt); - else if (eventID == ServerStoredGroupEvent.GROUP_RESOLVED_EVENT) - listener.groupResolved(evt); - }catch(Exception ex){ - logger.warn("Unhandled Exception! ", ex); - } - } - } - - /** - * Make the parent persistent presence operation set dispatch a contact - * removed event. - * @param parentGroup the group where that the removed contact belonged to. - * @param contact the contact that was removed. - */ - private void fireContactRemoved( ContactGroup parentGroup, - ContactYahooImpl contact) - { - //bail out if no one's listening - if(parentOperationSet == null){ - if (logger.isDebugEnabled()) - logger.debug("No presence op. set available. Bailing out."); - return; - } - - //dispatch - parentOperationSet.fireSubscriptionEvent( - contact, parentGroup, SubscriptionEvent.SUBSCRIPTION_REMOVED); - } - - /** - * Make the parent persistent presence operation set dispatch a subscription - * moved event. - * @param oldParentGroup the group where the source contact was located - * before being moved - * @param newParentGroup the group that the source contact is currently in. - * @param contact the contact that was added - */ - private void fireContactMoved( ContactGroup oldParentGroup, - ContactGroupYahooImpl newParentGroup, - ContactYahooImpl contact) - { - //bail out if no one's listening - if(parentOperationSet == null){ - if (logger.isDebugEnabled()) - logger.debug("No presence op. set available. Bailing out."); - return; - } - - //dispatch - parentOperationSet.fireSubscriptionMovedEvent( - contact, oldParentGroup, newParentGroup); - } - - /** - * Returns a reference to the provider that created us. - * @return a reference to a ProtocolProviderServiceImpl instance. - */ - ProtocolProviderServiceYahooImpl getParentProvider() - { - return yahooProvider; - } - - /** - * Returns the ConntactGroup with the specified name or null if no such - * group was found. - *

    - * @param name the name of the group we're looking for. - * @return a reference to the ContactGroupYahooImpl instance we're looking - * for or null if no such group was found. - */ - public ContactGroupYahooImpl findContactGroup(String name) - { - String nameToLookFor = replaceIllegalChars(name); - Iterator contactGroups = rootGroup.subgroups(); - - while(contactGroups.hasNext()) - { - ContactGroupYahooImpl contactGroup - = (ContactGroupYahooImpl) contactGroups.next(); - - if (contactGroup.getGroupName().equals(nameToLookFor)) - return contactGroup; - } - - return null; - } - - /** - * Returns the Contact with the specified id or null if - * no such id was found. - * - * @param id the id of the contact to find. - * @return the Contact carrying the specified - * screenName or null if no such contact exits. - */ - public ContactYahooImpl findContactById(String id) - { - Iterator contactGroups = rootGroup.subgroups(); - ContactYahooImpl result = null; - - while(contactGroups.hasNext()) - { - ContactGroupYahooImpl contactGroup - = (ContactGroupYahooImpl) contactGroups.next(); - - result = contactGroup.findContact(id); - - if (result != null) - return result; - } - - return null; - } - - /** - * Returns the Contact corresponding to the specified YahooUser - * or null if no such id was found. - * - * @param yahooUser the YahooUser of the contact to find. - * @return the Contact carrying the specified - * screenName or null if no such contact exits. - */ - public ContactYahooImpl findContactByYahooUser(YahooUser yahooUser) - { - return findContactById(yahooUser.getId().toLowerCase()); - } - - /** - * Returns the ContactGroup containing the specified contact or null - * if no such group or contact exist. - * - * @param child the contact whose parent group we're looking for. - * @return the ContactGroup containing the specified - * contact or null if no such groupo or contact - * exist. - */ - public ContactGroup findContactGroup(ContactYahooImpl child) - { - Iterator contactGroups = rootGroup.subgroups(); - String contactAddress = child.getAddress(); - - while(contactGroups.hasNext()) - { - ContactGroupYahooImpl contactGroup - = (ContactGroupYahooImpl) contactGroups.next(); - - if( contactGroup.findContact(contactAddress)!= null) - return contactGroup; - } - - return null; - } - - /** - * Adds a new contact with the specified screenname to the list under a - * default location. - * @param id the id of the contact to add. - * @throws OperationFailedException - */ - public void addContact(String id) - throws OperationFailedException - { - ContactGroupYahooImpl parent = getFirstPersistentGroup(); - - if(parent == null) - { - // if there is no group create it - parent = createUnresolvedContactGroup(DEFAULT_GROUP_NAME); - } - - addContact(parent, id); - } - - /** - * Adds a new contact with the specified screenname to the list under the - * specified group. - * @param id the id of the contact to add. - * @param parent the group under which we want the new contact placed. - * @throws OperationFailedException if the contact already exist - */ - public void addContact(final ContactGroupYahooImpl parent, String id) - throws OperationFailedException - { - if (logger.isTraceEnabled()) - logger.trace("Adding contact " + id + " to parent=" + parent); - - //if the contact is already in the contact list and is not volatile, - //then only broadcast an event - ContactYahooImpl existingContact = findContactById(id); - - if( existingContact != null - && existingContact.isPersistent() ) - { - if (logger.isDebugEnabled()) - logger.debug("Contact " + id + " already exists."); - throw new OperationFailedException( - "Contact " + id + " already exists.", - OperationFailedException.SUBSCRIPTION_ALREADY_EXISTS); - } - - if(id.indexOf("@") > -1 ) - addedCustomYahooIds.put(YahooSession.getYahooUserID(id), id); - - try - { - yahooSession.addFriend(YahooSession.getYahooUserID(id), - parent.getGroupName()); - } - catch(IOException ex) - { - throw new OperationFailedException( - "Contact cannot be added " + id, - OperationFailedException.NETWORK_FAILURE); - } - } - - /** - * Creates a non persistent contact for the specified address. This would - * also create (if necessary) a group for volatile contacts that would not - * be added to the server stored contact list. This method would have no - * effect on the server stored contact list. - * @param id the address of the contact to create. - * @return the newly created volatile ContactImpl - */ - ContactYahooImpl createVolatileContact(String id) - { - if (logger.isTraceEnabled()) - logger.trace("Creating volatile contact " + id); - ContactYahooImpl newVolatileContact = - new ContactYahooImpl(id, this, false, false, true); - - //Check whether a volatile group already exists and if not create one - ContactGroupYahooImpl theVolatileGroup = getNonPersistentGroup(); - - //if the parent group is null then create it - if (theVolatileGroup == null) - { - theVolatileGroup = new VolatileContactGroupYahooImpl( - YahooActivator.getResources().getI18NString( - "service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME"), - this); - - theVolatileGroup.addContact(newVolatileContact); - - this.rootGroup.addSubGroup(theVolatileGroup); - - fireGroupEvent(theVolatileGroup - , ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - else - { - theVolatileGroup.addContact(newVolatileContact); - - fireContactAdded(theVolatileGroup, newVolatileContact); - } - - return newVolatileContact; - } - - - /** - * Creates a non resolved contact for the specified address and inside the - * specified group. The newly created contact would be added to the local - * contact list as a standard contact but when an event is received from the - * server concerning this contact, then it will be reused and only its - * isResolved field would be updated instead of creating the whole contact - * again. - * - * @param parentGroup the group where the unersolved contact is to be - * created - * @param id the Address of the contact to create. - * @return the newly created unresolved ContactImpl - */ - ContactYahooImpl createUnresolvedContact(ContactGroup parentGroup, - String id) - { - if (logger.isTraceEnabled()) - logger.trace("Creating unresolved contact " + id - + " to parent=" + parentGroup); - - ContactYahooImpl existingContact = findContactById(id); - - if( existingContact != null) - { - return existingContact; - } - - ContactYahooImpl newUnresolvedContact - = new ContactYahooImpl(id, this, false, true, false); - - if(parentGroup instanceof ContactGroupYahooImpl) - ((ContactGroupYahooImpl)parentGroup). - addContact(newUnresolvedContact); - - fireContactAdded(parentGroup, newUnresolvedContact); - - return newUnresolvedContact; - } - - /** - * Creates a non resolved contact group for the specified name. The newly - * created group would be added to the local contact list as any other group - * but when an event is received from the server concerning this group, then - * it will be reused and only its isResolved field would be updated instead - * of creating the whole group again. - *

    - * @param groupName the name of the group to create. - * @return the newly created unresolved ContactGroupImpl - */ - ContactGroupYahooImpl createUnresolvedContactGroup(String groupName) - { - ContactGroupYahooImpl existingGroup = findContactGroup(groupName); - - if( existingGroup != null ) - { - if (logger.isDebugEnabled()) - logger.debug("ContactGroup " + groupName + " already exists."); - return existingGroup; - } - - ContactGroupYahooImpl newUnresolvedGroup = - new ContactGroupYahooImpl(groupName, this); - - this.rootGroup.addSubGroup(newUnresolvedGroup); - - fireGroupEvent(newUnresolvedGroup - , ServerStoredGroupEvent.GROUP_CREATED_EVENT); - - return newUnresolvedGroup; - } - - /** - * Creates the specified group on the server stored contact list. - * @param groupName a String containing the name of the new group. - * @throws OperationFailedException with code CONTACT_GROUP_ALREADY_EXISTS - * if the group we're trying to create is already in our contact list. - */ - public void createGroup(String groupName) - throws OperationFailedException - { - if (logger.isTraceEnabled()) - logger.trace("Creating group: " + groupName); - - ContactGroupYahooImpl existingGroup = findContactGroup(groupName); - - if( existingGroup != null && existingGroup.isPersistent() ) - { - if (logger.isDebugEnabled()) - logger.debug("ContactGroup " + groupName + " already exists."); - throw new OperationFailedException( - "ContactGroup " + groupName + " already exists.", - OperationFailedException.CONTACT_GROUP_ALREADY_EXISTS); - } - - // create unresolved group if friend is added - group will be resolved - createUnresolvedContactGroup(groupName); - } - - /** - * Removes the specified group from the buddy list. - * @param groupToRemove the group that we'd like removed. - */ - @SuppressWarnings("unchecked") //jymsg legacy code - public void removeGroup(ContactGroupYahooImpl groupToRemove) - { - // to remove group just remove all the contacts in it - - if (logger.isTraceEnabled()) - logger.trace("removing group " + groupToRemove); - - // if its not persistent group just remove it - if(!groupToRemove.isPersistent() || !groupToRemove.isResolved()) - { - rootGroup.removeSubGroup(groupToRemove); - fireGroupEvent(groupToRemove, - ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - return; - } - - Vector contacts - = groupToRemove.getSourceGroup().getMembers(); - - if(contacts.size() == 0) - { - // the group is empty just remove it - rootGroup.removeSubGroup(groupToRemove); - fireGroupEvent(groupToRemove, - ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - return; - } - - /* - * ContactGroupYahooImpl#getGroupName() isn't a plain getter so - * performance-wise we're better off not calling it multiple times in - * the following loop. - */ - String groupToRemoveName = groupToRemove.getGroupName(); - - for (YahooUser item : contacts) - { - try - { - yahooSession.removeFriend(item.getId(), groupToRemoveName); - } - catch(IOException ex) - { - if (logger.isInfoEnabled()) - logger.info("Cannot Remove contact " + item.getId()); - } - } - } - - /** - * Removes a contact from the serverside list - * Event will come for successful operation - * @param contactToRemove ContactYahooImpl - */ - void removeContact(ContactYahooImpl contactToRemove) - { - if (logger.isTraceEnabled()) - logger.trace("Removing yahoo contact " - + contactToRemove.getSourceContact()); - - if(contactToRemove.isVolatile()) - { - ContactGroupYahooImpl parent = - (ContactGroupYahooImpl)contactToRemove.getParentContactGroup(); - - parent.removeContact(contactToRemove); - fireContactRemoved(parent, contactToRemove); - return; - } - - try - { - yahooSession.removeFriend( - contactToRemove.getSourceContact().getId(), - contactToRemove.getParentContactGroup().getGroupName()); - } - catch(IOException ex) - { - if (logger.isInfoEnabled()) - logger.info("Cannot Remove contact " + contactToRemove); - } - } - - /** - * Renames the specified group according to the specified new name.. - * @param groupToRename the group that we'd like removed. - * @param newName the new name of the group - */ - public void renameGroup(ContactGroupYahooImpl groupToRename, String newName) - { - // not working - /* - try - { - yahooSession.renameGroup(groupToRename.getGroupName(), newName); - } - catch(IOException ex) - { - if (logger.isInfoEnabled()) - logger.info("Cannot rename group " + groupToRename); - } - - fireGroupEvent(groupToRename, - ServerStoredGroupEvent.GROUP_RENAMED_EVENT); - */ - } - - /** - * Moves the specified contact to the group indicated by - * newParent. - * @param contact the contact that we'd like moved under the new group. - * @param newParent the group where we'd like the parent placed. - */ - public void moveContact(ContactYahooImpl contact, - ContactGroupYahooImpl newParent) - { - String userID = contact.getID(); - try - { - contactListModListenerImpl. - waitForMove(userID, - contact.getParentContactGroup().getGroupName()); - - yahooSession.addFriend( - userID, - newParent.getGroupName()); - } - catch(IOException ex) - { - contactListModListenerImpl.removeWaitForMove(userID); - logger.error("Contact cannot be added " + ex.getMessage()); - } - } - - /** - * Returns the volatile group - * - * @return ContactGroupYahooImpl - */ - private ContactGroupYahooImpl getNonPersistentGroup() - { - for (int i = 0; i < getRootGroup().countSubgroups(); i++) - { - ContactGroupYahooImpl gr = - (ContactGroupYahooImpl)getRootGroup().getGroup(i); - - if(!gr.isPersistent()) - return gr; - } - - return null; - } - - /** - * Returns the first persistent group - * - * @return ContactGroupIcqImpl - */ - private ContactGroupYahooImpl getFirstPersistentGroup() - { - for (int i = 0; i < getRootGroup().countSubgroups(); i++) - { - ContactGroupYahooImpl gr = - (ContactGroupYahooImpl)getRootGroup().getGroup(i); - - if(gr.isPersistent()) - return gr; - } - - return null; - } - - /** - * Make the parent persistent presence operation set dispatch a contact - * added event. - * @param parentGroup the group where the new contact was added - * @param contact the contact that was added - */ - void fireContactAdded( ContactGroup parentGroup, - ContactYahooImpl contact) - { - //bail out if no one's listening - if(parentOperationSet == null){ - if (logger.isDebugEnabled()) - logger.debug("No presence op. set available. Bailing out."); - return; - } - - //dispatch - parentOperationSet.fireSubscriptionEvent( - contact, parentGroup, SubscriptionEvent.SUBSCRIPTION_CREATED); - } - - /** - * Make the parent persistent presence operation set dispatch a contact - * resolved event. - * @param parentGroup the group that the resolved contact belongs to. - * @param contact the contact that was resolved - */ - void fireContactResolved( ContactGroup parentGroup, - ContactYahooImpl contact) - { - //bail out if no one's listening - if(parentOperationSet == null){ - if (logger.isDebugEnabled()) - logger.debug("No presence op. set available. Bailing out."); - return; - } - - //dispatch - parentOperationSet.fireSubscriptionEvent( - contact, parentGroup, SubscriptionEvent.SUBSCRIPTION_RESOLVED); - } - - /** - * When the protocol is online this method is used to fill or resolve - * the current contact list - */ - @SuppressWarnings("unchecked") //jymsg legacy code - private void initList() - { - if (logger.isTraceEnabled()) - logger.trace("Start init list of " - + yahooProvider.getAccountID().getUserID()); - - for (YahooGroup item : yahooSession.getGroups()) - { - ContactGroupYahooImpl group = findContactGroup(item.getName()); - - if(group == null) - { - // create the group as it doesn't exist - group = new ContactGroupYahooImpl( - item, item.getMembers(), this, true); - - rootGroup.addSubGroup(group); - - //tell listeners about the added group - fireGroupEvent(group, - ServerStoredGroupEvent.GROUP_CREATED_EVENT); - } - else - { - // the group exist so just resolved. The group will check and - // create or resolve its entries - group.setResolved(item); - - //fire an event saying that the group has been resolved - fireGroupEvent(group - , ServerStoredGroupEvent.GROUP_RESOLVED_EVENT); - - /** @todo if something to delete . delete it */ - } - - if (logger.isTraceEnabled()) - logger.trace("Init of group done! : " + group); - } - } - - /** - * @param name Name of the group to search - * @return The yahoo group with given name - */ - private YahooGroup findGroup(String name) - { - for (YahooGroup elem : yahooSession.getGroups()) - { - if(elem.getName().equals(name)) - return elem; - } - return null; - } - - /** - * Process incoming authorization requests. - * @param ev the event to process. - */ - void processAuthorizationRequest(SessionAuthorizationEvent ev) - { - if(handler == null) - return; - - Contact srcContact = findContactById(ev.getFrom()); - - // if there is no such contact we create it as - // volatile so we can fire notification - // and then if accepted add it in the protocol - // so we can receive its states - boolean isCurrentlyCreated = false; - if(srcContact == null) - { - srcContact = createVolatileContact(ev.getFrom()); - isCurrentlyCreated = true; - } - - AuthorizationRequest authRequest = new AuthorizationRequest(); - authRequest.setReason(ev.getMessage()); - - AuthorizationResponse authResponse = - handler.processAuthorisationRequest( - authRequest, srcContact); - - if (authResponse.getResponseCode() == AuthorizationResponse.IGNORE) - { - return; - } - else if (authResponse.getResponseCode() == AuthorizationResponse.REJECT) - { - removeContact((ContactYahooImpl)srcContact); - try - { - yahooSession.rejectFriendAuthorization( - ev, ev.getFrom(), authResponse.getReason()); - } - catch(IOException ex) - { - logger.error("cannot send auth deny", ex); - } - - return; - } - - // else we accepted it - try - { - yahooSession.acceptFriendAuthorization(ev, ev.getFrom()); - } - catch(IOException ex) - { - logger.error("cannot send auth deny", ex); - } - - if(isCurrentlyCreated) - try - { - addContact(ev.getFrom()); - } - catch (OperationFailedException ex) - { - logger.error("Cannot add friend", ex); - } - } - - /** - * Imulates firing adding contact in group and moving contact to group. - * When moving contact it is first adding to the new group then - * it is removed from the old one. - */ - private class ContactListModListenerImpl - extends SessionAdapter - { - private final Hashtable waitMove - = new Hashtable(); - - public void waitForMove(String id, String oldParent) - { - waitMove.put(id, oldParent); - } - - public void removeWaitForMove(String id) - { - waitMove.remove(id); - } - - /** - * Successfully added a friend - * friend - YahooUser of friend - * group - name of group added to - * @param ev fired event - */ - @Override - public void friendAddedReceived(SessionFriendEvent ev) - { - if (logger.isTraceEnabled()) - logger.trace("Receive event for adding a friend : " + ev); - - ContactGroupYahooImpl group = - findContactGroup(ev.getGroup()); - - if(group == null){ - if (logger.isTraceEnabled()) - logger.trace("Group not found!" + ev.getGroup()); - return; - } - - String contactID = ev.getFriend().getId(); - ContactYahooImpl contactToAdd = findContactById(contactID); - - // if group is note resolved resolve it - // this means newly created group - if(!group.isResolved()) - { - // if the contact is volatile me must remove it - // as new one will be created - if(contactToAdd != null && contactToAdd.isVolatile()) - { - ContactGroupYahooImpl parent - = (ContactGroupYahooImpl)contactToAdd - .getParentContactGroup(); - - parent.removeContact(contactToAdd); - fireContactRemoved(parent, contactToAdd); - } - - YahooGroup gr = findGroup(ev.getGroup()); - - if(gr != null) - group.setResolved(gr); - - // contact will be added when resolving the group - - return; - } - - - boolean isVolatile = false; - - if(contactToAdd == null) - { - if(addedCustomYahooIds.containsKey(contactID)) - { - String expectedContactID = - addedCustomYahooIds.remove(contactID); - - contactToAdd = - new ContactYahooImpl(expectedContactID, ev.getFriend(), - ServerStoredContactListYahooImpl.this, true, true); - } - else - { - contactToAdd = - new ContactYahooImpl(ev.getFriend(), - ServerStoredContactListYahooImpl.this, true, true); - } - } - else - { - isVolatile = contactToAdd.isVolatile(); - } - - //first check is contact is moving from a group - Object isWaitingForMove = waitMove.get(contactID); - - if(isWaitingForMove != null && isWaitingForMove instanceof String) - { - // waits for move into group - // will remove it from old group and will wait for event remove - // from group, then will fire moved to group event - String oldParent = (String)isWaitingForMove; - - group.addContact(contactToAdd); - waitMove.put(contactID, group.getSourceGroup()); - try - { - yahooSession.removeFriend(contactID, oldParent); - } - catch(IOException ex) - { - if (logger.isInfoEnabled()) - logger.info("Cannot Remove(till moving) contact :" + - contactToAdd + " from group " + oldParent); - } - return; - } - - if(isVolatile) - { - // we must remove the volatile buddy as we will add - // the persistent one. - // Volatile buddy is moving from the volatile group - // to the new one - ContactGroupYahooImpl parent = - (ContactGroupYahooImpl)contactToAdd.getParentContactGroup(); - - parent.removeContact(contactToAdd); - fireContactRemoved(parent, contactToAdd); - - contactToAdd.setPersistent(true); - contactToAdd.setResolved(ev.getFriend()); - - group.addContact(contactToAdd); - - fireContactAdded(group, contactToAdd); - waitMove.remove(contactID); - - return; - } - - group.addContact(contactToAdd); - fireContactAdded(group, contactToAdd); - } - - /** - * Successfully removed a friend - * friend - YahooUser of friend - * group - name of group removed from - * @param ev fired event - */ - @Override - public void friendRemovedReceived(SessionFriendEvent ev) - { - if (logger.isTraceEnabled()) - logger.trace("Receive event for removing a friend : " + ev); - - String contactID = ev.getFriend().getId(); - - // first check is this part of move action - Object waitForMoveObj = waitMove.get(contactID); - if(waitForMoveObj != null && waitForMoveObj instanceof YahooGroup) - { - // first get the group - oldParent - ContactGroupYahooImpl oldParent - = findContactGroup(ev.getGroup()); - ContactYahooImpl contactToRemove - = oldParent.findContact(contactID); - - oldParent.removeContact(contactToRemove); - waitMove.remove(contactID); - - ContactGroupYahooImpl newParent = - findContactGroup(((YahooGroup)waitForMoveObj).getName()); - - fireContactMoved(oldParent, newParent, contactToRemove); - return; - } - - ContactYahooImpl contactToRemove = findContactById(contactID); - - // strange we cannot find the contact to be removed - if(contactToRemove == null) - return; - - ContactGroupYahooImpl parentGroup = - (ContactGroupYahooImpl)contactToRemove. - getParentContactGroup(); - parentGroup.removeContact(contactToRemove); - fireContactRemoved(parentGroup, contactToRemove); - - // check if the group is deleted. If the contact is the last one in - // the group. The group is also deleted - if(findGroup(ev.getGroup()) == null) - { - rootGroup.removeSubGroup(parentGroup); - fireGroupEvent(parentGroup, - ServerStoredGroupEvent.GROUP_REMOVED_EVENT); - } - } - - /** - * Someone wants to add us to their friends list - * to - the target (us!) - * from - the user who wants to add us - * message - the request message text - * @param ev fired event - */ - @Override - public void contactRequestReceived(SessionEvent ev) - { - if (logger.isInfoEnabled()) - logger.info("contactRequestReceived : " + ev); - - if(handler == null || ev.getFrom() == null) - return; - - ContactYahooImpl contact = findContactById(ev.getFrom()); - - if(contact == null) - contact = createVolatileContact(ev.getFrom()); - - AuthorizationRequest request = new AuthorizationRequest(); - request.setReason(ev.getMessage()); - - AuthorizationResponse resp = - handler.processAuthorisationRequest(request, contact); - - if (resp.getResponseCode() == AuthorizationResponse.REJECT) - { - try{ - yahooSession.rejectContact(ev, resp.getReason()); - }catch(IOException ex){ - logger.error("Cannot send reject : " + ex.getMessage()); - } - } - } - - /** - * Someone has rejected our attempts to add them to our friends list - * from - the user who rejected us - * message - rejection message text - * @param ev fired event - */ - @Override - public void contactRejectionReceived(SessionEvent ev) - { - if (logger.isInfoEnabled()) - logger.info("contactRejectionReceived : " + ev); - - if(handler == null) - return; - - ContactYahooImpl contact = findContactById(ev.getFrom()); - - AuthorizationResponse resp = - new AuthorizationResponse(AuthorizationResponse.REJECT, - ev.getMessage()); - handler.processAuthorizationResponse(resp, contact); - } - - /** - * Invoked on picture received. - * @param ev fired event - */ - @Override - public void pictureReceived(SessionPictureEvent ev) - { - ContactYahooImpl contact = findContactById(ev.getFrom()); - - if(contact == null) - return; - - contact.setImage(ev.getPictureData()); - - parentOperationSet.fireContactPropertyChangeEvent( - ContactPropertyChangeEvent.PROPERTY_IMAGE, - contact, null, ev.getPictureData()); - } - - /** - * Process Authorization responses - * @param ev the event to process - */ - @Override - public void authorizationReceived(SessionAuthorizationEvent ev) - { - if(ev.isAuthorizationAccepted()) - { - if (logger.isTraceEnabled()) - logger.trace("authorizationAccepted from " + ev.getFrom()); - Contact srcContact = findContactById(ev.getFrom()); - - if(srcContact == null) - { - if (logger.isTraceEnabled()) - logger.trace("No contact found"); - } - else - handler.processAuthorizationResponse( - new AuthorizationResponse( - AuthorizationResponse.ACCEPT, - ev.getMessage()), - srcContact); - } - else if(ev.isAuthorizationDenied()) - { - if (logger.isTraceEnabled()) - logger.trace("authorizationDenied from " + ev.getFrom()); - Contact srcContact = findContactById(ev.getFrom()); - - if(srcContact == null) - { - if (logger.isTraceEnabled()) - logger.trace("No contact found"); - } - else - { - handler.processAuthorizationResponse( - new AuthorizationResponse( - AuthorizationResponse.REJECT, - ev.getMessage()), - srcContact); - try - { - removeContact((ContactYahooImpl)srcContact); - } catch (Exception ex) - { - logger.error("cannot remove denied contact : " + - srcContact, ex); - } - } - } - else if(ev.isAuthorizationRequest()) - { - if (logger.isTraceEnabled()) - logger.trace("authorizationRequestReceived from " - + ev.getFrom()); - processAuthorizationRequest(ev); - } - } - } - - /** - * Sets the yahoo session instance of the lib - * which comunicates with the server - * @param session YahooSession - */ - void setYahooSession(YahooSession session) - { - this.yahooSession = session; - session.addSessionListener(contactListModListenerImpl); - initList(); - } - - /** - * It seems that ymsg (or the Yahoo! service itself as the problem also - * appears with libpurple) would return illegal chars for names that were - * entered in cyrillic. We use this method to translate their names into - * something that we could actually display and store here. - * - * @param ymsgString the String containing illegal chars. - * - * @return a String where all illegal chars are converted into human - * readable ones - */ - static String replaceIllegalChars(String ymsgString) - { - return ymsgString.replace((char)26, '?'); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/VolatileContactGroupYahooImpl.java b/src/net/java/sip/communicator/impl/protocol/yahoo/VolatileContactGroupYahooImpl.java deleted file mode 100644 index e2c589a..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/VolatileContactGroupYahooImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Yahoo implementation of the Volatile ContactGroup interface. - * - * @author Damian Minkov - */ -public class VolatileContactGroupYahooImpl - extends ContactGroupYahooImpl -{ - /** - * This contact group name - */ - private String contactGroupName = null; - - /** - * Creates an Yahoo group using the specified group name - * @param groupName String groupname - * @param ssclCallback a callback to the server stored contact list - * we're creating. - */ - VolatileContactGroupYahooImpl( - String groupName, - ServerStoredContactListYahooImpl ssclCallback) - { - super(groupName, ssclCallback); - this.contactGroupName = groupName; - } - - /** - * Returns the name of this group. - * @return a String containing the name of this group. - */ - @Override - public String getGroupName() - { - return contactGroupName; - } - - /** - * Returns a string representation of this group, in the form - * YahooGroup.GroupName[size]{ buddy1.toString(), buddy2.toString(), ...}. - * @return a String representation of the object. - */ - @Override - public String toString() - { - StringBuffer buff = new StringBuffer("VolatileYahooGroup."); - buff.append(getGroupName()); - buff.append(", childContacts="+countContacts()+":["); - - Iterator contacts = contacts(); - - while (contacts.hasNext()) - { - Contact contact = contacts.next(); - - buff.append(contact.toString()); - if(contacts.hasNext()) - buff.append(", "); - } - return buff.append("]").toString(); - } - - /** - * Determines whether or not this contact group is being stored by the - * server. Non persistent contact groups exist for the sole purpose of - * containing non persistent contacts. - * @return true if the contact group is persistent and false otherwise. - */ - @Override - public boolean isPersistent() - { - return false; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooAccountID.java b/src/net/java/sip/communicator/impl/protocol/yahoo/YahooAccountID.java deleted file mode 100644 index 0eb0e86..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooAccountID.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -/** - * The Yahoo implementation of a sip-communicator AccountID - * - * @author Damian Minkov - */ -public class YahooAccountID - extends AccountID -{ - /** - * Creates an account id from the specified id and account properties. - * @param id the id identifying this account - * @param accountProperties any other properties necessary for the account. - */ - YahooAccountID(String id, Map accountProperties ) - { - super(YahooSession.getYahooUserID(id), - accountProperties, ProtocolNames.YAHOO, "yahoo.com"); - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooActivator.java b/src/net/java/sip/communicator/impl/protocol/yahoo/YahooActivator.java deleted file mode 100644 index 1e7ca01..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooActivator.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; - -import org.jitsi.service.configuration.*; -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Loads the Yahoo provider factory and registers it with service in the OSGI - * bundle context. - * - * @author Damian Minkov - */ -public class YahooActivator - implements BundleActivator -{ - private ServiceRegistration yahooPpFactoryServReg = null; - private static BundleContext bundleContext = null; - private static ConfigurationService configurationService = null; - - private static ProtocolProviderFactoryYahooImpl yahooProviderFactory = null; - - private static ResourceManagementService resourcesService; - - /** - * Called when this bundle is started so the Framework can perform the - * bundle-specific activities necessary to start this bundle. - * - * @param context The execution context of the bundle being started. - * @throws Exception If this method throws an exception, this bundle is - * marked as stopped and the Framework will remove this bundle's - * listeners, unregister all services registered by this bundle, and - * release all services used by this bundle. - */ - public void start(BundleContext context) throws Exception - { - bundleContext = context; - - Hashtable hashtable = new Hashtable(); - hashtable.put(ProtocolProviderFactory.PROTOCOL, ProtocolNames.YAHOO); - - yahooProviderFactory = new ProtocolProviderFactoryYahooImpl(); - - //reg the yahoo account man. - yahooPpFactoryServReg = context.registerService( - ProtocolProviderFactory.class.getName(), - yahooProviderFactory, - hashtable); - } - - /** - * Returns a reference to a ConfigurationService implementation currently - * registered in the bundle context or null if no such implementation was - * found. - * - * @return ConfigurationService a currently valid implementation of the - * configuration service. - */ - public static ConfigurationService getConfigurationService() - { - if(configurationService == null) - { - ServiceReference confReference - = bundleContext.getServiceReference( - ConfigurationService.class.getName()); - configurationService - = (ConfigurationService) bundleContext.getService(confReference); - } - return configurationService; - } - - /** - * Returns a reference to the bundle context that we were started with. - * @return a reference to the BundleContext instance that we were started - * witn. - */ - public static BundleContext getBundleContext() - { - return bundleContext; - } - - /** - * Retrurns a reference to the protocol provider factory that we have - * registered. - * @return a reference to the ProtocolProviderFactoryYahooImpl - * instance that we have registered from this package. - */ - static ProtocolProviderFactoryYahooImpl getProtocolProviderFactory() - { - return yahooProviderFactory; - } - - /** - * Called when this bundle is stopped so the Framework can perform the - * bundle-specific activities necessary to stop the bundle. - * - * @param context The execution context of the bundle being stopped. - * @throws Exception If this method throws an exception, the bundle is - * still marked as stopped, and the Framework will remove the bundle's - * listeners, unregister all services registered by the bundle, and - * release all services used by the bundle. - */ - public void stop(BundleContext context) throws Exception - { - yahooProviderFactory.stop(); - yahooPpFactoryServReg.unregister(); - } - - public static ResourceManagementService getResources() - { - if (resourcesService == null) - { - ServiceReference serviceReference = bundleContext - .getServiceReference(ResourceManagementService.class.getName()); - - if(serviceReference == null) - return null; - - resourcesService = (ResourceManagementService) bundleContext - .getService(serviceReference); - } - - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooSession.java b/src/net/java/sip/communicator/impl/protocol/yahoo/YahooSession.java deleted file mode 100644 index f24e50c..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/YahooSession.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.impl.protocol.yahoo; - -import java.io.*; - -import ymsg.network.*; - -/** - * Extends The Yahoo session to have access to some - * protected functionality - * Not working for now. - * - * @author Damian Minkov - */ -public class YahooSession - extends Session -{ - /** - * Renames a group. Not working for now - */ - public void renameGroup(String oldName, String newName) - throws IOException - { - transmitGroupRename(oldName, newName); - } - - /** - * Removes the server part from the given id - */ - public static String getYahooUserID(String id) - { - return (id.indexOf("@") > -1 ) - ? id.substring(0, id.indexOf("@")) - : id; - } - - /** - * Sending typing notifications - * @param to user we are notifing - * @param from our user id - */ - void keyTyped(String to, String from) - { - try { - transmitNotify(to, from, true, " ", NOTIFY_TYPING); - }catch(IOException e){} - } - - /** - * Sending stop typing notifications - * @param to user we are notifing - * @param from our user id - */ - void stopTyping(String to, String from) - { - try { - transmitNotify(to, from, false, " ", NOTIFY_TYPING); - }catch(IOException e){} - } -} diff --git a/src/net/java/sip/communicator/impl/protocol/yahoo/yahoo.provider.manifest.mf b/src/net/java/sip/communicator/impl/protocol/yahoo/yahoo.provider.manifest.mf deleted file mode 100644 index 39e23bf..0000000 --- a/src/net/java/sip/communicator/impl/protocol/yahoo/yahoo.provider.manifest.mf +++ /dev/null @@ -1,22 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.impl.protocol.yahoo.YahooActivator -Bundle-Name: Yahoo Protocol Provider Implementation -Bundle-Description: An Yahoo implementation of the Protocol Provider Service. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.protocol.yahoo -Import-Package: org.osgi.framework, - javax.net.ssl, - javax.swing, - javax.swing.text, - javax.xml.parsers, - javax.naming, - javax.naming.directory, - org.xml.sax, - sun.security.action, - org.jitsi.service.configuration, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.service.dns, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.yahooconstants, - net.java.sip.communicator.service.protocol.event diff --git a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java index 0658d59..81a4aad 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java +++ b/src/net/java/sip/communicator/plugin/addrbook/macosx/MacOSXAddrBookContactQuery.java @@ -419,7 +419,7 @@ public class MacOSXAddrBookContactQuery c = Category.InstantMessaging; break; case kABMSNInstantProperty: - sc = SubCategory.MSN; + sc = SubCategory.Skype; c = Category.InstantMessaging; break; case kABYahooInstantProperty: @@ -1240,12 +1240,6 @@ public class MacOSXAddrBookContactQuery case kABPhoneProperty: supportedOpSets.add(OperationSetBasicTelephony.class); break; - case kABYahooInstantProperty: - supportedOpSets.add(OperationSetBasicInstantMessaging.class); - preferredProtocols.put( - OperationSetBasicInstantMessaging.class, - ProtocolNames.YAHOO); - break; default: break; } @@ -1339,7 +1333,7 @@ public class MacOSXAddrBookContactQuery return kABAIMInstantProperty; else if(subCategories.contains(SubCategory.ICQ)) return kABICQInstantProperty; - else if(subCategories.contains(SubCategory.MSN)) + else if(subCategories.contains(SubCategory.Skype)) return kABMSNInstantProperty; else if(subCategories.contains(SubCategory.Jabber)) return kABJabberInstantProperty; diff --git a/src/net/java/sip/communicator/plugin/aimaccregwizz/aimaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/aimaccregwizz/aimaccregwizz.manifest.mf index 274310a..b5d678f 100644 --- a/src/net/java/sip/communicator/plugin/aimaccregwizz/aimaccregwizz.manifest.mf +++ b/src/net/java/sip/communicator/plugin/aimaccregwizz/aimaccregwizz.manifest.mf @@ -12,7 +12,6 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.gui, net.java.sip.communicator.service.gui.event, net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.aimconstants, net.java.sip.communicator.service.protocol.event, net.java.sip.communicator.service.protocol.icqconstants, org.jitsi.service.resources, net.java.sip.communicator.service.resources, diff --git a/src/net/java/sip/communicator/plugin/globalproxyconfig/GlobalProxyPluginActivator.java b/src/net/java/sip/communicator/plugin/globalproxyconfig/GlobalProxyPluginActivator.java index a80633e..7e9dbd5 100644 --- a/src/net/java/sip/communicator/plugin/globalproxyconfig/GlobalProxyPluginActivator.java +++ b/src/net/java/sip/communicator/plugin/globalproxyconfig/GlobalProxyPluginActivator.java @@ -175,9 +175,8 @@ public class GlobalProxyPluginActivator implements BundleActivator "http.proxyPort", globalProxyPortStr); } - // used by some protocols like yahoo - System.setProperty( - "proxySet", "true"); + // used by some protocols + System.setProperty("proxySet", "true"); } else if(globalProxyType.equals( ProxyInfo.ProxyType.SOCKS4.name()) || @@ -196,9 +195,8 @@ public class GlobalProxyPluginActivator implements BundleActivator "socksProxyPort", globalProxyPortStr); } - // used by some protocols like yahoo - System.setProperty( - "socksProxySet", "true"); + // used by some protocols + System.setProperty("socksProxySet", "true"); } Authenticator.setDefault(new AuthenticatorImpl( diff --git a/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java b/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java index 28754e4..51b3a67 100644 --- a/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java +++ b/src/net/java/sip/communicator/plugin/msofficecomm/Messenger.java @@ -28,7 +28,6 @@ import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.ServerStoredDetails.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.service.protocol.jabberconstants.*; -import net.java.sip.communicator.service.protocol.yahooconstants.*; import net.java.sip.communicator.util.*; import org.jitsi.service.configuration.*; @@ -1123,11 +1122,6 @@ public class Messenger { mistatus = MISTATUS_ON_THE_PHONE; } - else if (ProtocolNames.YAHOO.equalsIgnoreCase(protocolName) - && YahooStatusEnum.ON_THE_PHONE.equals(presenceStatus)) - { - mistatus = MISTATUS_ON_THE_PHONE; - } else if ((i == 32 /* FIXME */) && ProtocolNames.JABBER.equalsIgnoreCase(protocolName) && JabberStatusEnum.IN_A_MEETING.equalsIgnoreCase( diff --git a/src/net/java/sip/communicator/plugin/msofficecomm/msofficecomm.manifest.mf b/src/net/java/sip/communicator/plugin/msofficecomm/msofficecomm.manifest.mf index 54d8545..2a3a712 100644 --- a/src/net/java/sip/communicator/plugin/msofficecomm/msofficecomm.manifest.mf +++ b/src/net/java/sip/communicator/plugin/msofficecomm/msofficecomm.manifest.mf @@ -10,7 +10,6 @@ Import-Package: javax.swing, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.event, net.java.sip.communicator.service.protocol.jabberconstants, - net.java.sip.communicator.service.protocol.yahooconstants, net.java.sip.communicator.util, org.jitsi.service.configuration, org.jitsi.util, diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/FirstWizardPage.java b/src/net/java/sip/communicator/plugin/yahooaccregwizz/FirstWizardPage.java deleted file mode 100644 index 27e32c6..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/FirstWizardPage.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.yahooaccregwizz; - -import java.awt.*; - -import javax.swing.*; -import javax.swing.event.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -/** - * The FirstWizardPage is the page, where user could enter the uin - * and the password of the account. - * - * @author Yana Stamcheva - * @author Damian Minkov - */ -public class FirstWizardPage - extends TransparentPanel - implements WizardPage, - DocumentListener -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public static final String FIRST_PAGE_IDENTIFIER = "FirstPageIdentifier"; - - public static final String USER_NAME_EXAMPLE - = "Ex: johnsmith@yahoo.com or johnsmith"; - - private JPanel uinPassPanel = new TransparentPanel(new BorderLayout(10, 10)); - - private JPanel labelsPanel = new TransparentPanel(); - - private JPanel valuesPanel = new TransparentPanel(); - - private JLabel uinLabel = new JLabel( - Resources.getString("plugin.yahooaccregwizz.USERNAME")); - - private JLabel passLabel - = new JLabel(Resources.getString("service.gui.PASSWORD")); - - private JPanel emptyPanel = new TransparentPanel(); - - private JLabel uinExampleLabel = new JLabel(USER_NAME_EXAMPLE); - - private JTextField userIDField = new TrimTextField(); - - private JPasswordField passField = new JPasswordField(); - - private JCheckBox rememberPassBox = - new SIPCommCheckBox( - Resources.getString("service.gui.REMEMBER_PASSWORD")); - - private JPanel mainPanel = new TransparentPanel(); - - private Object nextPageIdentifier = WizardPage.SUMMARY_PAGE_IDENTIFIER; - - private YahooAccountRegistrationWizard wizard; - - private boolean isCommitted = false; - - /** - * Creates an instance of FirstWizardPage. - * - * @param wizard the parent wizard - */ - public FirstWizardPage(YahooAccountRegistrationWizard wizard) - { - - super(new BorderLayout()); - - this.wizard = wizard; - - mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); - - this.init(); - - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.labelsPanel - .setLayout(new BoxLayout(labelsPanel, BoxLayout.Y_AXIS)); - - this.valuesPanel - .setLayout(new BoxLayout(valuesPanel, BoxLayout.Y_AXIS)); - } - - /** - * Initializes all panels, buttons, etc. - */ - private void init() - { - this.mainPanel.setOpaque(false); - this.labelsPanel.setOpaque(false); - this.valuesPanel.setOpaque(false); - this.uinPassPanel.setOpaque(false); - this.emptyPanel.setOpaque(false); - - this.userIDField.getDocument().addDocumentListener(this); - this.rememberPassBox.setSelected(true); - - this.uinExampleLabel.setForeground(Color.GRAY); - this.uinExampleLabel.setFont(uinExampleLabel.getFont().deriveFont(8)); - this.emptyPanel.setMaximumSize(new Dimension(40, 35)); - this.uinExampleLabel.setBorder( - BorderFactory.createEmptyBorder(0, 0, 8, 0)); - - labelsPanel.add(uinLabel); - labelsPanel.add(emptyPanel); - labelsPanel.add(passLabel); - - valuesPanel.add(userIDField); - valuesPanel.add(uinExampleLabel); - valuesPanel.add(passField); - - uinPassPanel.add(labelsPanel, BorderLayout.WEST); - uinPassPanel.add(valuesPanel, BorderLayout.CENTER); - uinPassPanel.add(rememberPassBox, BorderLayout.SOUTH); - - uinPassPanel.setBorder(BorderFactory.createTitledBorder(Resources - .getString("plugin.yahooaccregwizz.USERID_AND_PASSWORD"))); - - mainPanel.add(uinPassPanel); - this.add(mainPanel, BorderLayout.NORTH); - } - - /** - * Implements the WizardPage.getIdentifier to return this - * page identifier. - */ - public Object getIdentifier() - { - return FIRST_PAGE_IDENTIFIER; - } - - /** - * Implements the WizardPage.getNextPageIdentifier to return - * the next page identifier - the summary page. - */ - public Object getNextPageIdentifier() - { - return nextPageIdentifier; - } - - /** - * Implements the WizardPage.getBackPageIdentifier to return - * the back identifier. In this case it's null because this is the first - * wizard page. - * @return the identifier of the previous wizard page - */ - public Object getBackPageIdentifier() - { - return null; - } - - /** - * Implements the WizardPage.getWizardForm to return this - * panel. - */ - public Object getWizardForm() - { - return this; - } - - /** - * Before this page is displayed enables or disables the "Next" wizard - * button according to whether the UIN field is empty. - */ - public void pageShowing() - { - this.setNextButtonAccordingToUIN(); - } - - /** - * Saves the user input when the "Next" wizard buttons is clicked. - */ - public void commitPage() - { - YahooAccountRegistration registration = wizard.getRegistration(); - - String userID = userIDField.getText(); - - if(userID == null || userID.trim().length() == 0) - throw new IllegalStateException("No user ID provided."); - - registration.setUserID(userID); - registration.setPassword(new String(passField.getPassword())); - registration.setRememberPassword(rememberPassBox.isSelected()); - - nextPageIdentifier = SUMMARY_PAGE_IDENTIFIER; - - isCommitted = true; - } - - /** - * Enables or disables the "Next" wizard button according to whether the UIN - * field is empty. - */ - private void setNextButtonAccordingToUIN() - { - if (userIDField.getText() == null || userIDField.getText().equals("")) - { - wizard.getWizardContainer().setNextFinishButtonEnabled(false); - } - else - { - wizard.getWizardContainer().setNextFinishButtonEnabled(true); - } - } - - /** - * Handles the DocumentEvent triggered when user types in the UIN - * field. Enables or disables the "Next" wizard button according to whether - * the UIN field is empty. - */ - public void insertUpdate(DocumentEvent e) - { - this.setNextButtonAccordingToUIN(); - } - - /** - * Handles the DocumentEvent triggered when user deletes letters - * from the UIN field. Enables or disables the "Next" wizard button - * according to whether the UIN field is empty. - */ - public void removeUpdate(DocumentEvent e) - { - this.setNextButtonAccordingToUIN(); - } - - public void changedUpdate(DocumentEvent e) - { - } - - public void pageHiding() - { - } - - public void pageShown() - { - } - - public void pageBack() - { - } - - /** - * Fills the UIN and Password fields in this panel with the data coming - * from the given protocolProvider. - * - * @param protocolProvider The ProtocolProviderService to load - * the data from. - */ - public void loadAccount(ProtocolProviderService protocolProvider) - { - AccountID accountID = protocolProvider.getAccountID(); - String password = YahooAccRegWizzActivator - .getYahooProtocolProviderFactory().loadPassword(accountID); - - this.userIDField.setEnabled(false); - this.userIDField.setText(accountID.getUserID()); - - if (password != null) - { - this.passField.setText(password); - this.rememberPassBox.setSelected(true); - } - } - - public Object getSimpleForm() - { - return uinPassPanel; - } - - public boolean isCommitted() - { - return isCommitted; - } -} diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/Resources.java b/src/net/java/sip/communicator/plugin/yahooaccregwizz/Resources.java deleted file mode 100644 index c41a72f..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/Resources.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.yahooaccregwizz; - -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; - -/** - * The Resources class manages the access to the internationalization - * properties files and the image resources used in this plugin. - * - * @author Yana Stamcheva - */ -public class Resources -{ - private static ResourceManagementService resourcesService; - - public static ImageID YAHOO_LOGO - = new ImageID("service.protocol.yahoo.YAHOO_16x16"); - - public static ImageID PAGE_IMAGE - = new ImageID("service.protocol.yahoo.YAHOO_64x64"); - - /** - * Returns an internationalized string corresponding to the given key. - * @param key The key of the string. - * @return An internationalized string corresponding to the given key. - */ - public static String getString(String key) - { - return getResources().getI18NString(key); - } - - /** - * Loads an image from a given image identifier. - * @param imageID The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] getImage(ImageID imageID) - { - return getResources().getImageInBytes(imageID.getId()); - } - - /** - * Returns the ResourceManagementService. - * - * @return the ResourceManagementService. - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = - ResourceManagementServiceUtils - .getService(YahooAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccRegWizzActivator.java deleted file mode 100644 index cd526a9..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccRegWizzActivator.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.yahooaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Registers the YahooAccountRegistrationWizard in the UI Service. - * - * @author Yana Stamcheva - */ -public class YahooAccRegWizzActivator - extends AbstractServiceDependentActivator -{ - /** - * OSGi bundle context. - */ - public static BundleContext bundleContext; - - private static final Logger logger = - Logger.getLogger(YahooAccRegWizzActivator.class); - - private static BrowserLauncherService browserLauncherService; - - private static WizardContainer wizardContainer; - - private static YahooAccountRegistrationWizard yahooWizard; - - private static UIService uiService; - - /** - * Starts this bundle. - */ - @Override - public void start(Object dependentService) - { - uiService = (UIService)dependentService; - - wizardContainer = uiService.getAccountRegWizardContainer(); - - yahooWizard = new YahooAccountRegistrationWizard(wizardContainer); - - Hashtable containerFilter - = new Hashtable(); - - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - ProtocolNames.YAHOO); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - yahooWizard, - containerFilter); - } - - /** - * The dependent class. We are waiting for the ui service. - * @return the ui service class. - */ - @Override - public Class getDependentServiceClass() - { - return UIService.class; - } - - /** - * The bundle context to use. - * @param context the context to set. - */ - @Override - public void setBundleContext(BundleContext context) - { - bundleContext = context; - } - - public void stop(BundleContext bundleContext) throws Exception - { - } - - /** - * Returns the ProtocolProviderFactory for the Yahoo protocol. - * @return the ProtocolProviderFactory for the Yahoo protocol - */ - public static ProtocolProviderFactory getYahooProtocolProviderFactory() - { - ServiceReference[] serRefs = null; - String osgiFilter - = "(" - + ProtocolProviderFactory.PROTOCOL - + "=" - + ProtocolNames.YAHOO - + ")"; - - try { - serRefs - = bundleContext.getServiceReferences( - ProtocolProviderFactory.class.getName(), - osgiFilter); - } - catch (InvalidSyntaxException ex){ - logger.error("YahooAccRegWizzActivator : " + ex); - } - - return - (serRefs == null) - ? null - : (ProtocolProviderFactory) - bundleContext.getService(serRefs[0]); - } - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() { - if (browserLauncherService == null) { - ServiceReference serviceReference = bundleContext - .getServiceReference(BrowserLauncherService.class.getName()); - - browserLauncherService = (BrowserLauncherService) bundleContext - .getService(serviceReference); - } - - return browserLauncherService; - } -} diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistration.java b/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistration.java deleted file mode 100644 index 6cf7759..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistration.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.yahooaccregwizz; - -/** - * The YahooAccountRegistration is used to store all user input data - * through the YahooAccountRegistrationWizard. - * - * @author Yana Stamcheva - */ -public class YahooAccountRegistration { - - private String uin; - - private String password; - - private boolean rememberPassword = true; - - /** - * Returns the password of the yahoo registration account. - * @return the password of the yahoo registration account. - */ - public String getPassword() { - return password; - } - - /** - * Sets the password of the yahoo registration account. - * @param password the password of the yahoo registration account. - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * Returns TRUE if password has to remembered, FALSE otherwise. - * @return TRUE if password has to remembered, FALSE otherwise - */ - public boolean isRememberPassword() { - return rememberPassword; - } - - /** - * Sets the rememberPassword value of this yahoo account registration. - * @param rememberPassword TRUE if password has to remembered, FALSE - * otherwise - */ - public void setRememberPassword(boolean rememberPassword) { - this.rememberPassword = rememberPassword; - } - - /** - * Returns the UIN of the yahoo registration account. - * @return the UIN of the yahoo registration account. - */ - public String getUin() { - return uin; - } - - /** - * Sets the UIN of the yahoo registration account. - * @param uin the UIN of the yahoo registration account. - */ - public void setUserID(String uin) { - this.uin = uin; - } - -} diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistrationWizard.java deleted file mode 100644 index 033f409..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/YahooAccountRegistrationWizard.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.yahooaccregwizz; - -import java.awt.*; -import java.util.*; - -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * The YahooAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the Yahoo protocol. It should allow - * the user to create and configure a new Yahoo account. - * - * @author Yana Stamcheva - */ -public class YahooAccountRegistrationWizard - extends DesktopAccountRegistrationWizard -{ - private final Logger logger - = Logger.getLogger(YahooAccountRegistrationWizard.class); - - private FirstWizardPage firstWizardPage; - - private YahooAccountRegistration registration = - new YahooAccountRegistration(); - - private ProtocolProviderService protocolProvider; - - /** - * Creates an instance of YahooAccountRegistrationWizard. - * - * @param wizardContainer the wizard container, where this wizard is added - */ - public YahooAccountRegistrationWizard(WizardContainer wizardContainer) - { - setWizardContainer(wizardContainer); - - wizardContainer - .setFinishButtonText(Resources.getString("service.gui.SIGN_IN")); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return Resources.getImage(Resources.YAHOO_LOGO); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage - * method. Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Resources.getImage(Resources.PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString("plugin.yahooaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * - * method. Returns the description of the protocol for this wizard. - * - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources - .getString("plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns the set of pages contained in this wizard. - * - * @return Iterator - */ - @Override - public Iterator getPages() - { - java.util.List pages = new ArrayList(); - firstWizardPage = new FirstWizardPage(this); - - pages.add(firstWizardPage); - - return pages.iterator(); - } - - /** - * Returns the set of data that user has entered through this wizard. - * - * @return Iterator - */ - @Override - public Iterator> getSummary() - { - Hashtable summaryTable - = new Hashtable(); - - summaryTable.put( - Resources.getString("plugin.yahooaccregwizz.USERNAME"), - registration.getUin()); - summaryTable.put( - Resources.getString("service.gui.REMEMBER_PASSWORD"), - Boolean.toString(registration.isRememberPassword())); - - return summaryTable.entrySet().iterator(); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin() - throws OperationFailedException - { - firstWizardPage.commitPage(); - - return signin( registration.getUin(), - registration.getPassword()); - } - - /** - * Defines the operations that will be executed when the user clicks on - * the wizard "Signin" button. - * - * @param userName the user name to sign in with - * @param password the password to sign in with - * @return the created ProtocolProviderService corresponding to the - * new account - * @throws OperationFailedException if the operation didn't succeed - */ - @Override - public ProtocolProviderService signin(String userName, String password) - throws OperationFailedException - { - ProtocolProviderFactory factory = - YahooAccRegWizzActivator.getYahooProtocolProviderFactory(); - - return this.installAccount( factory, - userName, - password); - } - - /** - * Creates an account for the given user and password. - * - * @param providerFactory the ProtocolProviderFactory which will create the - * account - * @param user the user identifier - * @param passwd the password - * @return the ProtocolProviderService for the new account. - */ - public ProtocolProviderService installAccount( - ProtocolProviderFactory providerFactory, String user, String passwd) - throws OperationFailedException - { - Hashtable accountProperties - = new Hashtable(); - - accountProperties.put(ProtocolProviderFactory.ACCOUNT_ICON_PATH, - "resources/images/protocol/yahoo/yahoo32x32.png"); - - if (registration.isRememberPassword()) - { - accountProperties.put(ProtocolProviderFactory.PASSWORD, passwd); - } - - if (isModification()) - { - providerFactory.modifyAccount( protocolProvider, - accountProperties); - - setModification(false); - - return protocolProvider; - } - - try - { - AccountID accountID = - providerFactory.installAccount(user, accountProperties); - - ServiceReference serRef = - providerFactory.getProviderForAccount(accountID); - - protocolProvider = - (ProtocolProviderService) YahooAccRegWizzActivator - .bundleContext.getService(serRef); - } - catch (IllegalStateException exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Account already exists.", - OperationFailedException.IDENTIFICATION_CONFLICT); - } - catch (Exception exc) - { - logger.warn(exc.getMessage()); - - throw new OperationFailedException( - "Failed to add account", - OperationFailedException.GENERAL_ERROR); - } - - return protocolProvider; - } - - /** - * Fills the UIN and Password fields in this panel with the data coming - * from the given protocolProvider. - * - * @param protocolProvider The ProtocolProviderService to load - * the data from. - */ - @Override - public void loadAccount(ProtocolProviderService protocolProvider) - { - setModification(true); - - this.protocolProvider = protocolProvider; - - this.registration = new YahooAccountRegistration(); - - this.firstWizardPage.loadAccount(protocolProvider); - } - - /** - * Returns the registration object, which will store all the data through - * the wizard. - * - * @return the registration object, which will store all the data through - * the wizard - */ - public YahooAccountRegistration getRegistration() - { - return registration; - } - - /** - * Returns the size of this wizard. - * @return the size of this wizard - */ - @Override - public Dimension getSize() - { - return new Dimension(600, 500); - } - - /** - * Returns the identifier of the page to show first in the wizard. - * @return the identifier of the page to show first in the wizard. - */ - @Override - public Object getFirstPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns the identifier of the page to show last in the wizard. - * @return the identifier of the page to show last in the wizard. - */ - @Override - public Object getLastPageIdentifier() - { - return firstWizardPage.getIdentifier(); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return FirstWizardPage.USER_NAME_EXAMPLE; - } - - /** - * Defines the operation that will be executed when user clicks on the - * "Sign up" link. - * @throws UnsupportedOperationException if the web sign up operation is - * not supported by the current implementation. - */ - @Override - public void webSignup() - { - YahooAccRegWizzActivator.getBrowserLauncher() - .openURL("https://edit.yahoo.com/registration"); - } - - /** - * Returns true if the web sign up is supported by the current - * implementation, false - otherwise. - * @return true if the web sign up is supported by the current - * implementation, false - otherwise - */ - @Override - public boolean isWebSignupSupported() - { - return true; - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - firstWizardPage = new FirstWizardPage(this); - - return firstWizardPage.getSimpleForm(); - } - - /** - * Whether the advanced configuration is enabled. Gives an option - * to disable/hide advanced config button. - * @return whether the advanced configuration is enabled. - */ - public boolean isAdvancedConfigurationEnabled() - { - return false; - } -} diff --git a/src/net/java/sip/communicator/plugin/yahooaccregwizz/yahooaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/yahooaccregwizz/yahooaccregwizz.manifest.mf deleted file mode 100644 index a975e2e..0000000 --- a/src/net/java/sip/communicator/plugin/yahooaccregwizz/yahooaccregwizz.manifest.mf +++ /dev/null @@ -1,33 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.yahooaccregwizz.YahooAccRegWizzActivator -Bundle-Name: Yahoo account registration wizard -Bundle-Description: Yahoo account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.yahooaccregwizz -Import-Package: org.osgi.framework, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - net.java.sip.communicator.service.protocol.icqconstants, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - javax.swing, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.accessibility, - javax.swing.plaf, - javax.swing.plaf.metal, - javax.swing.plaf.basic, - javax.imageio, - javax.swing.filechooser, - javax.swing.tree, - javax.swing.undo, - javax.swing.border diff --git a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java index 332c18d..362faf4 100644 --- a/src/net/java/sip/communicator/service/contactsource/ContactDetail.java +++ b/src/net/java/sip/communicator/service/contactsource/ContactDetail.java @@ -210,11 +210,9 @@ public class ContactDetail */ AIM("AIM"), ICQ("ICQ"), - MSN("MSN"), - Jabber("Jabber"), + Jabber("XMPP"), Skype("Skype"), Yahoo("Yahoo"), - Facebook("Facebook"), GoogleTalk("GoogleTalk"), /** diff --git a/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java index 0e89162..e72fe67 100644 --- a/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java +++ b/src/net/java/sip/communicator/service/googlecontacts/GoogleContactsEntry.java @@ -37,21 +37,11 @@ public interface GoogleContactsEntry GOOGLETALK, /** - * Yahoo protocol. - */ - YAHOO, - - /** * AIM protocol. */ AIM, /** - * MSN protocol. - */ - MSN, - - /** * ICQ protocol. */ ICQ, @@ -62,6 +52,11 @@ public interface GoogleContactsEntry JABBER, /** + * Skype protocol. + */ + SKYPE, + + /** * Other protocol (i.e. not supported). */ OTHER, diff --git a/src/net/java/sip/communicator/service/protocol/AdHocChatRoom.java b/src/net/java/sip/communicator/service/protocol/AdHocChatRoom.java index 6f07bd1..e2af0a8 100644 --- a/src/net/java/sip/communicator/service/protocol/AdHocChatRoom.java +++ b/src/net/java/sip/communicator/service/protocol/AdHocChatRoom.java @@ -25,8 +25,7 @@ import net.java.sip.communicator.service.protocol.event.*; * Represents an ad-hoc rendez-vous point where multiple chat users could * communicate together. This interface describes the main methods used by some * protocols for multi user chat, without useless methods (such as kicking a - * participant) which aren't supported by these protocols (MSN, ICQ, Yahoo!, - * etc.). + * participant) which aren't supported by these protocols (MSN, ICQ, etc.). * * AdHocChatRoom acts like a simplified ChatRoom. * diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java index 51ac63d..ba51c91 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolNames.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolNames.java @@ -44,16 +44,6 @@ public interface ProtocolNames public static final String IRC = "IRC"; /** - * The Gadu-Gadu protocol. - */ - public static final String GADU_GADU = "Gadu-Gadu"; - - /** - * The GroupWise protocol. - */ - public static final String GROUP_WISE = "GroupWise"; - - /** * The ICQ service protocol. */ public static final String ICQ = "ICQ"; @@ -64,26 +54,11 @@ public interface ProtocolNames public static final String AIM = "AIM"; /** - * The Yahoo! messenger protocol. - */ - public static final String YAHOO = "Yahoo!"; - - /** - * The Skype protocol. - */ - public static final String SKYPE = "Skype"; - - /** * The SIP Communicator MOCK protocol. */ public static final String SIP_COMMUNICATOR_MOCK = "sip-communicator-mock"; /** - * The Zeroconf protocol. - */ - public static final String ZEROCONF = "Zeroconf"; - - /** * The SSH protocol. */ public static final String SSH = "SSH"; @@ -92,9 +67,4 @@ public interface ProtocolNames * The Gibberish protocol. */ public static final String GIBBERISH = "Gibberish"; - - /** - * The Dict protocol. - */ - public static final String DICT = "Dict"; } diff --git a/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf b/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf index 271af97..233eb84 100644 --- a/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf +++ b/src/net/java/sip/communicator/service/protocol/protocol.provider.manifest.mf @@ -17,12 +17,10 @@ Import-Package: net.java.sip.communicator.service.credentialsstorage, org.jitsi.util.event, org.osgi.framework Export-Package: net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.aimconstants, net.java.sip.communicator.service.protocol.event, net.java.sip.communicator.service.protocol.globalstatus, net.java.sip.communicator.service.protocol.icqconstants, net.java.sip.communicator.service.protocol.jabber, net.java.sip.communicator.service.protocol.jabberconstants, net.java.sip.communicator.service.protocol.sip, - net.java.sip.communicator.service.protocol.whiteboardobjects, - net.java.sip.communicator.service.protocol.yahooconstants + net.java.sip.communicator.service.protocol.whiteboardobjects diff --git a/src/net/java/sip/communicator/service/protocol/yahooconstants/YahooStatusEnum.java b/src/net/java/sip/communicator/service/protocol/yahooconstants/YahooStatusEnum.java deleted file mode 100644 index d21ec033..0000000 --- a/src/net/java/sip/communicator/service/protocol/yahooconstants/YahooStatusEnum.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.service.protocol.yahooconstants; - -import java.io.*; -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.util.*; - -/** - * An enumeration containing all status instances that MUST be supported by - * an implementation of the yahoo protocol. Implementations may - * support other forms of PresenceStatus but they MUST ALL support those - * enumerated here. - *

    - * For testing purposes, this class also provides a List containing - * all of the status fields. - * - * @author Damian Minkov - */ -public class YahooStatusEnum - extends PresenceStatus -{ - /** - * The Logger used by the YahooStatusEnum class and its - * instances for logging output. - */ - private static Logger logger = Logger.getLogger(YahooStatusEnum.class); - - /** - * The Online status. Indicate that the user is able and willing to - * communicate. - */ - public static final YahooStatusEnum AVAILABLE - = new YahooStatusEnum(65, "Available", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-online.png")); - - /** - * The Not Available status. Indicates that the user has connectivity - * but might not be able to immediately act (i.e. even less immediately than - * when in an Away status ;-P ) upon initiation of communication. - */ - public static final YahooStatusEnum BE_RIGHT_BACK - = new YahooStatusEnum(48, "Be Right Back", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-away.png")); - - /** - * The Idle status. Indicates that the user is not using the messanger. - */ - public static final YahooStatusEnum IDLE - = new YahooStatusEnum(46, "Idle", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-idle.png")); - - /** - * The Invisible status. Indicates that the user has connectivity even - * though it may appear otherwise to others, to whom she would appear to be - * offline. - */ - public static final YahooStatusEnum INVISIBLE - = new YahooStatusEnum(45, "Invisible", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-invisible.png")); - - /** - * The STEPPED_OUT status. Indicates that the user has connectivity but might - * not be able to immediately act upon initiation of communication. - */ - public static final YahooStatusEnum STEPPED_OUT - = new YahooStatusEnum(40, "Stepped out", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-away.png")); - - /** - * The Out to lunch status. Indicates that the user is eating. - */ - public static final YahooStatusEnum OUT_TO_LUNCH - = new YahooStatusEnum(39, "Out to lunch", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-lunch.png")); - - /** - * The Not at home status. Indicates that the user is not at home. - */ - public static final YahooStatusEnum NOT_AT_HOME - = new YahooStatusEnum(38, "Not at home", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-na.png")); - - /** - * The Not at desk status. Indicates that the user is not at his desk, but - * somewhere in the office. - */ - public static final YahooStatusEnum NOT_AT_DESK - = new YahooStatusEnum(36, "Not at desk", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-na.png")); - - /** - * The Not in office status. Indicates that the user is out of the office. - */ - public static final YahooStatusEnum NOT_IN_OFFICE - = new YahooStatusEnum(34, "Not in office", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-na.png")); - - /** - * The On vacation status. Indicates that the user is somewhere on the - * beach or skiing. - */ - public static final YahooStatusEnum ON_VACATION - = new YahooStatusEnum(33, "On vacation", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-vacation.png")); - - /** - * The On the phone status. Indicates that the user is talking to the phone. - */ - public static final YahooStatusEnum ON_THE_PHONE - = new YahooStatusEnum(31, "On the phone", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-phone.png")); - - /** - * The DND status. Indicates that the user has connectivity but prefers - * not to be contacted. - */ - public static final YahooStatusEnum BUSY - = new YahooStatusEnum(30, "Busy", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-busy.png")); - - /** - * The Offline status. Indicates the user does not seem to be connected - * to the network or at least does not want us to know she is - */ - public static final YahooStatusEnum OFFLINE - = new YahooStatusEnum(0, "Offline", - loadIcon("resources/images/protocol/yahoo/yahoo16x16-offline.png")); - - /** - * The minimal set of states that any implementation must support. - */ - public static final ArrayList yahooStatusSet - = new ArrayList(); - static{ - yahooStatusSet.add(AVAILABLE); - yahooStatusSet.add(BE_RIGHT_BACK); - yahooStatusSet.add(BUSY); - yahooStatusSet.add(IDLE); - yahooStatusSet.add(INVISIBLE); - yahooStatusSet.add(NOT_AT_DESK); - yahooStatusSet.add(NOT_AT_HOME); - yahooStatusSet.add(NOT_IN_OFFICE); - yahooStatusSet.add(OFFLINE); - yahooStatusSet.add(ON_THE_PHONE); - yahooStatusSet.add(ON_VACATION); - yahooStatusSet.add(OUT_TO_LUNCH); - yahooStatusSet.add(STEPPED_OUT); - } - - /** - * Creates a status with the specified connectivity coeff, name and icon. - * @param status the connectivity coefficient for the specified status - * @param statusName String - * @param statusIcon the icon associated with this status - */ - protected YahooStatusEnum(int status, String statusName, byte[] statusIcon) - { - super(status, statusName, statusIcon); - } - - /** - * Loads an image from a given image path. - * @param imagePath The identifier of the image. - * @return The image for the given identifier. - */ - public static byte[] loadIcon(String imagePath) { - InputStream is = YahooStatusEnum.class.getClassLoader() - .getResourceAsStream(imagePath); - - if(is == null) - return null; - - byte[] icon = null; - try { - icon = new byte[is.available()]; - is.read(icon); - } catch (IOException exc) { - logger.error("Failed to load icon: " + imagePath, exc); - } - return icon; - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetAdHocMultiUserChat.java b/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetAdHocMultiUserChat.java index 13e5092..1f7db0f 100644 --- a/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetAdHocMultiUserChat.java +++ b/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetAdHocMultiUserChat.java @@ -138,10 +138,6 @@ public abstract class TestOperationSetAdHocMultiUserChat extends TestCase * -Then they will leave the room. They will be invited again in another * test. * - * NOTE that this test will be especially used by Yahoo! protocol because of - * the fact that creating a conference chat with this protocol fails if any - * participants are given to the dedicated constructor of the library. - * * @throws OperationNotSupportedException * @throws OperationFailedException */ @@ -160,7 +156,6 @@ public abstract class TestOperationSetAdHocMultiUserChat extends TestCase opSetAHMUC3, AHMUCEventCollector.INVITATION_EVENT); // We create the room with the given contacts: - // (NOTE that in Yahoo! adHocChatRoomName won't be considered!) AdHocChatRoom room = opSetAHMUC1.createAdHocChatRoom( adHocChatRoomName, contacts, invitationReason); @@ -440,7 +435,7 @@ public abstract class TestOperationSetAdHocMultiUserChat extends TestCase /** * Make sure that invitations have been received on both side (user2 and * user3). Note that it only make sense to use this method with protocol - * who support invitations (Yahoo! and ICQ). + * who support invitations (ICQ). * * We will first test that after having accept an invitation the concerned * user joins the room and be a part of participants. diff --git a/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetFileTransfer.java b/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetFileTransfer.java index e123bd3..d29092d 100644 --- a/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetFileTransfer.java +++ b/test/net/java/sip/communicator/slick/protocol/generic/TestOperationSetFileTransfer.java @@ -605,9 +605,8 @@ public abstract class TestOperationSetFileTransfer ,FileTransferStatusChangeEvent.PREPARING ,stat1.getNewStatus()); - // now wait if some protocol filres inProgress + // now wait if some protocol fires inProgress // jabber doesn't fire inProgress here - // yahoo fires it receiverStatusListener.waitForEvent(14000); // wait in_progress diff --git a/test/net/java/sip/communicator/slick/protocol/icq/icq.provider.slick.manifest.mf b/test/net/java/sip/communicator/slick/protocol/icq/icq.provider.slick.manifest.mf index 68d09e2..d1420bd 100644 --- a/test/net/java/sip/communicator/slick/protocol/icq/icq.provider.slick.manifest.mf +++ b/test/net/java/sip/communicator/slick/protocol/icq/icq.provider.slick.manifest.mf @@ -12,6 +12,5 @@ Import-Package: junit.framework, net.java.sip.communicator.service.dns, net.java.sip.communicator.service.protocol, net.java.sip.communicator.service.protocol.icqconstants, - net.java.sip.communicator.service.protocol.aimconstants, net.java.sip.communicator.service.protocol.event, org.jitsi.service.fileaccess diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountInstallation.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountInstallation.java deleted file mode 100644 index 0df8b3c..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountInstallation.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; - -import org.osgi.framework.*; - -public class TestAccountInstallation - extends TestCase -{ - - /** - * Creates the test with the specified method name. - * @param name the name of the method to execute. - */ - public TestAccountInstallation(String name) - { - super(name); - } - - /** - * JUnit setup method. - * @throws Exception in case anything goes wrong. - */ - @Override - protected void setUp() throws Exception - { - super.setUp(); - } - - /** - * JUnit teardown method. - * @throws Exception in case anything goes wrong. - */ - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - } - - /** - * Installs an account and verifies whether the installation has gone well. - */ - public void testInstallAccount() - { - // first obtain a reference to the provider factory - ServiceReference[] serRefs = null; - String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL - + "="+ProtocolNames.YAHOO+")"; - try{ - serRefs = YahooSlickFixture.bc.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex) - { - //this really shouldhn't occur as the filter expression is static. - fail(osgiFilter + " is not a valid osgi filter"); - } - - assertTrue( - "Failed to find a provider factory service for protocol Yahoo", - serRefs != null && serRefs.length > 0); - - //Keep the reference for later usage. - ProtocolProviderFactory yahooProviderFactory = (ProtocolProviderFactory) - YahooSlickFixture.bc.getService(serRefs[0]); - - //make sure the account is empty - assertTrue("There was an account registered with the account mananger " - +"before we've installed any", - yahooProviderFactory.getRegisteredAccounts().size() == 0); - - - //Prepare the properties of the first yahoo account. - - Hashtable yahooAccount1Properties = getAccountProperties( - YahooProtocolProviderServiceLick.ACCOUNT_1_PREFIX); - Hashtable yahooAccount2Properties = getAccountProperties( - YahooProtocolProviderServiceLick.ACCOUNT_2_PREFIX); - Hashtable yahooAccount3Properties = getAccountProperties( - YahooProtocolProviderServiceLick.ACCOUNT_3_PREFIX); - - //try to install an account with a null account id - try{ - yahooProviderFactory.installAccount( - null, yahooAccount1Properties); - fail("installing an account with a null account id must result " - +"in a NullPointerException"); - }catch(NullPointerException exc) - { - //that's what had to happen - } - - //now really install the accounts - yahooProviderFactory.installAccount( - yahooAccount1Properties.get(ProtocolProviderFactory.USER_ID) - , yahooAccount1Properties); - yahooProviderFactory.installAccount( - yahooAccount2Properties.get(ProtocolProviderFactory.USER_ID) - , yahooAccount2Properties); - yahooProviderFactory.installAccount( - yahooAccount3Properties.get(ProtocolProviderFactory.USER_ID) - , yahooAccount3Properties); - - - //try to install one of the accounts one more time and verify that an - //excepion is thrown. - try{ - yahooProviderFactory.installAccount( - yahooAccount1Properties.get(ProtocolProviderFactory.USER_ID) - , yahooAccount1Properties); - - fail("An IllegalStateException must be thrown when trying to "+ - "install a duplicate account"); - - }catch(IllegalStateException exc) - { - //that's what supposed to happen. - } - - //Verify that the provider factory is aware of our installation - assertTrue( - "The newly installed account was not in the acc man's " - +"registered accounts!", - yahooProviderFactory.getRegisteredAccounts().size() == 3); - - //Verify protocol providers corresponding to the new account have - //been properly registered with the osgi framework. - - osgiFilter = - "(&("+ProtocolProviderFactory.PROTOCOL +"="+ProtocolNames.YAHOO+")" - +"(" + ProtocolProviderFactory.USER_ID - + "=" + yahooAccount1Properties.get( - ProtocolProviderFactory.USER_ID) - + "))"; - - try - { - serRefs = YahooSlickFixture.bc.getServiceReferences( - ProtocolProviderService.class.getName(), - osgiFilter); - } - catch (InvalidSyntaxException ex) - { - //this really shouldhn't occur as the filter expression is static. - fail(osgiFilter + "is not a valid osgi filter"); - } - - assertTrue("An protocol provider was apparently not installed as " - + "requested." - , serRefs != null && serRefs.length > 0); - - Object yahooProtocolProvider - = YahooSlickFixture.bc.getService(serRefs[0]); - - assertTrue("The installed protocol provider does not implement " - + "the protocol provider service." - ,yahooProtocolProvider instanceof ProtocolProviderService); - } - - /** - * Returns all properties necessary for the intialization of the account - * with accountPrefix. - * @param accountPrefix the prefix contained by all property names for the - * the account we'd like to initialized - * @return a Hashtable that can be used when creating the account in a - * protocol provider factory. - */ - private Hashtable getAccountProperties(String accountPrefix) - { - Hashtable table = new Hashtable(); - - String userID = System.getProperty( - accountPrefix + ProtocolProviderFactory.USER_ID, null); - - assertNotNull( - "The system property named " - + accountPrefix + ProtocolProviderFactory.USER_ID - +" has to tontain a valid yahoo address that could be used during " - +"SIP Communicator's tests." - , userID); - - table.put(ProtocolProviderFactory.USER_ID, userID); - - String passwd = System.getProperty( - accountPrefix + ProtocolProviderFactory.PASSWORD, null ); - - assertNotNull( - "The system property named " - + accountPrefix + ProtocolProviderFactory.PASSWORD - +" has to contain the password corresponding to the account " - + "specified in " - + accountPrefix + ProtocolProviderFactory.USER_ID - , passwd); - - table.put(ProtocolProviderFactory.PASSWORD, passwd); - - String serverAddress = System.getProperty( - accountPrefix + ProtocolProviderFactory.SERVER_ADDRESS, null); - - // optional - if(serverAddress != null) - table.put(ProtocolProviderFactory.SERVER_ADDRESS, serverAddress); - - String serverPort = System.getProperty( - accountPrefix + ProtocolProviderFactory.SERVER_PORT, null); - - // optional - if(serverPort != null) - table.put(ProtocolProviderFactory.SERVER_PORT, serverPort); - - return table; - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallation.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallation.java deleted file mode 100644 index 7b04758..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallation.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.slick.protocol.generic.*; - -import org.osgi.framework.*; - -/** - * Tests whether accounts are uninstalled properly. It is important that - * tests from this class be called last since they will install the accounts - * that have been used to test the implementations. Apart from uninstallation - * tests the class also contains tests that remove and reinstall the protocol - * provider bundle in order to verify that accounts are persistent. - * - * @author Emil Ivov - * @author Valentin Martinet - */ -public class TestAccountUninstallation - extends TestCase -{ - private YahooSlickFixture fixture = new YahooSlickFixture(); - - /** - * Constructs a test instance - * @param name The name of the test. - */ - public TestAccountUninstallation(String name) - { - super(name); - } - - /** - * JUnit setup method. - * @throws Exception in case anything goes wrong. - */ - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - } - - /** - * JUnit teardown method. - * @throws Exception in case anything goes wrong. - */ - @Override - protected void tearDown() throws Exception - { - fixture.tearDown(); - super.tearDown(); - } - - /** - * Returns a suite containing tests in this class in the order that we'd - * like them executed. - * @return a Test suite containing tests in this class in the order that - * we'd like them executed. - */ - public static Test suite() - { - TestSuite suite = new TestSuite(); - - suite.addTest( - new TestAccountUninstallation("testInstallationPersistency")); - suite.addTest( - new TestAccountUninstallation("testUninstallAccount")); - - return suite; - } - - /** - * Stops and removes the tested bundle, verifies that it has unregistered - * its provider, then reloads and restarts the bundle and verifies that - * the protocol provider is reRegistered in the bundle context. - * - * @throws java.lang.Exception if an exception occurs during testing. - */ - public void testInstallationPersistency() throws Exception - { - Bundle providerBundle - = AdHocMultiUserChatSlickFixture.findProtocolProviderBundle(fixture.provider1); - - //set the global providerBundle reference that we will be using - //in the last series of tests (Account uninstallation persistency) - YahooSlickFixture.providerBundle = providerBundle; - - assertNotNull("Couldn't find a bundle for the tested provider" - , providerBundle); - - providerBundle.stop(); - - assertTrue("Couldn't stop the protocol provider bundle. State was " - + providerBundle.getState() - , Bundle.ACTIVE != providerBundle.getState() - && Bundle.STOPPING != providerBundle.getState()); - - providerBundle.uninstall(); - - assertEquals("Couldn't stop the protocol provider bundle." - , Bundle.UNINSTALLED, providerBundle.getState()); - - //verify that the provider is no longer available - ServiceReference[] yahooProviderRefs = null; - try - { - yahooProviderRefs = AdHocMultiUserChatSlickFixture.bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(&" - + "(" + ProtocolProviderFactory.PROTOCOL - + "=" +ProtocolNames.YAHOO + ")" - + "(" + ProtocolProviderFactory.USER_ID - + "="+ fixture.userID1 + ")" - + ")"); - } - catch (InvalidSyntaxException ex) - { - fail("We apparently got our filter wrong: " + ex.getMessage()); - } - - //make sure we didn't see a service - assertTrue("A Protocol Provider Service was still regged as an osgi service " - +"for yahoo URI:" + fixture.userID1 - + "After it was explicitly uninstalled" - ,yahooProviderRefs == null || yahooProviderRefs.length == 0); - - //verify that the provider factory knows that we have uninstalled the - //provider. - assertTrue( - "The yahoo provider factory kept a reference to the provider we just " - +"uninstalled (uri="+fixture.userID1+")", - fixture.providerFactory.getRegisteredAccounts().isEmpty() - && fixture.providerFactory.getProviderForAccount( - fixture.provider1.getAccountID()) - == null); - - //Now reinstall the bundle - providerBundle = AdHocMultiUserChatSlickFixture.bc.installBundle(providerBundle.getLocation()); - - //set the global providerBundle reference that we will be using - //in the last series of tests (Account uninstallation persistency) - YahooSlickFixture.providerBundle = providerBundle; - - assertEquals("Couldn't re-install protocol provider bundle." - , Bundle.INSTALLED, providerBundle.getState()); - - AccountManagerUtils.startBundleAndWaitStoredAccountsLoaded(AdHocMultiUserChatSlickFixture.bc, - providerBundle, ProtocolNames.YAHOO); - assertEquals("Couldn't re-start protocol provider bundle." - , Bundle.ACTIVE, providerBundle.getState()); - - //Make sure that the provider is there again. - //verify that the provider is no longer available - try - { - yahooProviderRefs = AdHocMultiUserChatSlickFixture.bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(&" - + "(" + ProtocolProviderFactory.PROTOCOL - + "=" +ProtocolNames.YAHOO + ")" - + "(" + ProtocolProviderFactory.USER_ID - + "="+ fixture.userID1 + ")" - + ")"); - } - catch (InvalidSyntaxException ex) - { - fail("We apparently got our filter wrong " + ex.getMessage()); - } - - //make sure we didn't see a service - assertTrue("A Protocol Provider Service was not restored after being" - +"reinstalled. yahoo URI:" + fixture.userID1 - ,yahooProviderRefs != null && yahooProviderRefs.length > 0); - - ServiceReference[] yahooFactoryRefs = null; - try - { - yahooFactoryRefs = AdHocMultiUserChatSlickFixture.bc.getServiceReferences( - ProtocolProviderFactory.class.getName(), - "(" + ProtocolProviderFactory.PROTOCOL - + "=" +ProtocolNames.YAHOO + ")"); - } - catch (InvalidSyntaxException ex) - { - fail("We apparently got our filter wrong " + ex.getMessage()); - } - - //we're the ones who've reinstalled the factory so it's our - //responsibility to update the fixture. - fixture.providerFactory - = (ProtocolProviderFactory)AdHocMultiUserChatSlickFixture.bc.getService(yahooFactoryRefs[0]); - fixture.provider1 - = (ProtocolProviderService)AdHocMultiUserChatSlickFixture.bc.getService(yahooProviderRefs[0]); - - - //verify that the provider is also restored in the provider factory - //itself - assertTrue( - "The yahoo provider did not restore its own reference to the provider " - +"that we just reinstalled (URI="+fixture.userID1+")", - !fixture.providerFactory.getRegisteredAccounts().isEmpty() - && fixture.providerFactory.getProviderForAccount( - fixture.provider1.getAccountID()) - != null); - - } - - /** - * Uninstalls our test account and makes sure it really has been removed. - * - */ - public void testUninstallAccount() - { - assertFalse("No installed accounts found", - fixture.providerFactory.getRegisteredAccounts().isEmpty()); - - assertNotNull( - "Found no provider corresponding to URI " + fixture.userID1 - ,fixture.providerFactory.getProviderForAccount( - fixture.provider1.getAccountID())); - - assertTrue( - "Failed to remove a provider corresponding to URI " - + fixture.userID1 - ,fixture.providerFactory.uninstallAccount( - fixture.provider1.getAccountID())); - assertTrue( - "Failed to remove a provider corresponding to URI " - + fixture.userID2 - ,fixture.providerFactory.uninstallAccount( - fixture.provider2.getAccountID())); - assertTrue( - "Failed to remove a provider corresponding to URI " - + fixture.userID3 - ,fixture.providerFactory.uninstallAccount( - fixture.provider3.getAccountID())); - - //make sure no providers have remained installed. - ServiceReference[] yahooProviderRefs = null; - try - { - yahooProviderRefs = AdHocMultiUserChatSlickFixture.bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(" + ProtocolProviderFactory.PROTOCOL - + "=" +ProtocolNames.YAHOO + ")"); - } - catch (InvalidSyntaxException ex) - { - fail("We apparently got our filter wrong " + ex.getMessage()); - } - - //make sure we didn't see a service - assertTrue("A Protocol Provider Service was still regged as an osgi " - + "service for yahoo URI:" + fixture.userID1 - + "After it was explicitly uninstalled" - ,yahooProviderRefs == null || yahooProviderRefs.length == 0); - - //verify that the provider factory knows that we have uninstalled the - //provider. - assertTrue( - "The yahoo provider factory kept a reference to the provider we just " - +"uninstalled (uri="+fixture.userID1+")", - fixture.providerFactory.getRegisteredAccounts().isEmpty() - && fixture.providerFactory.getProviderForAccount( - fixture.provider1.getAccountID()) - == null); - - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallationPersistence.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallationPersistence.java deleted file mode 100644 index d87a238..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestAccountUninstallationPersistence.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; - -import org.jitsi.service.configuration.*; -import org.osgi.framework.*; - -/** - * Contains tests verifying persistence of account uninstallation. In other - * words we try to make sure that once uninstalled an account remains - * uninstalled. - * - * @author Emil Ivov - */ -public class TestAccountUninstallationPersistence - extends TestCase -{ - /** - * Creates a new test instance wrapper around the test with the specified - * name. - * @param testName the name of the test that we will be executing. - */ - public TestAccountUninstallationPersistence(String testName) - { - super(testName); - } - - /** - * Retrieves a reference to the yahoo bundle, stops it and uninstalls it and - * then reinstalls it in order to make sure that accounts are not reloaded - * once removed. - * - * @throws java.lang.Exception if something goes wrong while manipulating - * the bundles. - */ - public void testAccountUninstallationPersistence() - throws Exception - { - Bundle providerBundle = YahooSlickFixture.providerBundle; - - providerBundle.stop(); - - assertTrue("Couldn't stop the protocol provider bundle. State was " - + providerBundle.getState() - , Bundle.ACTIVE != providerBundle.getState() - && Bundle.STOPPING != providerBundle.getState()); - - providerBundle.uninstall(); - - assertEquals("Couldn't stop the protocol provider bundle." - , Bundle.UNINSTALLED, providerBundle.getState()); - - //Now reinstall the bundle and restart the provider - providerBundle - = YahooSlickFixture.bc.installBundle(providerBundle.getLocation()); - - assertEquals("Couldn't re-install protocol provider bundle." - , Bundle.INSTALLED, providerBundle.getState()); - - AccountManagerUtils.startBundleAndWaitStoredAccountsLoaded( - YahooSlickFixture.bc, providerBundle, ProtocolNames.YAHOO); - assertEquals("Couldn't re-start protocol provider bundle." - , Bundle.ACTIVE, providerBundle.getState()); - - - //verify that the provider is not reinstalled - ServiceReference[] yahooProviderRefs = null; - try - { - yahooProviderRefs = YahooSlickFixture.bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(" + ProtocolProviderFactory.PROTOCOL - + "=" +ProtocolNames.YAHOO + ")"); - } - catch (InvalidSyntaxException ex) - { - fail("We apparently got our filter wrong " + ex.getMessage()); - } - - //make sure we didn't retrieve a service - assertTrue("A yahoo Protocol Provider Service was still regged as an " - +"osgi service after it was explicitly uninstalled" - ,yahooProviderRefs == null || yahooProviderRefs.length == 0); - - //and a nasty hack at the end - delete the configuration file so that - //we get a fresh start on next run. - ServiceReference confReference - = YahooSlickFixture.bc.getServiceReference( - ConfigurationService.class.getName()); - ConfigurationService configurationService - = (ConfigurationService) YahooSlickFixture.bc.getService(confReference); - - configurationService.purgeStoredConfiguration(); - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetAdHocMultiUserChatYahooImpl.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetAdHocMultiUserChatYahooImpl.java deleted file mode 100644 index 3f66045..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetAdHocMultiUserChatYahooImpl.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.slick.protocol.generic.*; - -/** - * Tests for the Yahoo! ad-hoc multi-user chat operation set. - * - * @author Valentin Martinet - */ -public class TestOperationSetAdHocMultiUserChatYahooImpl -extends TestOperationSetAdHocMultiUserChat -{ - /** - * Creates the test with the specified method name. - * - * @param name the name of the method to execute. - */ - public TestOperationSetAdHocMultiUserChatYahooImpl(String name) - { - super(name); - } - - - /** - * Creates a test suite containing tests of this class in a specific order. - * - * @return Test a testsuite containing all tests to execute. - */ - public static TestSuite suite() - { - TestSuite suite = new TestSuite(); - - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "testRegisterAccount3")); - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "prepareContactList")); - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "testCreateRoomWithParticipants")); - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "testInvitations")); - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "testSendIM")); - suite.addTest(new TestOperationSetAdHocMultiUserChatYahooImpl( - "testPeerLeaved")); - - return suite; - } - - /** - * Register the third testing account. - * - * @throws OperationFailedException - */ - public void testRegisterAccount3() throws OperationFailedException - { - fixture.provider3.register( - new SecurityAuthorityImpl( - System.getProperty( - YahooProtocolProviderServiceLick.ACCOUNT_3_PREFIX - + ProtocolProviderFactory.PASSWORD).toCharArray())); - - assertEquals(fixture.provider3.getRegistrationState(), - RegistrationState.REGISTERED); - } - - /** - * JUnit setUp method. - * @throws Exception - * - * @throws Exception - */ - @Override - public void start() throws Exception - { - fixture = new YahooSlickFixture(); - fixture.setUp(); - - // Supported operation sets by each protocol provider. - Map - supportedOpSets1, supportedOpSets2, supportedOpSets3; - - supportedOpSets1 = fixture.provider1.getSupportedOperationSets(); - supportedOpSets2 = fixture.provider2.getSupportedOperationSets(); - supportedOpSets3 = fixture.provider3.getSupportedOperationSets(); - - // - // Initialization of operation sets for the first testing account: - // - - if (supportedOpSets1 == null || supportedOpSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " + - "this implementation. "); - - opSetAHMUC1 = (OperationSetAdHocMultiUserChat) supportedOpSets1.get( - OperationSetAdHocMultiUserChat.class.getName()); - - if (opSetAHMUC1 == null) - throw new NullPointerException( - "No implementation for multi user chat was found"); - - opSetPresence1 = (OperationSetPresence) supportedOpSets1.get( - OperationSetPresence.class.getName()); - - if (opSetPresence1 == null) - throw new NullPointerException( - "An implementation of the service must provide an " + - "implementation of at least one of the PresenceOperationSets"); - - - // - // Initialization of operation sets for the second testing account: - // - - if (supportedOpSets2 == null || supportedOpSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " + - "this implementation. "); - - opSetAHMUC2 = (OperationSetAdHocMultiUserChat) supportedOpSets2.get( - OperationSetAdHocMultiUserChat.class.getName()); - - if (opSetAHMUC2 == null) - throw new NullPointerException( - "No implementation for ad hoc multi user chat was found"); - - opSetPresence2 = (OperationSetPresence) supportedOpSets2.get( - OperationSetPresence.class.getName()); - - if (opSetPresence2 == null) - throw new NullPointerException( - "An implementation of the service must provide an " + - "implementation of at least one of the PresenceOperationSets"); - - - // - // Initialization of operation sets for the third testing account: - // - - if (supportedOpSets3 == null || supportedOpSets3.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " + - "this implementation. "); - - opSetAHMUC3 = (OperationSetAdHocMultiUserChat) supportedOpSets3.get( - OperationSetAdHocMultiUserChat.class.getName()); - - if (opSetAHMUC3 == null) - throw new NullPointerException( - "No implementation for ad hoc multi user chat was found"); - - opSetPresence3 = (OperationSetPresence) supportedOpSets3.get( - OperationSetPresence.class.getName()); - - if (opSetPresence3 == null) - throw new NullPointerException( - "An implementation of the service must provide an " + - "implementation of at least one of the PresenceOperationSets"); - } - -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetBasicInstantMessaging.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetBasicInstantMessaging.java deleted file mode 100644 index 9b8fa7b..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetBasicInstantMessaging.java +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.io.*; -import java.net.*; -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -/** - * Performs testing of the basic instant messaging operation set. Tests include - * going over basic functionality such as sending a message from the tested - * implementation and asserting reception by the tester agent and vice versa. - * @author Emil Ivov - */ -public class TestOperationSetBasicInstantMessaging - extends TestCase -{ - private static final Logger logger = - Logger.getLogger(TestOperationSetBasicInstantMessaging.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - - private OperationSetBasicInstantMessaging opSetBasicIM1 = null; - private OperationSetBasicInstantMessaging opSetBasicIM2 = null; - - private OperationSetPresence opSetPresence1 = null; - private OperationSetPresence opSetPresence2 = null; - - public TestOperationSetBasicInstantMessaging(String name) - { - super(name); - } - - /** - * Get a reference to the basic IM operation set. - * @throws Exception if this is not a good day. - */ - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - - Map supportedOperationSets1 = - fixture.provider1.getSupportedOperationSets(); - - if ( supportedOperationSets1 == null - || supportedOperationSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //get the operation set presence here. - opSetBasicIM1 = - (OperationSetBasicInstantMessaging)supportedOperationSets1.get( - OperationSetBasicInstantMessaging.class.getName()); - - if (opSetBasicIM1 == null) - { - throw new NullPointerException( - "No implementation for basic IM was found"); - } - - //we also need the presence op set in order to retrieve contacts. - opSetPresence1 = - (OperationSetPresence)supportedOperationSets1.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence1 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - - Map supportedOperationSets2 = - fixture.provider2.getSupportedOperationSets(); - - if ( supportedOperationSets2 == null - || supportedOperationSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //get the operation set presence here. - opSetBasicIM2 = - (OperationSetBasicInstantMessaging)supportedOperationSets2.get( - OperationSetBasicInstantMessaging.class.getName()); - - if (opSetBasicIM2 == null) - { - throw new NullPointerException( - "No implementation for basic IM was found"); - } - - opSetPresence2 = - (OperationSetPresence) supportedOperationSets2.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence2 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - - fixture.tearDown(); - } - - /** - * Creates a test suite containing tests of this class in a specific order. - * We'll first execute tests beginning with the "test" prefix and then go to - * ordered tests.We first execture tests for receiving messagese, so that - * a volatile contact is created for the sender. we'll then be able to - * retrieve this volatile contact and send them a message on our turn. - * We need to do things this way as the contact corresponding to the tester - * agent has been removed in the previous test and we no longer have it - * in our contact list. - * - * @return Test a testsuite containing all tests to execute. - */ - public static Test suite() - { - TestSuite suite = new TestSuite(); - - suite.addTest(new TestOperationSetBasicInstantMessaging( - "prepareContactList")); - - suite.addTestSuite(TestOperationSetBasicInstantMessaging.class); - - //the following 2 need to be run in the specified order. - suite.addTest(new TestOperationSetBasicInstantMessaging( - "firstTestReceiveMessage")); - suite.addTest(new TestOperationSetBasicInstantMessaging( - "thenTestSendMessage")); - - return suite; - } - - /** - * Create the list to be sure that contacts exchanging messages - * exists in each other lists - * @throws Exception - */ - public void prepareContactList() - throws Exception - { - fixture.clearProvidersLists(); - - Object o = new Object(); - synchronized(o) - { - o.wait(2000); - } - - try - { - opSetPresence1.subscribe(fixture.userID2); - } - catch (OperationFailedException ex) - { - // the contact already exist its OK - } - - try - { - opSetPresence2.subscribe(fixture.userID1); - } - catch (OperationFailedException ex1) - { - // the contact already exist its OK - } - - synchronized(o) - { - o.wait(2000); - } - } - - /** - * Send an instant message from the tested operation set and assert - * reception by the tester agent. - */ - public void firstTestReceiveMessage() - { - ContactGroup rootGroup - = ((OperationSetPersistentPresence)opSetPresence2).getServerStoredContactListRoot(); - - logger.debug("=========== Server Stored Contact List ================="); - - logger.debug("rootGroup="+rootGroup.getGroupName() - +" rootGroup.childContacts="+rootGroup.countContacts() - + "rootGroup.childGroups="+rootGroup.countSubgroups() - + "Printing rootGroupContents=\n"+rootGroup.toString()); - - String body = "This is an IM coming from the tester agent" - + " on " + new Date().toString(); - - ImEventCollector evtCollector = new ImEventCollector(); - - //add a msg listener and register to the op set and send an instant - //msg from the tester agent. - opSetBasicIM1.addMessageListener(evtCollector); - - Contact testerAgentContact - = opSetPresence2.findContactByID(fixture.userID1); - - logger.debug("Will send message " + body + " to: " + testerAgentContact); - - opSetBasicIM2.sendInstantMessage(testerAgentContact, - opSetBasicIM2.createMessage(body)); - - evtCollector.waitForEvent(10000); - - opSetBasicIM1.removeMessageListener(evtCollector); - - //assert reception of a message event - assertTrue( "No events delivered upon a received message" - , evtCollector.collectedEvents.size() > 0); - - //assert event instance of Message Received Evt - assertTrue( "Received evt was not an instance of " - + MessageReceivedEvent.class.getName() - , evtCollector.collectedEvents.get(0) - instanceof MessageReceivedEvent); - - //assert source contact == testAgent.uin - MessageReceivedEvent evt - = (MessageReceivedEvent)evtCollector.collectedEvents.get(0); - assertEquals("message sender " - , evt.getSourceContact().getAddress() - , fixture.userID2); - - //assert messageBody == body - assertEquals("message body", body, evt.getSourceMessage().getContent()); - } - - /** - * Send an instant message from the tester agent and assert reception by - * the tested implementation - */ - public void thenTestSendMessage() - { - String body = "This is an IM coming from the tested implementation" - + " on " + new Date().toString(); - - //create the message - net.java.sip.communicator.service.protocol.Message msg - = opSetBasicIM1.createMessage(body); - - //register a listener in the op set - ImEventCollector imEvtCollector1 = new ImEventCollector(); - opSetBasicIM1.addMessageListener(imEvtCollector1); - - //register a listener in the tester agent - ImEventCollector imEvtCollector2 = new ImEventCollector(); - opSetBasicIM2.addMessageListener(imEvtCollector2); - - Contact testerAgentContact - = opSetPresence1.findContactByID(fixture.userID2); - - opSetBasicIM1.sendInstantMessage(testerAgentContact, msg); - - imEvtCollector1.waitForEvent(10000); - imEvtCollector2.waitForEvent(10000); - - opSetBasicIM1.removeMessageListener(imEvtCollector1); - opSetBasicIM2.removeMessageListener(imEvtCollector2); - - //verify that the message delivered event was dispatched - assertTrue( "No events delivered when sending a message" - , imEvtCollector1.collectedEvents.size() > 0); - - assertTrue( "Received evt was not an instance of " - + MessageDeliveredEvent.class.getName() - , imEvtCollector1.collectedEvents.get(0) - instanceof MessageDeliveredEvent); - - MessageDeliveredEvent evt - = (MessageDeliveredEvent)imEvtCollector1.collectedEvents.get(0); - assertEquals("message destination " - , evt.getDestinationContact().getAddress() - , fixture.userID2); - - assertSame("source message", msg, evt.getSourceMessage()); - - - //verify that the message has successfully arived at the destination - assertTrue( "No messages received by the tester agent" - , imEvtCollector2.collectedEvents.size() > 0); - String receivedBody = - ((MessageReceivedEvent)imEvtCollector2.collectedEvents - .get(0)).getSourceMessage().getContent(); - - assertEquals("received message body", msg.getContent(), receivedBody); - } - - /** - * Creates an Message through the simple createMessage() method and inspects - * its parameters. - */ - public void testCreateMessage1() - { - String body = "This is an IM coming from the tested implementation" - + " on " + new Date().toString(); - net.java.sip.communicator.service.protocol.Message msg - = opSetBasicIM1.createMessage(body); - - assertEquals("message body", body, msg.getContent()); - assertTrue("message body bytes" - , Arrays.equals(body.getBytes(), msg.getRawData())); - assertEquals("message length", body.length(), msg.getSize()); - assertEquals("message content type" - , OperationSetBasicInstantMessaging.DEFAULT_MIME_TYPE - , msg.getContentType()); - - assertEquals("message encoding" - , OperationSetBasicInstantMessaging.DEFAULT_MIME_ENCODING - , msg.getEncoding()); - - assertNotNull("message uid", msg.getMessageUID()); - - //a further test on message uid. - net.java.sip.communicator.service.protocol.Message msg2 - = opSetBasicIM1.createMessage(body); - assertFalse("message uid", msg.getMessageUID().equals( - msg2.getMessageUID())); - } - - /** - * Creates an Message through the advance createMessage() method and - * inspects its parameters. - */ - public void testCreateMessage2() - throws UnsupportedEncodingException - { - String body = "This is an IM coming from the tested implementation" - + " on " + new Date().toString(); - String contentType = "text/html"; - String encoding = "UTF-16"; - String subject = "test message"; - net.java.sip.communicator.service.protocol.Message msg = - opSetBasicIM1.createMessage(body, contentType, encoding, subject); - byte[] bodyBytes = body.getBytes(encoding); - - assertEquals("message body", body, msg.getContent()); - assertTrue("message body bytes" - , Arrays.equals(bodyBytes, msg.getRawData())); - assertEquals("message length", bodyBytes.length, msg.getSize()); - assertEquals("message content type", contentType, msg.getContentType()); - assertEquals("message encoding", encoding, msg.getEncoding()); - assertNotNull("message uid", msg.getMessageUID()); - - //a further test on message uid. - net.java.sip.communicator.service.protocol.Message msg2 - = opSetBasicIM1.createMessage(body); - assertFalse("message uid", msg.getMessageUID().equals( - msg2.getMessageUID())); - } - - /** - * Collects instant messaging events. - */ - private class ImEventCollector implements MessageListener - { - private List collectedEvents = new LinkedList(); - /** - * Called when a new incoming Message has been received. - * @param evt the MessageReceivedEvent containing the newly - * received message, its sender and other details. - */ - public void messageReceived(MessageReceivedEvent evt) - { - logger.debug("Received a MessageReceivedEvent: " + evt); - - synchronized(this) - { - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Called to indicated that delivery of a message sent earlier has failed. - * Reason code and phrase are contained by the MessageFailedEvent - * @param evt the MessageFailedEvent containing the ID of the - * message whose delivery has failed. - */ - public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) - { - logger.debug("Received a MessageDeliveryFailedEvent: " + evt); - - synchronized(this) - { - collectedEvents.add(evt); - notifyAll(); - } - } - - - /** - * Called when the underlying implementation has received an indication - * that a message, sent earlier has been successfully received by the - * destination. - * @param evt the MessageDeliveredEvent containing the id of the message - * that has caused the event. - */ - public void messageDelivered(MessageDeliveredEvent evt) - { - logger.debug("Received a MessageDeliveredEvent: " + evt); - - synchronized(this) - { - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whichever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - synchronized(this) - { - - if(collectedEvents.size() > 0) - { - logger.trace("ImEvent already received. " + collectedEvents); - return; - } - - try{ - wait(waitFor); - } - catch (InterruptedException ex) - { - logger.debug( - "Interrupted while waiting for a message evt", ex); - } - } - } - } - - /** - * A method that would simply send messages to a group of people so that - * they would get notified that tests are being run. - */ - public void testSendFunMessages() - { - String hostname = ""; - - try{ - hostname = java.net.InetAddress.getLocalHost().getHostName() + ": "; - }catch (UnknownHostException ex){} - - String message = hostname - + "Hello this is the SIP Communicator (version " - + System.getProperty("sip-communicator.version") - + ") build on: " - + new Date().toString() - + ". Have a very nice day!"; - - String list = System.getProperty("accounts.reporting.YAHOO_REPORT_LIST"); - - logger.debug("Will send message " + message + " to: " + list); - - //if no property is specified - return - if(list == null || list.trim().length() == 0) - return; - - StringTokenizer tokenizer = new StringTokenizer(list, " "); - - while(tokenizer.hasMoreTokens()) - { - String contactID = tokenizer.nextToken(); - Contact contact - = opSetPresence2.findContactByID(contactID); - - if(contact == null) - { - try - { - opSetPresence2.subscribe(contactID); - Object o = new Object(); - synchronized (o) - { - o.wait(2000); - } - } - catch (Exception ex1) - { - continue; - } - } - - contact - = opSetPresence2.findContactByID(contactID); - - opSetBasicIM2.sendInstantMessage(contact, - opSetBasicIM2.createMessage(message)); - } - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetFileTransferImpl.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetFileTransferImpl.java deleted file mode 100644 index 90a2ff3..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetFileTransferImpl.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.slick.protocol.generic.*; -import net.java.sip.communicator.util.*; - -import org.osgi.framework.*; - -/** - * Implementation for generic file transfer. - * @author Damian Minkov - */ -public class TestOperationSetFileTransferImpl - extends TestOperationSetFileTransfer -{ - private static final Logger logger = - Logger.getLogger(TestOperationSetFileTransferImpl.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - - private OperationSetPresence opSetPresence1 = null; - private OperationSetPresence opSetPresence2 = null; - - private OperationSetFileTransfer opSetFT1 = null; - private OperationSetFileTransfer opSetFT2 = null; - - private static Contact contact1 = null; - private static Contact contact2 = null; - - @Override - public Contact getContact1() - { - if(contact1 == null) - { - contact1 = opSetPresence1.findContactByID(fixture.userID2); - } - - return contact1; - } - - @Override - public Contact getContact2() - { - if(contact2 == null) - { - contact2 = opSetPresence2.findContactByID(fixture.userID1); - } - - return contact2; - } - - @Override - public void start() - throws Exception - { - fixture.setUp(); - - Map supportedOperationSets1 = - fixture.provider1.getSupportedOperationSets(); - - if ( supportedOperationSets1 == null - || supportedOperationSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //we also need the presence op set in order to retrieve contacts. - opSetPresence1 = - (OperationSetPresence)supportedOperationSets1.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence1 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - - opSetFT1 = - (OperationSetFileTransfer)supportedOperationSets1.get( - OperationSetFileTransfer.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetFT1 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the FileTransferOperationSets"); - } - - Map supportedOperationSets2 = - fixture.provider2.getSupportedOperationSets(); - - if ( supportedOperationSets2 == null - || supportedOperationSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - opSetPresence2 = - (OperationSetPresence) supportedOperationSets2.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence2 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - - opSetFT2 = - (OperationSetFileTransfer)supportedOperationSets2.get( - OperationSetFileTransfer.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetFT2 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the FileTransferOperationSets"); - } - - prepareContactList(); - } - - @Override - public void stop() - throws Exception - { - fixture.tearDown(); - } - - /** - * Create the list to be sure that contacts exchanging messages - * exists in each other lists - * @throws Exception - */ - public void prepareContactList() - throws Exception - { - // clear the provider the first time we run a filetransfer list - if(getContact1() == null && getContact2() == null) - fixture.clearProvidersLists(); - - if(getContact1() == null) - { - Object o = new Object(); - synchronized(o) - { - o.wait(2000); - } - - try - { - opSetPresence1.setAuthorizationHandler(new AuthHandler()); - opSetPresence1.subscribe(fixture.userID2); - } - catch (OperationFailedException ex) - { - // the contact already exist its OK - } - } - - if(getContact2() == null) - { - try - { - opSetPresence2.setAuthorizationHandler(new AuthHandler()); - opSetPresence2.subscribe(fixture.userID1); - } - catch (OperationFailedException ex1) - { - // the contact already exist its OK - } - - logger.info("will wait till the list prepare is completed"); - Object o = new Object(); - synchronized(o) - { - o.wait(4000); - } - } - } - - @Override - public OperationSetFileTransfer getOpSetFilTransfer1() - { - return opSetFT1; - } - - @Override - public OperationSetFileTransfer getOpSetFilTransfer2() - { - return opSetFT2; - } - - @Override - public BundleContext getContext() - { - return AdHocMultiUserChatSlickFixture.bc; - } - - @Override - public boolean enableTestSendAndReceive() - { - return true; - } - - @Override - public boolean enableTestSenderCancelBeforeAccepted() - { - return true; - } - - @Override - public boolean enableTestReceiverDecline() - { - return true; - } - - @Override - public boolean enableTestReceiverCancelsWhileTransfering() - { - return true; - } - - @Override - public boolean enableTestSenderCancelsWhileTransfering() - { - return true; - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPersistentPresence.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPersistentPresence.java deleted file mode 100644 index 2ebf0e6..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPersistentPresence.java +++ /dev/null @@ -1,582 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.slick.protocol.generic.*; -import net.java.sip.communicator.util.*; - -/** - * @author Damian Minkov - */ -public class TestOperationSetPersistentPresence - extends TestCase -{ - private static final Logger logger = - Logger.getLogger(TestOperationSetPersistentPresence.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - private OperationSetPersistentPresence opSetPersPresence1 = null; - private OperationSetPersistentPresence opSetPersPresence2 = null; - private static final String testGroupName = "NewGroup"; - private static final String testGroupName2 = "Renamed"; - - public TestOperationSetPersistentPresence(String name) - { - super(name); - } - - /** - * Creates a test suite containing all tests of this class followed by - * test methods that we want executed in a specified order. - * @return the Test suite to run - */ - public static Test suite() - { - TestSuite suite = - new TestSuite(); - - //the following 2 need to be run in the specified order. - //(postTestRemoveGroup() needs the group created from - //postTestCreateGroup() ) - suite.addTest( - new TestOperationSetPersistentPresence("postTestCreateGroup")); - - //rename - //suite.addTest( new TestOperationSetPersistentPresence( - // "postTestRenameGroup")); - - suite.addTest( - new TestOperationSetPersistentPresence("postTestRemoveGroup")); - - // create the contact list - suite.addTest( - new TestOperationSetPersistentPresence("prepareContactList")); - - suite.addTestSuite(TestOperationSetPersistentPresence.class); - - return suite; - } - - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - - Map supportedOperationSets1 = - fixture.provider1.getSupportedOperationSets(); - - if ( supportedOperationSets1 == null - || supportedOperationSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this Yahoo implementation. "); - - //get the operation set presence here. - opSetPersPresence1 = - (OperationSetPersistentPresence)supportedOperationSets1.get( - OperationSetPersistentPresence.class.getName()); - - //if still null then the implementation doesn't offer a presence - //operation set which is unacceptable for yahoo. - if (opSetPersPresence1 == null) - throw new NullPointerException( - "An implementation of the Yahoo service must provide an " - + "implementation of at least the one of the Presence " - + "Operation Sets"); - - // lets do it once again for the second provider - Map supportedOperationSets2 = - fixture.provider2.getSupportedOperationSets(); - - if (supportedOperationSets2 == null - || supportedOperationSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - + "this Yahoo implementation. "); - - //get the operation set presence here. - opSetPersPresence2 = - (OperationSetPersistentPresence) supportedOperationSets2.get( - OperationSetPersistentPresence.class.getName()); - - //if still null then the implementation doesn't offer a presence - //operation set which is unacceptable for yahoo. - if (opSetPersPresence2 == null) - throw new NullPointerException( - "An implementation of the yahoo service must provide an " - + "implementation of at least the one of the Presence " - + "Operation Sets"); - } - - @Override - protected void tearDown() throws Exception - { - fixture.tearDown(); - super.tearDown(); - } - - /** - * Retrieves a server stored contact list and checks whether it contains - * all contacts that have been added there during the initialization - * phase by the testerAgent. - */ - public void testRetrievingServerStoredContactList() - { - ContactGroup rootGroup - = opSetPersPresence1.getServerStoredContactListRoot(); - - logger.debug("=========== Server Stored Contact List ================="); - - logger.debug("rootGroup="+rootGroup.getGroupName() - +" rootGroup.childContacts="+rootGroup.countContacts() - + "rootGroup.childGroups="+rootGroup.countSubgroups() - + "Printing rootGroupContents=\n"+rootGroup.toString()); - - Hashtable> expectedContactList - = AdHocMultiUserChatSlickFixture.preInstalledBuddyList; - - logger.debug("============== Expected Contact List ==================="); - logger.debug(expectedContactList); - - //Go through the contact list retrieved by the persistence presence set - //and remove the name of every contact and group that we find there from - //the expected contct list hashtable. - Iterator groups = rootGroup.subgroups(); - while (groups.hasNext() ) - { - ContactGroup group = groups.next(); - - List expectedContactsInGroup - = expectedContactList.get(group.getGroupName()); - - // When sending the offline message - // the sever creates a group NotInContactList, - // because the buddy we are sending message to is not in - // the contactlist. So this group must be ignored - // Also we must ignore the group created by default - // from the yahoo lib - if(!group.getGroupName().equals("NotInContactList") && - !group.getGroupName().equals("Default group")) - { - assertNotNull("Group " + group.getGroupName() + - " was returned by " - + - "the server but was not in the expected contact list." - , expectedContactsInGroup); - - Iterator contactsIter = group.contacts(); - while(contactsIter.hasNext()) - { - String contactID = contactsIter.next().getAddress(); - expectedContactsInGroup.remove(contactID); - } - - //If we've removed all the sub contacts, remove the group too. - if(expectedContactsInGroup.size() == 0) - expectedContactList.remove(group.getGroupName()); - } - } - - //whatever we now have in the expected contact list snapshot are groups, - //that have been added by the testerAgent but that were not retrieved - //by the persistent presence operation set. - assertTrue("The following contacts were on the server sidec contact " - +"list, but were not returned by the pers. pres. op. set" - + expectedContactList.toString() - , expectedContactList.isEmpty()); - } - - /** - * Creates a group in the server stored contact list, makes sure that the - * corresponding event has been generated and verifies that the group is - * in the list. - * - * @throws java.lang.Exception - */ - public void postTestCreateGroup() - throws Exception - { - // first clear the list - fixture.clearProvidersLists(); - - waitFor(5000); - - logger.trace("testing creation of server stored groups"); - //first add a listener - GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); - opSetPersPresence1 - .addServerStoredGroupChangeListener(groupChangeCollector); - - //create the group - opSetPersPresence1.createServerStoredContactGroup( - opSetPersPresence1.getServerStoredContactListRoot(), testGroupName); - - groupChangeCollector.waitForEvent(10000); - - opSetPersPresence1 - .removeServerStoredGroupChangeListener(groupChangeCollector); - - // check whether we got group created event - assertEquals("Collected Group Change events: ", - 1, groupChangeCollector.collectedEvents.size()); - - assertEquals("Group name.", testGroupName, - ((ServerStoredGroupEvent)groupChangeCollector.collectedEvents - .get(0)).getSourceGroup().getGroupName()); - - // check whether the group is retrievable - ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName); - - assertNotNull("A newly created group was not in the contact list.", - group); - - assertEquals("New group name", testGroupName, group.getGroupName()); - - // when opearting with groups . the group must have entries - // so changes to take effect. Otherwise group will be lost after loggingout - try - { - opSetPersPresence1.subscribe(group, fixture.userID2); - - waitFor(1500); - } - catch (Exception ex) - { - fail("error adding entry to group : " + - group.getGroupName() + " " + - ex.getMessage()); - } - } - - - /** - * Removes the group created in the server stored contact list by the create - * group test, makes sure that the corresponding event has been generated - * and verifies that the group is not in the list any more. - */ - public void postTestRemoveGroup() - { - logger.trace("testing removal of server stored groups"); - - //first add a listener - GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); - opSetPersPresence1 - .addServerStoredGroupChangeListener(groupChangeCollector); - - try - { - //remove the group - opSetPersPresence1.removeServerStoredContactGroup( - opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName)); - } - catch(OperationFailedException ex) - { - logger.error("error removing group", ex); - } - - groupChangeCollector.waitForEvent(10000); - - opSetPersPresence1 - .removeServerStoredGroupChangeListener(groupChangeCollector); - - // check whether we got group created event - assertEquals("Collected Group Change event", - 1, groupChangeCollector.collectedEvents.size()); - - assertEquals("Group name.", testGroupName, - ((ServerStoredGroupEvent)groupChangeCollector.collectedEvents - .get(0)).getSourceGroup().getGroupName()); - - // check whether the group is still on the contact list - ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName); - - assertNull("A freshly removed group was still on the contact list. - " + group, - group); - } - - /** - * Renames our test group and checks whether corresponding events are - * triggered. Verifies whether the group has really changed its name and - * whether it is findable by its new name. Also makes sure that it does - * not exist under its previous name any more. - */ - public void postTestRenameGroup() - { - logger.trace("Testing renaming groups."); - - ContactGroup group = opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName); - - //first add a listener - GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); - opSetPersPresence1 - .addServerStoredGroupChangeListener(groupChangeCollector); - - //change the name and wait for a confirmation event - opSetPersPresence1.renameServerStoredContactGroup(group, testGroupName2); - - groupChangeCollector.waitForEvent(10000); - - opSetPersPresence1 - .removeServerStoredGroupChangeListener(groupChangeCollector); - - //examine the event - assertEquals("Collected Group Change event", - 1, groupChangeCollector.collectedEvents.size()); - - assertEquals("Group name.", testGroupName2, - ((ServerStoredGroupEvent)groupChangeCollector.collectedEvents - .get(0)).getSourceGroup().getGroupName()); - - // check whether the group is still on the contact list - ContactGroup oldGroup = opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName); - - assertNull("A group was still findable by its old name after renaming.", - oldGroup); - - //make sure that we could find the group by its new name. - ContactGroup newGroup = opSetPersPresence1.getServerStoredContactListRoot() - .getGroup(testGroupName2); - - assertNotNull("Could not find a renamed group by its new name.", - newGroup); - } - - /** - * Create the contact list. Later will be test to be sure that creating is ok - * @throws Exception - */ - public void prepareContactList() - throws Exception - { - logger.trace("prepareContactList"); - - fixture.clearProvidersLists(); - - waitFor(3000); - - String contactList = System.getProperty( - YahooProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME, null); - - logger.debug("The " - + YahooProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME - + " property is set to=" + contactList); - - if( contactList == null - || contactList.trim().length() < 6)//at least 4 for a UIN, 1 for the - // dot and 1 for the grp name - throw new IllegalArgumentException( - "The " + - YahooProtocolProviderServiceLick.CONTACT_LIST_PROPERTY_NAME + - " property did not contain a contact list."); - StringTokenizer tokenizer = new StringTokenizer(contactList, " \n\t"); - - logger.debug("tokens contained by the CL tokenized=" - +tokenizer.countTokens()); - - Hashtable> contactListToCreate = new Hashtable>(); - - //go over all group.uin tokens - while (tokenizer.hasMoreTokens()) - { - String groupUinToken = tokenizer.nextToken(); - int dotIndex = groupUinToken.indexOf("."); - - if ( dotIndex == -1 ) - { - throw new IllegalArgumentException(groupUinToken - + " is not a valid Group.UIN token"); - } - - String groupName = groupUinToken.substring(0, dotIndex); - String uin = groupUinToken.substring(dotIndex + 1); - - if( groupName.trim().length() < 1 - || uin.trim().length() < 4 ) - { - throw new IllegalArgumentException( - groupName + " or " + uin + - " are not a valid group name or yahoo UIN."); - } - - //check if we've already seen this group and if not - add it - List uinInThisGroup = contactListToCreate.get(groupName); - if (uinInThisGroup == null) - { - uinInThisGroup = new ArrayList(); - contactListToCreate.put(groupName, uinInThisGroup); - } - - uinInThisGroup.add(uin); - } - - // now init the list - Enumeration newGroupsEnum = contactListToCreate.keys(); - - GroupChangeCollector groupChangeCollector = new GroupChangeCollector(); - opSetPersPresence1.addServerStoredGroupChangeListener(groupChangeCollector); - - //go over all groups in the contactsToAdd table - while (newGroupsEnum.hasMoreElements()) - { - String groupName = newGroupsEnum.nextElement(); - logger.debug("Will add group " + groupName); - - opSetPersPresence1.createServerStoredContactGroup( - opSetPersPresence1.getServerStoredContactListRoot(), groupName); - - groupChangeCollector.waitForEvent(3000); - - ContactGroup newlyCreatedGroup = - opSetPersPresence1.getServerStoredContactListRoot().getGroup(groupName); - - Iterator contactsToAddToThisGroup - = contactListToCreate.get(groupName).iterator(); - while (contactsToAddToThisGroup.hasNext()) - { - String id = contactsToAddToThisGroup.next(); - - logger.debug("Will add buddy " + id); - opSetPersPresence1.subscribe(newlyCreatedGroup, id); - } - } - - waitFor(4000); - - //store the created contact list for later reference - YahooSlickFixture.preInstalledBuddyList = contactListToCreate; - } - - private void waitFor(long time) - throws Exception - { - Object o = new Object(); - synchronized(o) - { - o.wait(time); - } - } - - /** - * The class would listen for and store received events delivered to - * ServerStoredGroupListeners. - */ - private class GroupChangeCollector implements ServerStoredGroupListener - { - public ArrayList collectedEvents = new ArrayList(); - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whicever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - synchronized(this) - { - if(collectedEvents.size() > 0) - return; - - try{ - wait(waitFor); - } - catch (InterruptedException ex) - { - logger.debug( - "Interrupted while waiting for a subscription evt", ex); - } - } - } - - /** - * Called whnever an indication is received that a new server stored - * group is created. - * @param evt a ServerStoredGroupChangeEvent containing a reference to - * the newly created group. - */ - public void groupCreated(ServerStoredGroupEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Called when an indication is received that the name of a server stored - * contact group has changed. - * @param evt a ServerStoredGroupChangeEvent containing the details of the - * name change. - */ - public void groupNameChanged(ServerStoredGroupEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Called whnever an indication is received that an existing server stored - * group has been removed. - * @param evt a ServerStoredGroupChangeEvent containing a reference to the - * newly created group. - */ - public void groupRemoved(ServerStoredGroupEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Called whnever an indication is received that an existing server - * stored group has been resolved. - * @param evt a ServerStoredGroupChangeEvent containing a reference to - * the resolved group. - */ - public void groupResolved(ServerStoredGroupEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPresence.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPresence.java deleted file mode 100644 index 1413a42..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetPresence.java +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.beans.*; -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.service.protocol.yahooconstants.*; -import net.java.sip.communicator.util.*; - -/** - * Tests yahoo implementations of a Presence Operation Set. Tests in this class - * verify functionality such as: Changing local (our own) status and - * corresponding event dispatching; Querying status of contacts, Subscribing - * for presence notifications upong status changes of specific contacts. - *

    - * Using a custom suite() method, we make sure that apart from standard test - * methods (those with a test prefix) we also execute those that - * we want run in a specific order like for example - postTestSubscribe() and - * postTestUnsubscribe(). - *

    - * @author Damian Minkov - */ -public class TestOperationSetPresence - extends TestCase -{ - private static final Logger logger = - Logger.getLogger(TestOperationSetPresence.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - private OperationSetPresence operationSetPresence1 = null; - private OperationSetPresence operationSetPresence2 = null; - - private AuthHandler authHandler1 = null; - private AuthHandler authHandler2 = null; - - public TestOperationSetPresence(String name) - { - super(name); - } - - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - - Map supportedOperationSets1 = - fixture.provider1.getSupportedOperationSets(); - - if ( supportedOperationSets1 == null - || supportedOperationSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //get the operation set presence here. - operationSetPresence1 = - (OperationSetPresence)supportedOperationSets1.get( - OperationSetPresence.class.getName()); - - //if the op set is null then the implementation doesn't offer a presence - //operation set which is unacceptable for yahoo. - if (operationSetPresence1 == null) - { - throw new NullPointerException( - "An implementation of the yahoo service must provide an " - + "implementation of at least the one of the Presence " - + "Operation Sets"); - } - - // do it once again for the second provider - Map supportedOperationSets2 = - fixture.provider2.getSupportedOperationSets(); - - if ( supportedOperationSets2 == null - || supportedOperationSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this yahoo implementation. "); - - //get the operation set presence here. - operationSetPresence2 = - (OperationSetPresence)supportedOperationSets2.get( - OperationSetPresence.class.getName()); - - //if the op set is null then the implementation doesn't offer a presence - //operation set which is unacceptable for yahoo. - if (operationSetPresence2 == null) - { - throw new NullPointerException( - "An implementation of the yahoo service must provide an " - + "implementation of at least the one of the Presence " - + "Operation Sets"); - } - - if(authHandler1 == null) - { - authHandler1 = new AuthHandler(operationSetPresence1); - operationSetPresence1.setAuthorizationHandler(authHandler1); - } - - if(authHandler2 == null) - { - authHandler2 = new AuthHandler(operationSetPresence2); - operationSetPresence2.setAuthorizationHandler(authHandler2); - } - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - - fixture.tearDown(); - } - - /** - * Creates a test suite containing all tests of this class followed by - * test methods that we want executed in a specified order. - * @return Test - */ - public static Test suite() - { - //return an (almost) empty suite if we're running in offline mode. - if(YahooSlickFixture.onlineTestingDisabled) - { - TestSuite suite = new TestSuite(); - //the only test around here that we could run without net - //connectivity - suite.addTest( - new TestOperationSetPresence( - "testSupportedStatusSetForCompleteness")); - return suite; - } - - TestSuite suite = new TestSuite(); - - // clear the lists before subscribing users - suite.addTest(new TestOperationSetPresence("clearLists")); - - // first postTestSubscribe. to be sure that contacts are in the - // list so we can further continue and test presences each other - suite.addTest(new TestOperationSetPresence("postTestSubscribe")); - - // add other tests - suite.addTestSuite(TestOperationSetPresence.class); - - // now test unsubscribe - suite.addTest(new TestOperationSetPresence("postTestUnsubscribe")); - - return suite; - } - - /** - * Verifies that all necessary yahoo test states are supported by the - * implementation. - */ - public void testSupportedStatusSetForCompleteness() - { - //first create a local list containing the presence status instances - //supported by the underlying implementation. - Iterator supportedStatusSetIter = - operationSetPresence1.getSupportedStatusSet(); - - List supportedStatusSet - = new LinkedList(); - while (supportedStatusSetIter.hasNext()){ - supportedStatusSet.add(supportedStatusSetIter.next()); - } - - //create a copy of the MUST status set and remove any matching status - //that is also present in the supported set. - List requiredStatusSetCopy - = (List) YahooStatusEnum.yahooStatusSet.clone(); - - requiredStatusSetCopy.removeAll(supportedStatusSet); - - //if we have anything left then the implementation is wrong. - int unsupported = requiredStatusSetCopy.size(); - assertTrue( "There are " + unsupported + " statuses as follows:" - + requiredStatusSetCopy, - unsupported == 0); - } - - /** - * Verify that changing state to STEPPED_OUT works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToSteppedOut() throws Exception - { - subtestStateTransition(YahooStatusEnum.STEPPED_OUT); - } - - /** - * Verify that changing state to NOT_IN_OFFICE works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToNotInOffice() throws Exception - { - subtestStateTransition(YahooStatusEnum.NOT_IN_OFFICE); - } - - /** - * Verify that changing state to BUSY works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToBusy() throws Exception - { - subtestStateTransition(YahooStatusEnum.BUSY); - } - - /** - * Verify that changing state to FREE_FOR_CHAT works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToIdle() throws Exception - { - subtestStateTransition(YahooStatusEnum.IDLE); - } - - /** - * Verify that changing state to BE_RIGHT_BACK works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToBRB() throws Exception - { - subtestStateTransition(YahooStatusEnum.BE_RIGHT_BACK); - } - - /** - * Verify that changing state to OUT_TO_LUNCH works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToOutToLunch() throws Exception - { - subtestStateTransition(YahooStatusEnum.OUT_TO_LUNCH); - } - - /** - * Verify that changing state to ON_THE_PHONE works as supposed to and that it - * generates the corresponding event. - * @throws Exception in case a failure occurs while the operation set - * is switching to the new state. - */ - public void testChangingStateToOnThePhone() throws Exception - { - subtestStateTransition(YahooStatusEnum.ON_THE_PHONE); - } - - /** - * Used by methods testing state transiotions - * - * @param newStatus the YahooStatusEnum field corresponding to the status - * that we'd like the opeation set to enter. - * - * @throws Exception in case changing the state causes an exception - */ - public void subtestStateTransition( YahooStatusEnum newStatus) - throws Exception - { - logger.trace(" --=== beginning state transition test ===--"); - - PresenceStatus oldStatus = operationSetPresence2.getPresenceStatus(); - - logger.debug( "old status is=" + oldStatus.getStatusName() - + " new status=" + newStatus.getStatusName() - + " for contact : " + fixture.userID2); - - //First register a listener to make sure that all corresponding - //events have been generated. - PresenceStatusEventCollector statusEventCollector2 - = new PresenceStatusEventCollector(); - ContactPresenceEventCollector statusEventCollector1 - = new ContactPresenceEventCollector(fixture.userID2, newStatus); - operationSetPresence2.addProviderPresenceStatusListener( - statusEventCollector2); - operationSetPresence1.addContactPresenceStatusListener( - statusEventCollector1); - - //change the status - operationSetPresence2.publishPresenceStatus(newStatus, null); - - //test event notification. - statusEventCollector2.waitForPresEvent(10000); - statusEventCollector1.waitForEvent(10000); - - operationSetPresence2.removeProviderPresenceStatusListener( - statusEventCollector2); - operationSetPresence1.removeContactPresenceStatusListener( - statusEventCollector1); - - assertEquals("Events dispatched during an event transition.", - 1, statusEventCollector2.collectedPresEvents.size()); - assertEquals("A status changed event contained wrong old status.", - oldStatus, - ((ProviderPresenceStatusChangeEvent) - statusEventCollector2.collectedPresEvents.get(0)) - .getOldStatus()); - assertEquals("A status changed event contained wrong new status.", - newStatus, - ((ProviderPresenceStatusChangeEvent) - statusEventCollector2.collectedPresEvents.get(0)) - .getNewStatus()); - - // verify that the operation set itself is aware of the status change - assertEquals("opSet.getPresenceStatus() did not return properly.", - newStatus, - operationSetPresence2.getPresenceStatus()); - - YahooStatusEnum actualStatus = (YahooStatusEnum) - operationSetPresence1.queryContactStatus(fixture.userID2); - - assertEquals("The underlying implementation did not switch to the " - +"requested presence status.", - newStatus, - actualStatus); - - logger.trace(" --=== finished test ===--"); - } - - /** - * The method would add a subscription for a contact, wait for a - * subscription event confirming the subscription, then change the status - * of the newly added contact (which is actually the testerAgent) and - * make sure that the corresponding notification events have been generated. - * - * @throws java.lang.Exception if an exception occurs during testing. - */ - public void postTestSubscribe() - throws Exception - { - logger.debug("Testing Subscription and Subscription Event Dispatch."); - - dumplists(); - - SubscriptionEventCollector subEvtCollector - = new SubscriptionEventCollector(); - operationSetPresence1.addSubscriptionListener(subEvtCollector); - - - synchronized (subEvtCollector){ - operationSetPresence1.subscribe(fixture.userID2); - //we may already have the event, but it won't hurt to check. - subEvtCollector.waitForEvent(10000); - operationSetPresence1.removeSubscriptionListener(subEvtCollector); - } - - assertEquals("Subscription event dispatching failed." - , 1, subEvtCollector.collectedEvents.size()); - SubscriptionEvent subEvt = - (SubscriptionEvent)subEvtCollector.collectedEvents.get(0); - - assertEquals("SubscriptionEvent Source:", - fixture.userID2, - ((Contact)subEvt.getSource()).getAddress()); - assertEquals("SubscriptionEvent Source Contact:", - fixture.userID2, - subEvt.getSourceContact().getAddress()); - assertSame("SubscriptionEvent Source Provider:", - fixture.provider1, - subEvt.getSourceProvider()); - - subEvtCollector.collectedEvents.clear(); - - // make the user agent tester change its states and make sure we are - // notified - logger.debug("Testing presence notifications."); - YahooStatusEnum oldStatus - = (YahooStatusEnum)operationSetPresence2.getPresenceStatus(); - - - YahooStatusEnum newStatus = YahooStatusEnum.ON_THE_PHONE; - - //in case we are by any chance already in a ON_THE_PHONE status, we'll - //be changing to something else - if(oldStatus.equals(newStatus)){ - newStatus = YahooStatusEnum.BUSY; - } - - //now do the actual status notification testing - ContactPresenceEventCollector contactPresEvtCollector - = new ContactPresenceEventCollector( - fixture.userID2, newStatus); - operationSetPresence1.addContactPresenceStatusListener( - contactPresEvtCollector); - - synchronized (contactPresEvtCollector){ - operationSetPresence2.publishPresenceStatus(newStatus, "new status"); - //we may already have the event, but it won't hurt to check. - contactPresEvtCollector.waitForEvent(10000); - operationSetPresence1 - .removeContactPresenceStatusListener(contactPresEvtCollector); - } - - // something happened. the friend is not added correctly will - // try to remove it and add it again - if(contactPresEvtCollector.collectedEvents.size() == 0) - { - logger.info("ATTENTION: Yahoo friend not added correctly will remove and add him again"); - - // remove it - operationSetPresence1.unsubscribe(subEvt.getSourceContact()); - - // wait remove to be finished - Object lock = new Object(); - synchronized(lock){ - try{ - lock.wait(3000); - }catch (Exception e){} - } - - // add it - operationSetPresence1.addSubscriptionListener(subEvtCollector); - subEvtCollector.collectedEvents.clear(); - synchronized (subEvtCollector){ - operationSetPresence1.subscribe(fixture.userID2); - //we may already have the event, but it won't hurt to check. - subEvtCollector.waitForEvent(10000); - operationSetPresence1.removeSubscriptionListener(subEvtCollector); - } - subEvtCollector.collectedEvents.clear(); - - if(newStatus.equals(YahooStatusEnum.BUSY)){ - newStatus = YahooStatusEnum.OUT_TO_LUNCH; - } - else - newStatus = YahooStatusEnum.BUSY; - - // query it again for the status - contactPresEvtCollector = new ContactPresenceEventCollector( - fixture.userID2, newStatus); - operationSetPresence1.addContactPresenceStatusListener( - contactPresEvtCollector); - - synchronized (contactPresEvtCollector){ -// operationSetPresence2.publishPresenceStatus(newStatus, "new status"); - operationSetPresence2.publishPresenceStatus(newStatus, null); - //we may already have the event, but it won't hurt to check. - contactPresEvtCollector.waitForEvent(10000); - operationSetPresence1 - .removeContactPresenceStatusListener(contactPresEvtCollector); - } - } - - assertEquals("Presence Notif. event dispatching failed." - , 1, contactPresEvtCollector.collectedEvents.size()); - ContactPresenceStatusChangeEvent presEvt = - (ContactPresenceStatusChangeEvent) - contactPresEvtCollector.collectedEvents.get(0); - - assertEquals("Presence Notif. event Source:", - fixture.userID2, - ((Contact)presEvt.getSource()).getAddress()); - assertEquals("Presence Notif. event Source Contact:", - fixture.userID2, - presEvt.getSourceContact().getAddress()); - assertSame("Presence Notif. event Source Provider:", - fixture.provider1, - presEvt.getSourceProvider()); - - PresenceStatus reportedNewStatus = presEvt.getNewStatus(); - PresenceStatus reportedOldStatus = presEvt.getOldStatus(); - - assertEquals( "Reported new PresenceStatus: ", - newStatus, reportedNewStatus ); - - //don't require equality between the reported old PresenceStatus and - //the actual presence status of the tester agent because a first - //notification is not supposed to have the old status as it really was. - assertNotNull( "Reported old PresenceStatus: ", reportedOldStatus ); - - try - { - // add the the user to the reverse side needed for status tests - subEvtCollector.collectedEvents.clear(); - operationSetPresence2.addSubscriptionListener(subEvtCollector); - - synchronized (subEvtCollector) - { - operationSetPresence2.subscribe(fixture.userID1); - //we may already have the event, but it won't hurt to check. - subEvtCollector.waitForEvent(10000); - operationSetPresence2.removeSubscriptionListener( - subEvtCollector); - } - } - catch (OperationFailedException ex) - { - // happens if the user is already subscribed - } - } - - /** - * We unsubscribe from presence notification deliveries concerning - * testerAgent's presence status and verify that we receive the - * subscription removed event. We then make the tester agent change status - * and make sure that no notifications are delivered. - * - * @throws java.lang.Exception in case unsubscribing fails. - */ - public void postTestUnsubscribe() - throws Exception - { - logger.debug("Testing Unsubscribe and unsubscription event dispatch."); - - // First create a subscription and verify that it really gets created. - SubscriptionEventCollector subEvtCollector - = new SubscriptionEventCollector(); - operationSetPresence1.addSubscriptionListener(subEvtCollector); - - Contact yahooTesterAgentContact = operationSetPresence1 - .findContactByID(fixture.userID2); - - assertNotNull( - "Failed to find an existing subscription for the tester agent" - , yahooTesterAgentContact); - - synchronized(subEvtCollector){ - operationSetPresence1.unsubscribe(yahooTesterAgentContact); - subEvtCollector.waitForEvent(10000); - //don't want any more events - operationSetPresence1.removeSubscriptionListener(subEvtCollector); - } - - assertEquals("Subscription event dispatching failed." - , 1, subEvtCollector.collectedEvents.size()); - SubscriptionEvent subEvt = - (SubscriptionEvent)subEvtCollector.collectedEvents.get(0); - - assertEquals("SubscriptionEvent Source:", - yahooTesterAgentContact, subEvt.getSource()); - - assertEquals("SubscriptionEvent Source Contact:", - yahooTesterAgentContact, subEvt.getSourceContact()); - - assertSame("SubscriptionEvent Source Provider:", - fixture.provider1, - subEvt.getSourceProvider()); - - subEvtCollector.collectedEvents.clear(); - - // make the user agent tester change its states and make sure we don't - // get notifications as we're now unsubscribed. - logger.debug("Testing (lack of) presence notifications."); - YahooStatusEnum oldStatus - = (YahooStatusEnum)operationSetPresence2.getPresenceStatus(); - YahooStatusEnum newStatus = YahooStatusEnum.ON_THE_PHONE; - - //in case we are by any chance already in a ON_THE_PHONE status, we'll - //be changing to something else - if(oldStatus.equals(newStatus)){ - newStatus = YahooStatusEnum.BUSY; - } - - //now do the actual status notification testing - ContactPresenceEventCollector contactPresEvtCollector - = new ContactPresenceEventCollector(fixture.userID2, null); - operationSetPresence1.addContactPresenceStatusListener( - contactPresEvtCollector); - - synchronized (contactPresEvtCollector){ - operationSetPresence2.publishPresenceStatus(newStatus, "new status"); - - //we may already have the event, but it won't hurt to check. - contactPresEvtCollector.waitForEvent(10000); - operationSetPresence1 - .removeContactPresenceStatusListener(contactPresEvtCollector); - } - - assertEquals("Presence Notifications were received after unsubscibing." - , 0, contactPresEvtCollector.collectedEvents.size()); - } - - public void clearLists() - throws Exception - { - logger.debug("Clear the two lists before tests"); - - // wait a moment if any event hes left from the previous tests - Object o = new Object(); - synchronized(o) - { - o.wait(2000); - } - - // wait for a moment - // give time the impl to get the lists - logger.debug("start clearing"); - fixture.clearProvidersLists(); - - synchronized(o) - { - o.wait(3000); - } - } - - /** - * An event collector that would collect all events generated by a - * provider after a status change. The collector would also do a notidyAll - * every time it receives an event. - */ - private class PresenceStatusEventCollector - implements ProviderPresenceStatusListener - { - public ArrayList collectedPresEvents = new ArrayList(); - public ArrayList collectedStatMsgEvents = new ArrayList(); - - public void providerStatusChanged(ProviderPresenceStatusChangeEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedPresEvents.size()+")= "+evt); - collectedPresEvents.add(evt); - notifyAll(); - } - } - - public void providerStatusMessageChanged(PropertyChangeEvent evt) - { - synchronized(this) - { - logger.debug("Collected stat.msg. evt(" - +collectedPresEvents.size()+")= "+evt); - collectedStatMsgEvents.add(evt); - notifyAll(); - } - } - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whicever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForPresEvent(long waitFor) - { - logger.trace("Waiting for a change in provider status."); - synchronized(this) - { - if(collectedPresEvents.size() > 0){ - logger.trace("Change already received. " + collectedPresEvents); - return; - } - - try{ - wait(waitFor); - if(collectedPresEvents.size() > 0) - logger.trace("Received a change in provider status."); - else - logger.trace("No change received for "+waitFor+"ms."); - } - catch (InterruptedException ex){ - logger.debug("Interrupted while waiting for a provider evt" - , ex); - } - } - } - - /** - * Blocks until at least one staus message event is received or until - * waitFor miliseconds pass (whichever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for a status message event before simply bailing out. - */ - public void waitForStatMsgEvent(long waitFor) - { - logger.trace("Waiting for a provider status message event."); - synchronized(this) - { - if(collectedStatMsgEvents.size() > 0){ - logger.trace("Stat msg. evt already received. " - + collectedStatMsgEvents); - return; - } - - try{ - wait(waitFor); - if(collectedStatMsgEvents.size() > 0) - logger.trace("Received a prov. stat. msg. evt."); - else - logger.trace("No prov. stat msg. received for " - +waitFor+"ms."); - } - catch (InterruptedException ex){ - logger.debug("Interrupted while waiting for a status msg evt" - , ex); - } - } - } - } - - /** - * The class would listen for and store received subscription modification - * events. - */ - private class SubscriptionEventCollector implements SubscriptionListener - { - public ArrayList collectedEvents = new ArrayList(); - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whicever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - synchronized(this) - { - if(collectedEvents.size() > 0) - { - logger.trace("Event already received. " + collectedEvents); - return; - } - - try{ - wait(waitFor); - } - catch (InterruptedException ex) - { - logger.debug( - "Interrupted while waiting for a subscription evt", ex); - } - } - } - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void subscriptionCreated(SubscriptionEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void subscriptionRemoved(SubscriptionEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void contactModified(ContactPropertyChangeEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void subscriptionMoved(SubscriptionMovedEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void subscriptionFailed(SubscriptionEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - /** - * Stores the received subsctiption and notifies all waiting on this - * object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void subscriptionResolved(SubscriptionEvent evt) - { - synchronized(this) - { - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - - } - - /** - * The class would listen for and store received events caused by changes - * in contact presence states. - */ - private class ContactPresenceEventCollector - implements ContactPresenceStatusListener - { - public ArrayList collectedEvents = new ArrayList(); - private String trackedScreenName = null; - private YahooStatusEnum status = null; - - ContactPresenceEventCollector(String screenname, - YahooStatusEnum wantedStatus) - { - this.trackedScreenName = screenname; - this.status = wantedStatus; - } - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whicever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - synchronized(this) - { - if(collectedEvents.size() > 0) - return; - - try{ - wait(waitFor); - if(collectedEvents.size() > 0) - logger.trace("Received a change in contact status."); - else - logger.trace("No change received for "+waitFor+"ms."); - } - catch (InterruptedException ex) - { - logger.debug( - "Interrupted while waiting for a subscription evt", ex); - } - } - } - - /** - * Stores the received status change event and notifies all waiting on - * this object - * @param evt the SubscriptionEvent containing the corresponding contact - */ - public void contactPresenceStatusChanged( - ContactPresenceStatusChangeEvent evt) - { - synchronized(this) - { - //if the user has specified event details and the received - //event does not match - then ignore it. - if( this.trackedScreenName != null - && !evt.getSourceContact().getAddress() - .equals(trackedScreenName)) - return; - if( status != null - && status != evt.getNewStatus()) - return; - - logger.debug("Collected evt("+collectedEvents.size()+")= "+evt); - collectedEvents.add(evt); - notifyAll(); - } - } - } - - /** - * AuthorizationHandler which accepts all requests! - */ - private class AuthHandler - implements AuthorizationHandler - { - private OperationSetPresence opset = null; - AuthHandler(OperationSetPresence opset) - { - this.opset = opset; - } - - public AuthorizationResponse processAuthorisationRequest( - AuthorizationRequest req, Contact sourceContact) - { -// try{ -// opset.subscribe(sourceContact.getAddress()); -// }catch(Exception ex){} - - return - new AuthorizationResponse(AuthorizationResponse.ACCEPT, ""); - } - public AuthorizationRequest createAuthorizationRequest(Contact contact ) - { - return new AuthorizationRequest(); - } - public void processAuthorizationResponse( - AuthorizationResponse response, Contact sourceContact){} - } - - private void dumplists() - { - // just wait a little all modification events to be received - Object o = new Object(); - synchronized(o) - { - try{o.wait(3000);}catch (InterruptedException ex){} - } - - OperationSetPersistentPresence op1 = (OperationSetPersistentPresence)operationSetPresence1; - OperationSetPersistentPresence op2 = (OperationSetPersistentPresence)operationSetPresence2; - - logger.info("------------ START DUMP LIST " + fixture.userID1 + " ------------"); - ContactGroup rootGroup = op1.getServerStoredContactListRoot(); - Iterator groups = rootGroup.subgroups(); - while (groups.hasNext() ) - { - ContactGroup group = groups.next(); - logger.info("group " + group.getGroupName()); - - Iterator contactsIter = group.contacts(); - while(contactsIter.hasNext()) - { - logger.info("\tcontact " + contactsIter.next()); - } - } - logger.info("------------ END DUMP LIST " + fixture.userID1 + " ------------"); - - - logger.info("------------ START DUMP LIST " + fixture.userID2 + " ------------"); - rootGroup = op2.getServerStoredContactListRoot(); - groups = rootGroup.subgroups(); - while (groups.hasNext() ) - { - ContactGroup group = groups.next(); - logger.info("group " + group.getGroupName()); - - Iterator contactsIter = group.contacts(); - while(contactsIter.hasNext()) - { - logger.info("\tcontact " + contactsIter.next()); - } - } - logger.info("------------ END DUMP LIST " + fixture.userID2 + " ------------"); - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetTypingNotifications.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetTypingNotifications.java deleted file mode 100644 index 5138fed..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestOperationSetTypingNotifications.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.util.*; - -/** - * Tests functionality of the typing notifications operation set. - * - * @author Damian Minkov - */ -public class TestOperationSetTypingNotifications - extends TestCase -{ - private static final Logger logger = - Logger.getLogger(TestOperationSetTypingNotifications.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - private OperationSetTypingNotifications opSetTypingNotifs1 = null; - private OperationSetPresence opSetPresence1 = null; - private OperationSetTypingNotifications opSetTypingNotifs2 = null; - private OperationSetPresence opSetPresence2 = null; - - private OperationSetBasicInstantMessaging opSetBasicIM1 = null; - private OperationSetBasicInstantMessaging opSetBasicIM2 = null; - - - public TestOperationSetTypingNotifications(String name) - { - super(name); - } - - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - - Map supportedOperationSets1 = - fixture.provider1.getSupportedOperationSets(); - - if ( supportedOperationSets1 == null - || supportedOperationSets1.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //get the operation set presence here. - opSetTypingNotifs1 = - (OperationSetTypingNotifications)supportedOperationSets1.get( - OperationSetTypingNotifications.class.getName()); - - //if the op set is null then the implementation doesn't offer a typing.n - //operation set which is unacceptable. - if (opSetTypingNotifs1 == null) - { - throw new NullPointerException( - "No implementation for typing notifications was found"); - } - - opSetBasicIM1 = - (OperationSetBasicInstantMessaging)supportedOperationSets1.get( - OperationSetBasicInstantMessaging.class.getName()); - - if (opSetBasicIM1 == null) - { - throw new NullPointerException( - "No implementation for basic IM was found"); - } - - - //we also need the presence op set in order to retrieve contacts. - opSetPresence1 = - (OperationSetPresence)supportedOperationSets1.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence1 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - - Map supportedOperationSets2 = - fixture.provider2.getSupportedOperationSets(); - - if ( supportedOperationSets2 == null - || supportedOperationSets2.size() < 1) - throw new NullPointerException( - "No OperationSet implementations are supported by " - +"this implementation. "); - - //get the operation set presence here. - opSetTypingNotifs2 = - (OperationSetTypingNotifications)supportedOperationSets2.get( - OperationSetTypingNotifications.class.getName()); - - //if the op set is null then the implementation doesn't offer a typing.n - //operation set which is unacceptable for. - if (opSetTypingNotifs2 == null) - { - throw new NullPointerException( - "No implementation for typing notifications was found"); - } - - opSetBasicIM2 = - (OperationSetBasicInstantMessaging)supportedOperationSets2.get( - OperationSetBasicInstantMessaging.class.getName()); - - if (opSetBasicIM2 == null) - { - throw new NullPointerException( - "No implementation for basic IM was found"); - } - - - //we also need the presence op set in order to retrieve contacts. - opSetPresence2 = - (OperationSetPresence)supportedOperationSets2.get( - OperationSetPresence.class.getName()); - - //if the op set is null show that we're not happy. - if (opSetPresence2 == null) - { - throw new NullPointerException( - "An implementation of the service must provide an " - + "implementation of at least one of the PresenceOperationSets"); - } - } - - /** - * Create the list to be sure that contacts exchanging messages - * exists in each other lists - * @throws Exception - */ - public void prepareContactList() throws Exception - { - // be sure that contacts are in their lists - try{ - opSetPresence1.subscribe(fixture.userID2); - } - catch (OperationFailedException ex){ - // the contact already exist its OK - } - - try{ - opSetPresence2.subscribe(fixture.userID1); - } - catch (OperationFailedException ex1){ - // the contact already exist its OK - } - - Object o = new Object(); - synchronized (o) - { - o.wait(2000); - } - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - - fixture.tearDown(); - } - - /** - * Creates a test suite containing tests of this class in a specific order. - * We'll first execute a test where we receive a typing notification, and - * a volatile contact is created for the sender. we'll then be able to - * retrieve this volatile contact and them a notification on our turn. - * We need to do things this way as the contact corresponding to the tester - * agent has been removed in the previous test and we no longer have it - * in our contact list. - * - * @return Test a testsuite containing all tests to execute. - */ - public static Test suite() - { - TestSuite suite = new TestSuite(); - - suite.addTest(new TestOperationSetTypingNotifications( - "prepareContactList")); - - //the following 2 need to be run in the specified order. - suite.addTest(new TestOperationSetTypingNotifications( - "testTypingNotificationsEventDelivery")); - return suite; - } - - /** - * Sends a typing notification and verifies - * whether it is properly received by the tested implementation - */ - public void testTypingNotificationsEventDelivery() - { - TypingEventCollector evtCollector = new TypingEventCollector(); - - // send message so request for receiving notifications also to be set - Contact notifingContact = - opSetPresence1.findContactByID(fixture.userID2); - opSetBasicIM1.sendInstantMessage(notifingContact, - opSetBasicIM1.createMessage("ping")); - - opSetTypingNotifs1.addTypingNotificationsListener(evtCollector); - - Contact contactToNotify = - opSetPresence2.findContactByID(fixture.userID1); - - opSetBasicIM2.sendInstantMessage(contactToNotify, - opSetBasicIM2.createMessage("pong")); - - Object w = new Object(); - synchronized(w){try {w.wait(500);}catch (Exception e) {}} - - opSetTypingNotifs2.sendTypingNotification( - contactToNotify, OperationSetTypingNotifications.STATE_TYPING); - - evtCollector.waitForEvent(10000); - - opSetTypingNotifs1.removeTypingNotificationsListener(evtCollector); - - //check event dispatching - assertTrue("Number of typing events received was zero." - , evtCollector.collectedEvents.size() > 0); - - TypingNotificationEvent evt = (TypingNotificationEvent)evtCollector - .collectedEvents.get(0); - - assertEquals("Source of the typing notification event" - , fixture.userID2 - , evt.getSourceContact().getAddress() ); - - assertEquals("Source of the typing notification event" - , OperationSetTypingNotifications.STATE_TYPING - , evt.getTypingState()); - } - - /** - * Simply collects allre received events and provides a mechanisim for - * waiting for the next event. - */ - private class TypingEventCollector implements TypingNotificationsListener - { - private List collectedEvents = new LinkedList(); - /** - * Called to indicate that a remote Contact has sent us a typing - * notification. The method adds the event to the list of - * captured events. - * @param event a TypingNotificationEvent containing the sender - * of the notification and its type. - */ - public void typingNotificationReceived(TypingNotificationEvent event) - { - logger.debug("Received a typing notification: " + event); - synchronized (this) - { - collectedEvents.add(event); - notifyAll(); - } - } - - /** - * Called to indicate that sending typing notification has failed. - * - * @param event a TypingNotificationEvent containing the sender - * of the notification and its type. - */ - public void typingNotificationDeliveryFailed(TypingNotificationEvent event) - {} - - /** - * Blocks until at least one event is received or until waitFor - * miliseconds pass (whicever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - synchronized(this){ - - if(collectedEvents.size() > 0) - return; - - try{ - wait(waitFor); - } - catch (InterruptedException ex){ - logger.debug( - "Interrupted while waiting for a subscription evt", ex); - } - } - } - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/TestProtocolProviderServiceYahooImpl.java b/test/net/java/sip/communicator/slick/protocol/yahoo/TestProtocolProviderServiceYahooImpl.java deleted file mode 100644 index 87c07f3..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/TestProtocolProviderServiceYahooImpl.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; -import net.java.sip.communicator.slick.protocol.generic.*; -import net.java.sip.communicator.util.*; - -/** - * Performs testing on protocol provider methods. - * @todo add more detailed docs once the tests are written. - * @author Damian Minkov - */ -public class TestProtocolProviderServiceYahooImpl - extends TestCase -{ - private static final Logger logger = - Logger.getLogger(TestProtocolProviderServiceYahooImpl.class); - - private YahooSlickFixture fixture = new YahooSlickFixture(); - - /** - * An event adapter that would collec registation state change events - */ - public RegistrationEventCollector regEvtCollector1 - = new RegistrationEventCollector(); - - /** - * An event adapter that would collec registation state change events - */ - public RegistrationEventCollector regEvtCollector2 - = new RegistrationEventCollector(); - - /** - * An event adapter that would collec registation state change events - */ - public RegistrationEventCollector regEvtCollector3 - = new RegistrationEventCollector(); - - /** - * Creates a test encapsulator for the method with the specified name. - * @param name the name of the method this test should run. - */ - public TestProtocolProviderServiceYahooImpl(String name) - { - super(name); - } - - /** - * Initializes the fixture. - * @throws Exception if super.setUp() throws one. - */ - @Override - protected void setUp() throws Exception - { - super.setUp(); - fixture.setUp(); - } - - /** - * Tears the fixture down. - * @throws Exception if fixture.tearDown() fails. - */ - @Override - protected void tearDown() throws Exception - { - fixture.tearDown(); - super.tearDown(); - } - - /** - * Makes sure that the instance of the Yahoo protocol provider that we're - * going to use for testing is properly initialized and registered with - * a Yahoo registrar. This MUST be called before any other online testing - * of the Yahoo provider so that we won't have to reregister for every single - * test. - *

    - * The method also verifies that a registration event is fired upon - * succesful registration and collected by our event collector. - * - * @throws OperationFailedException if provider.register() fails. - */ - public void testRegister() - throws OperationFailedException - { - //add an event collector that will collect all events during the - //registration and allow us to later inspect them and make sure - //they were properly dispatched. - fixture.provider1.addRegistrationStateChangeListener(regEvtCollector1); - fixture.provider2.addRegistrationStateChangeListener(regEvtCollector2); - - //register our three providers - fixture.provider1.register(new SecurityAuthorityImpl( - System.getProperty(YahooProtocolProviderServiceLick.ACCOUNT_1_PREFIX - + ProtocolProviderFactory.PASSWORD).toCharArray())); - fixture.provider2.register(new SecurityAuthorityImpl( - System.getProperty(YahooProtocolProviderServiceLick.ACCOUNT_2_PREFIX - + ProtocolProviderFactory.PASSWORD).toCharArray())); - - //give it enough time to register. We won't really have to wait all this - //time since the registration event collector would notify us the moment - //we get signed on. - logger.debug("Waiting for registration to complete ..."); - - regEvtCollector1.waitForEvent(15000); - regEvtCollector2.waitForEvent(40000); - - //make sure that the registration process trigerred the corresponding - //events. - assertTrue( - "No events were dispatched during the registration process." - ,regEvtCollector1.collectedNewStates.size() > 0); - - assertTrue( - "No registration event notifying of registration was dispatched. " - +"All events were: " + regEvtCollector1.collectedNewStates - ,regEvtCollector1.collectedNewStates - .contains(RegistrationState.REGISTERED)); - - //now the same for provider 2 - assertTrue( - "No events were dispatched during the registration process " - +"of provider2." - ,regEvtCollector2.collectedNewStates.size() > 0); - - assertTrue( - "No registration event notifying of registration was dispatched. " - +"All events were: " + regEvtCollector2.collectedNewStates - ,regEvtCollector2.collectedNewStates - .contains(RegistrationState.REGISTERED)); - - fixture.provider1 - .removeRegistrationStateChangeListener(regEvtCollector1); - fixture.provider2 - .removeRegistrationStateChangeListener(regEvtCollector2); - } - - - /** - * Verifies that all operation sets have the type they are declarded to - * have. - * - * @throws java.lang.Exception if a class indicated in one of the keys - * could not be forName()ed. - */ - public void testOperationSetTypes() throws Exception - { - Map supportedOperationSets = - fixture.provider1.getSupportedOperationSets(); - - // make sure that keys (which are supposed to be class names) correspond - // what the class of the values recorded against them. - for (Map.Entry entry : supportedOperationSets - .entrySet()) - { - String setName = entry.getKey(); - Object opSet = entry.getValue(); - - assertTrue(opSet + " was not an instance of " + setName - + " as declared", Class.forName(setName).isInstance(opSet)); - } - } - - /** - * A class that would plugin as a registration listener to a protocol - * provider and simply record all events that it sees and notifyAll() - * if it sees an event that notifies us of a completed - * registration. - */ - public class RegistrationEventCollector - implements RegistrationStateChangeListener - { - public List collectedNewStates = new LinkedList(); - - /** - * The method would simply register all received events so that they - * could be available for later inspection by the unit tests. In the - * case where a registraiton event notifying us of a completed - * registration is seen, the method would call notifyAll(). - * - * @param evt ProviderStatusChangeEvent the event describing the status - * change. - */ - public void registrationStateChanged(RegistrationStateChangeEvent evt) - { - logger.debug("Received a RegistrationStateChangeEvent: " + evt); - - collectedNewStates.add(evt.getNewState()); - - if (evt.getNewState().equals(RegistrationState.REGISTERED)) - { - logger.debug("We're registered and will notify those who wait"); - synchronized (this) - { - notifyAll(); - } - } - } - - /** - * Blocks until an event notifying us of the awaited state change is - * received or until waitFor miliseconds pass (whichever happens first). - * - * @param waitFor the number of miliseconds that we should be waiting - * for an event before simply bailing out. - */ - public void waitForEvent(long waitFor) - { - logger.trace("Waiting for a RegistrationStateChangeEvent "); - - synchronized (this) - { - if (collectedNewStates.contains(RegistrationState.REGISTERED)) - { - logger.trace("Event already received. " - + collectedNewStates); - return; - } - - try - { - wait(waitFor); - - if (collectedNewStates.size() > 0) - logger.trace( - "Received a RegistrationStateChangeEvent."); - else - logger.trace( - "No RegistrationStateChangeEvent received for " - + waitFor + "ms."); - - } - catch (InterruptedException ex) - { - logger.debug( - "Interrupted while waiting for a " - +"RegistrationStateChangeEvent" - , ex); - } - } - } - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/YahooProtocolProviderServiceLick.java b/test/net/java/sip/communicator/slick/protocol/yahoo/YahooProtocolProviderServiceLick.java deleted file mode 100644 index a9dc75d..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/YahooProtocolProviderServiceLick.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import java.util.*; - -import junit.framework.*; - -import org.osgi.framework.*; - -/** - * Yahoo specific testing for a Yahoo Protocol Provider Service implementation. - * The test suite registers three accounts for - * - * @author Damian Minkov - * @author Valentin Martinet - */ -public class YahooProtocolProviderServiceLick - extends TestSuite - implements BundleActivator -{ - /** - * The prefix used for property names containing settings for our first - * testing account. - */ - public static final String ACCOUNT_1_PREFIX - = "accounts.yahoo.account1."; - - /** - * The prefix used for property names containing settings for our second - * testing account. - */ - public static final String ACCOUNT_2_PREFIX - = "accounts.yahoo.account2."; - - /** - * The prefix used for property names containing settings for our third - * testing account. - */ - public static final String ACCOUNT_3_PREFIX - = "accounts.yahoo.account3."; - - /** - * The name of the property that indicates whether the user would like to - * only run the offline tests. - */ - public static final String DISABLE_ONLINE_TESTS_PROPERTY_NAME - = "accounts.yahoo.DISABLE_ONLINE_TESTING"; - - /** - * The name of the property the value of which is a formatted string that - * contains the contact list that. - */ - public static final String CONTACT_LIST_PROPERTY_NAME - = "accounts.yahoo.CONTACT_LIST"; - - /** - * Initializes and registers all tests that we'll run as a part of this - * slick. - * - * @param context a currently valid bundle context. - */ - public void start(BundleContext context) - { - setName("YahooProtocolProviderSlick"); - - Hashtable properties = new Hashtable(); - properties.put("service.pid", getName()); - - YahooSlickFixture.bc = context; - - // verify whether the user wants to avoid online testing - String offlineMode = System.getProperty( - DISABLE_ONLINE_TESTS_PROPERTY_NAME, null); - - if (offlineMode != null && offlineMode.equalsIgnoreCase("true")) - YahooSlickFixture.onlineTestingDisabled = true; - - - addTestSuite(TestAccountInstallation.class); - addTestSuite(TestProtocolProviderServiceYahooImpl.class); - - addTest(TestOperationSetPresence.suite()); - - //the following should only be run when we want online testing. - if(!YahooSlickFixture.onlineTestingDisabled) - { - addTest(TestOperationSetPersistentPresence.suite()); - - addTest(TestOperationSetBasicInstantMessaging.suite()); - - addTest(TestOperationSetTypingNotifications.suite()); - - addTestSuite(TestOperationSetFileTransferImpl.class); - - //addTest(TestOperationSetAdHocMultiUserChatYahooImpl.suite()); - } - - addTest(TestAccountUninstallation.suite()); - addTestSuite(TestAccountUninstallationPersistence.class); - - context.registerService(getClass().getName(), this, properties); - } - - /** - * Prepares the slick for shutdown. - * - * @param context a currently valid bundle context. - */ - public void stop(BundleContext context) - { - - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/YahooSlickFixture.java b/test/net/java/sip/communicator/slick/protocol/yahoo/YahooSlickFixture.java deleted file mode 100644 index 88d36f5..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/YahooSlickFixture.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.slick.protocol.yahoo; - -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.slick.protocol.generic.*; - -import org.osgi.framework.*; - -/** - * Contains fields and methods used by most or all tests in the yahoo slick. - * - * @author Damian Minkov - * @author Valentin Martinet - */ -public class YahooSlickFixture - extends AdHocMultiUserChatSlickFixture -{ - /** - * Constructor - */ - public YahooSlickFixture() - { - super(); - } - - /** - * Initializes protocol provider references and whatever else there is to - * initialize. - * - * @throws InvalidSyntaxException in case we meet problems while retrieving - * protocol providers through OSGI - */ - @Override - public void setUp() throws InvalidSyntaxException - { - // first obtain a reference to the provider factory - ServiceReference[] serRefs = null; - String osgiFilter = "(" + ProtocolProviderFactory.PROTOCOL - + "="+ProtocolNames.YAHOO+")"; - try{ - serRefs = bc.getServiceReferences( - ProtocolProviderFactory.class.getName(), osgiFilter); - } - catch (InvalidSyntaxException ex){ - //this really shouldhn't occur as the filter expression is static. - fail(osgiFilter + " is not a valid osgi filter"); - } - - assertTrue( - "Failed to find a provider factory service for protocol yahoo", - (serRefs != null) && (serRefs.length > 0)); - - //Keep the reference for later usage. - providerFactory = (ProtocolProviderFactory)bc.getService(serRefs[0]); - - userID1 = - System.getProperty( - YahooProtocolProviderServiceLick.ACCOUNT_1_PREFIX - + ProtocolProviderFactory.USER_ID); - - userID2 = - System.getProperty( - YahooProtocolProviderServiceLick.ACCOUNT_2_PREFIX - + ProtocolProviderFactory.USER_ID); - - userID3 = - System.getProperty( - YahooProtocolProviderServiceLick.ACCOUNT_3_PREFIX - + ProtocolProviderFactory.USER_ID); - - //find the protocol providers exported for the three accounts - ServiceReference[] yahooProvider1Refs - = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(&" - +"("+ProtocolProviderFactory.PROTOCOL+"="+ProtocolNames.YAHOO+")" - +"("+ProtocolProviderFactory.USER_ID+"=" - + userID1 +")" - +")"); - - //make sure we found a service - assertNotNull("No Protocol Provider was found for yahoo account1:" - + userID1 - , yahooProvider1Refs); - assertTrue("No Protocol Provider was found for yahoo account1:"+userID1, - yahooProvider1Refs.length > 0); - - ServiceReference[] yahooProvider2Refs - = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(&" - +"("+ProtocolProviderFactory.PROTOCOL+"="+ProtocolNames.YAHOO+")" - +"("+ProtocolProviderFactory.USER_ID+"=" - + userID2 +")" - +")"); - - //again make sure we found a service. - assertNotNull("No Protocol Provider was found for yahoo account2:" - + userID2 - , yahooProvider2Refs); - assertTrue("No Protocol Provider was found for yahoo account2:"+userID2, - yahooProvider2Refs.length > 0); - - ServiceReference[] yahooProvider3Refs - = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - "(&" - +"("+ProtocolProviderFactory.PROTOCOL+"="+ProtocolNames.YAHOO+")" - +"("+ProtocolProviderFactory.USER_ID+"=" - + userID3 +")" - +")"); - - //again make sure we found a service. - assertNotNull("No Protocol Provider was found for yahoo account3:" - + userID3 - , yahooProvider3Refs); - assertTrue("No Protocol Provider was found for yahoo account2:"+userID3, - yahooProvider3Refs.length > 0); - - //save the service for other tests to use. - provider1ServiceRef = yahooProvider1Refs[0]; - provider1 = (ProtocolProviderService)bc.getService(provider1ServiceRef); - provider2ServiceRef = yahooProvider2Refs[0]; - provider2 = (ProtocolProviderService)bc.getService(provider2ServiceRef); - provider3ServiceRef = yahooProvider3Refs[0]; - provider3 = (ProtocolProviderService)bc.getService(provider3ServiceRef); - } -} diff --git a/test/net/java/sip/communicator/slick/protocol/yahoo/yahoo.provider.slick.manifest.mf b/test/net/java/sip/communicator/slick/protocol/yahoo/yahoo.provider.slick.manifest.mf deleted file mode 100644 index e57e344..0000000 --- a/test/net/java/sip/communicator/slick/protocol/yahoo/yahoo.provider.slick.manifest.mf +++ /dev/null @@ -1,17 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.slick.protocol.yahoo.YahooProtocolProviderServiceLick -Bundle-Name: Yahoo Protocol Provider Service Leveraging Implementation Compatibility Kit -Bundle-Description: A Service Leveraging Implementation Compatibility Kit for the Yahoo implementation of the ProtocolProvider Service -Bundle-Vendor: sip-communicator.org -Bundle-Version: 0.0.1 -System-Bundle: yes -Import-Package: org.jitsi.service.configuration, - junit.framework, - org.osgi.framework, - javax.net.ssl, - javax.xml.parsers, - net.java.sip.communicator.util, - net.java.sip.communicator.service.dns, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.yahooconstants, - net.java.sip.communicator.service.protocol.event, - org.jitsi.service.fileaccess -- cgit v1.1 From 9edf7d68ccf968083c38859b89a097b7fc73f0c0 Mon Sep 17 00:00:00 2001 From: Lucas Murray Date: Sat, 12 Nov 2016 04:06:53 +1100 Subject: Remove missed Yahoo protocol references (#301) --- .classpath | 1 - nbproject/project.xml | 2 +- resources/install/build.xml | 9 --------- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/.classpath b/.classpath index 3b5a7cf..7fbeb53 100755 --- a/.classpath +++ b/.classpath @@ -66,7 +66,6 @@ - diff --git a/nbproject/project.xml b/nbproject/project.xml index ba9c55e..9300193 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/ymsg_network_v0_67.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 diff --git a/resources/install/build.xml b/resources/install/build.xml index 6dc3441..fe1ff31 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -3026,15 +3026,6 @@ overwrite="true" link="${debian.src.dir}/lib/installer-exclude/json-simple-1.1.1.jar"/> - - - - - Date: Thu, 8 Dec 2016 18:04:59 -0600 Subject: Adds an option to specify custom header names for meet room name. --- .../impl/protocol/sip/CallSipImpl.java | 27 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java index bae70a2..62711c7 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java @@ -61,15 +61,27 @@ public class CallSipImpl * Name of extra INVITE header which specifies name of MUC room that is * hosting the Jitsi Meet conference. */ - public static final String JITSI_MEET_ROOM_HEADER - = "Jitsi-Conference-Room"; + public String JITSI_MEET_ROOM_HEADER = "Jitsi-Conference-Room"; + + /** + * Property name of extra INVITE header which specifies name of MUC room + * that is hosting the Jitsi Meet conference. + */ + private static final String JITSI_MEET_ROOM_HEADER_PROPERTY + = "JITSI_MEET_ROOM_HEADER_NAME"; + + /** + * Property name of extra INVITE header which specifies password required + * to enter MUC room that is hosting the Jitsi Meet conference. + */ + public String JITSI_MEET_ROOM_PASS_HEADER = "Jitsi-Conference-Room-Pass"; /** * Name of extra INVITE header which specifies password required to enter * MUC room that is hosting the Jitsi Meet conference. */ - public static final String JITSI_MEET_ROOM_PASS_HEADER - = "Jitsi-Conference-Room-Pass"; + private static final String JITSI_MEET_ROOM_PASS_HEADER_PROPERTY + = "JITSI_MEET_ROOM_PASS_HEADER_NAME"; /** * Custom header included in initial desktop sharing call creation. @@ -159,6 +171,13 @@ public class CallSipImpl } this.retransmitsRingingInterval = retransmitsRingingInterval; + AccountID account = parentOpSet.getProtocolProvider().getAccountID(); + // Specify custom header names + JITSI_MEET_ROOM_HEADER = account.getAccountPropertyString( + JITSI_MEET_ROOM_HEADER_PROPERTY, JITSI_MEET_ROOM_HEADER); + JITSI_MEET_ROOM_PASS_HEADER = account.getAccountPropertyString( + JITSI_MEET_ROOM_PASS_HEADER_PROPERTY, JITSI_MEET_ROOM_PASS_HEADER); + //let's add ourselves to the calls repo. we are doing it ourselves just //to make sure that no one ever forgets. parentOpSet.getActiveCallsRepository().addCall(this); -- cgit v1.1 From 9ffda8db84eac97151430f95ae0d6ce46fb6a157 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 27 Dec 2016 22:34:08 +0100 Subject: Ignore invalid ICE candidates --- .../communicator/impl/protocol/jabber/IceUdpTransportManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java index d326b96..7305f5c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java @@ -1000,6 +1000,12 @@ public class IceUdpTransportManager if (candidate.getGeneration() != generation) continue; + if (candidate.getIP() == null || "".equals(candidate.getIP())) + { + logger.warn("Skipped ICE candidate with empty IP"); + continue; + } + Component component = stream.getComponent(candidate.getComponent()); String relAddr; -- cgit v1.1 From c7bc11749b35e5d0b7ecf1488080f53d5b8d3ea2 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 27 Dec 2016 22:34:59 +0100 Subject: Ignore invalid (empty) Jingle Nodes relay IPs --- .../communicator/impl/protocol/jabber/JingleNodesHarvester.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java index bb7d31b..5c12aa7 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java @@ -125,7 +125,7 @@ public class JingleNodesHarvester } } - if (ciq != null && ciq.getRemoteport() > 0) + if (ciq != null) { ip = ciq.getHost(); port = ciq.getRemoteport(); @@ -136,6 +136,12 @@ public class JingleNodesHarvester " local port: " + ciq.getLocalport()); } + if (ip == null || ciq.getRemoteport() == 0) + { + logger.warn("JN relay ignored because ip was null or port 0"); + return candidates; + } + /* RTP */ TransportAddress relayedAddress = new TransportAddress(ip, port, Transport.UDP); @@ -160,6 +166,7 @@ public class JingleNodesHarvester candidates.add(local); } } + return candidates; } -- cgit v1.1 From 1c6d035dc8c58403156826bbe12f442605baa5b0 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 27 Dec 2016 22:35:30 +0100 Subject: Strip scope/interface identifier from IPv6 Jingle Nodes relay addresses --- .../impl/protocol/jabber/JingleNodesHarvester.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java index 5c12aa7..32ee849 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java @@ -142,6 +142,16 @@ public class JingleNodesHarvester return candidates; } + // Drop the scope or interface name if the relay sends it + // along in its IPv6 address. The scope/ifname is only valid on the + // host that owns the IP and we don't need it here. + int scopeIndex = ip.indexOf('%'); + if (scopeIndex > 0) + { + logger.warn("Dropping scope from assumed IPv6 address " + ip); + ip = ip.substring(0, scopeIndex); + } + /* RTP */ TransportAddress relayedAddress = new TransportAddress(ip, port, Transport.UDP); -- cgit v1.1 From f3ea05926989789c200e26799ca1954a0321a9db Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 27 Dec 2016 22:55:50 +0100 Subject: Update libjitsi Add support for RFC4566/RFC6466 media types Jenkins build 898 jitsi/libjitsi@2d067d45d916fe1d792bfb204159fbf25011db4f --- .classpath | 2 +- build.xml | 6 +++--- .../libjitsi-1.0-20160707.163121-175.jar | Bin 8075571 -> 0 bytes .../libjitsi-1.0-20161226.161151-208.jar | Bin 0 -> 8791384 bytes nbproject/project.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar diff --git a/.classpath b/.classpath index 7fbeb53..415a47e 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index 47745ef..44f0ad0 100644 --- a/build.xml +++ b/build.xml @@ -444,7 +444,7 @@ - + @@ -465,7 +465,7 @@ - + @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar b/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar deleted file mode 100644 index bd92f39..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20160707.163121-175.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar b/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar new file mode 100644 index 0000000..280000b Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar differ diff --git a/nbproject/project.xml b/nbproject/project.xml index 9300193..d69b2de 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 3805f9507a3931f34067fcb64ae28e6f69d44fcc Mon Sep 17 00:00:00 2001 From: paweldomas Date: Fri, 16 Dec 2016 08:58:37 -0600 Subject: Use base Connection class instead of XMPPConnection Tries to use base Connection class instead of XMPPConnection where possible. --- .../protocol/jabber/AnonymousLoginStrategy.java | 2 +- .../impl/protocol/jabber/CallJabberImpl.java | 2 +- .../impl/protocol/jabber/ChatRoomJabberImpl.java | 2 +- .../impl/protocol/jabber/InfoRetreiver.java | 2 +- .../impl/protocol/jabber/JabberLoginStrategy.java | 2 +- .../jabber/LoginByClientCertificateStrategy.java | 2 +- .../protocol/jabber/LoginByPasswordStrategy.java | 2 +- ...perationSetBasicInstantMessagingJabberImpl.java | 2 +- .../OperationSetBasicTelephonyJabberImpl.java | 2 +- .../OperationSetMultiUserChatJabberImpl.java | 4 +- .../OperationSetPersistentPresenceJabberImpl.java | 4 +- ...perationSetTelephonyConferencingJabberImpl.java | 2 +- .../jabber/OperationSetVideoBridgeImpl.java | 2 +- .../jabber/OutgoingFileTransferJabberImpl.java | 2 +- .../jabber/ProtocolProviderServiceJabberImpl.java | 79 +++++++++++++--------- .../protocol/jabber/ScServiceDiscoveryManager.java | 6 +- .../jabber/extensions/caps/EntityCapsManager.java | 2 +- .../JabberAccountCreationForm.java | 2 +- 18 files changed, 68 insertions(+), 53 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/AnonymousLoginStrategy.java b/src/net/java/sip/communicator/impl/protocol/jabber/AnonymousLoginStrategy.java index c955100..b62d01a 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/AnonymousLoginStrategy.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/AnonymousLoginStrategy.java @@ -70,7 +70,7 @@ public class AnonymousLoginStrategy } @Override - public boolean login(XMPPConnection connection, String userName, + public boolean login(Connection connection, String userName, String resource) throws XMPPException { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java index e23481a..3987ea8 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java @@ -311,7 +311,7 @@ public class CallJabberImpl contentRequest.addChannel(remoteChannelRequest); } - XMPPConnection connection = protocolProvider.getConnection(); + Connection connection = protocolProvider.getConnection(); PacketCollector packetCollector = connection.createPacketCollector( new PacketIDFilter(conferenceRequest.getPacketID())); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java index e3d4f12..1897b42 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java @@ -868,7 +868,7 @@ public class ChatRoomJabberImpl clearCachedConferenceDescriptionList(); - XMPPConnection connection = this.provider.getConnection(); + Connection connection = this.provider.getConnection(); try { // if we are already disconnected diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java index a0387df..c3137ad 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java @@ -151,7 +151,7 @@ public class InfoRetreiver List result = new LinkedList(); try { - XMPPConnection connection = jabberProvider.getConnection(); + Connection connection = jabberProvider.getConnection(); if(connection == null || !connection.isAuthenticated()) return null; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JabberLoginStrategy.java b/src/net/java/sip/communicator/impl/protocol/jabber/JabberLoginStrategy.java index 438ea1b..de7578c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JabberLoginStrategy.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JabberLoginStrategy.java @@ -61,7 +61,7 @@ public interface JabberLoginStrategy * @param resource the XMPP resource * @return true to continue connecting, false to abort */ - public boolean login(XMPPConnection connection, String userName, + public boolean login(Connection connection, String userName, String resource) throws XMPPException; diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/LoginByClientCertificateStrategy.java b/src/net/java/sip/communicator/impl/protocol/jabber/LoginByClientCertificateStrategy.java index 09c9462..4825e01 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/LoginByClientCertificateStrategy.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/LoginByClientCertificateStrategy.java @@ -116,7 +116,7 @@ class LoginByClientCertificateStrategy * accepted. * @throws XMPPException */ - public boolean login(XMPPConnection connection, String userName, + public boolean login(Connection connection, String userName, String resource) throws XMPPException { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/LoginByPasswordStrategy.java b/src/net/java/sip/communicator/impl/protocol/jabber/LoginByPasswordStrategy.java index 43fc8a4..7034221 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/LoginByPasswordStrategy.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/LoginByPasswordStrategy.java @@ -115,7 +115,7 @@ public class LoginByPasswordStrategy * @return always true. * @throws XMPPException */ - public boolean login(XMPPConnection connection, String userName, + public boolean login(Connection connection, String userName, String resource) throws XMPPException { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java index 42a3916..f055613 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java @@ -1109,7 +1109,7 @@ public class OperationSetBasicInstantMessagingJabberImpl NewMailNotificationIQ.NAMESPACE, new NewMailNotificationProvider()); - XMPPConnection connection = jabberProvider.getConnection(); + Connection connection = jabberProvider.getConnection(); connection.addPacketListener( new MailboxIQListener(), new PacketTypeFilter(MailboxIQ.class)); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java index cc36936..6853ae7 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java @@ -774,7 +774,7 @@ public class OperationSetBasicTelephonyJabberImpl */ private void unsubscribeForJinglePackets() { - XMPPConnection connection = protocolProvider.getConnection(); + Connection connection = protocolProvider.getConnection(); if(connection != null) connection.removePacketListener(this); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java index 80bbb4e..cf53906 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java @@ -471,10 +471,10 @@ public class OperationSetMultiUserChatJabberImpl * Almost all MultiUserChat methods require an xmpp connection * param so I added this method only for the sake of utility. * - * @return the XMPPConnection currently in use by the jabber provider or + * @return the XMPP connection currently in use by the jabber provider or * null if jabber provider has yet to be initialized. */ - private XMPPConnection getXmppConnection() + private Connection getXmppConnection() { return (jabberProvider == null) ? null diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java index 2d40ac1..c502824 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java @@ -691,7 +691,7 @@ public class OperationSetPersistentPresenceJabberImpl */ assertConnected(); - XMPPConnection xmppConnection = parentProvider.getConnection(); + Connection xmppConnection = parentProvider.getConnection(); if (xmppConnection == null) { @@ -1124,7 +1124,7 @@ public class OperationSetPersistentPresenceJabberImpl ssContactList.cleanup(); - XMPPConnection connection = parentProvider.getConnection(); + Connection connection = parentProvider.getConnection(); if(connection != null) { connection.removePacketListener(subscribtionPacketListener); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java index 56cf63c..e5b83e7 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java @@ -379,7 +379,7 @@ public class OperationSetTelephonyConferencingJabberImpl */ private void unsubscribeForCoinPackets() { - XMPPConnection connection = parentProvider.getConnection(); + Connection connection = parentProvider.getConnection(); if (connection != null) connection.removePacketListener(this); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java index e388865..5d3dd8b 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetVideoBridgeImpl.java @@ -287,7 +287,7 @@ public class OperationSetVideoBridgeImpl } else if (RegistrationState.UNREGISTERED.equals(registrationState)) { - XMPPConnection connection = protocolProvider.getConnection(); + Connection connection = protocolProvider.getConnection(); if (connection != null) connection.removePacketListener(this); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OutgoingFileTransferJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OutgoingFileTransferJabberImpl.java index f38d0bc..b219d68 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OutgoingFileTransferJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OutgoingFileTransferJabberImpl.java @@ -248,7 +248,7 @@ public class OutgoingFileTransferJabberImpl ThumbnailIQ thumbnailIQ = (ThumbnailIQ) packet; String thumbnailIQCid = thumbnailIQ.getCid(); - XMPPConnection connection = protocolProvider.getConnection(); + Connection connection = protocolProvider.getConnection(); if ((thumbnailIQCid != null) && thumbnailIQCid.equals(thumbnailElement.getCid())) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 1d08250..60f9629 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -220,7 +220,7 @@ public class ProtocolProviderServiceJabberImpl /** * Used to connect to a XMPP server. */ - private XMPPConnection connection; + private Connection connection; /** * The socket address of the XMPP server. @@ -607,7 +607,7 @@ public class ProtocolProviderServiceJabberImpl */ public boolean isSignalingTransportSecure() { - return connection != null && connection.isUsingTLS(); + return connection.isSecureConnection(); } /** @@ -622,7 +622,7 @@ public class ProtocolProviderServiceJabberImpl if(connection != null && connection.isConnected()) { // Transport using a secure connection. - if(connection.isUsingTLS()) + if(isSignalingTransportSecure()) { return TransportProtocol.TLS; } @@ -1203,13 +1203,16 @@ public class ProtocolProviderServiceJabberImpl throw new XMPPException("Error creating custom trust manager", e); } - if(debugger == null) + // FIXME rework debugger to work with Connection if possible + if(debugger == null && connection instanceof XMPPConnection) + { debugger = new SmackPacketDebugger(); - // sets the debugger - debugger.setConnection(connection); - connection.addPacketListener(debugger, null); - connection.addPacketInterceptor(debugger, null); + // sets the debugger + debugger.setConnection((XMPPConnection) connection); + connection.addPacketListener(debugger, null); + connection.addPacketInterceptor(debugger, null); + } connection.connect(); @@ -1256,9 +1259,10 @@ public class ProtocolProviderServiceJabberImpl } else { - if (connection.getSocket() instanceof SSLSocket) + final SSLSocket sslSocket = getSSLSocket(); + + if (sslSocket != null) { - final SSLSocket sslSocket = (SSLSocket) connection.getSocket(); StringBuilder buff = new StringBuilder(); buff.append("Chosen TLS protocol and algorithm:\n") .append("Protocol: ").append(sslSocket.getSession() @@ -2127,11 +2131,11 @@ public class ProtocolProviderServiceJabberImpl } /** - * Returns the XMPPConnectionopened by this provider - * @return a reference to the XMPPConnection last opened by this + * Returns the Connectionopened by this provider + * @return a reference to the Connection last opened by this * provider. */ - public XMPPConnection getConnection() + public Connection getConnection() { return connection; } @@ -2488,7 +2492,7 @@ public class ProtocolProviderServiceJabberImpl */ public String getFullJid(String bareJid) { - XMPPConnection connection = getConnection(); + Connection connection = getConnection(); // when we are not connected there is no full jid if (connection != null && connection.isConnected()) @@ -2692,12 +2696,21 @@ public class ProtocolProviderServiceJabberImpl */ public void startJingleNodesDiscovery() { + if (!(connection instanceof XMPPConnection)) + { + logger.warn( + "Jingle node discovery currently will work only with " + + "TCP XMPP connection"); + return; + } + // Jingle Nodes Service Initialization + final XMPPConnection xmppConnection = (XMPPConnection) connection; final JabberAccountIDImpl accID = (JabberAccountIDImpl)getAccountID(); - final SmackServiceNode service = new SmackServiceNode(connection, - 60000); + final SmackServiceNode service + = new SmackServiceNode(xmppConnection, 60000); // make sure SmackServiceNode will clean up when connection is closed - connection.addConnectionListener(service); + xmppConnection.addConnectionListener(service); for(JingleNodeDescriptor desc : accID.getJingleNodes()) { @@ -2713,7 +2726,7 @@ public class ProtocolProviderServiceJabberImpl new Thread(new JingleNodesServiceDiscovery( service, - connection, + xmppConnection, accID, jingleNodesSyncRoot)) .start(); @@ -2841,7 +2854,7 @@ public class ProtocolProviderServiceJabberImpl */ private void setTrafficClass() { - Socket s = connection.getSocket(); + Socket s = getSocket(); if(s != null) { @@ -2876,7 +2889,7 @@ public class ProtocolProviderServiceJabberImpl */ public String getJitsiVideobridge() { - XMPPConnection connection = getConnection(); + Connection connection = getConnection(); if (connection != null) { @@ -2967,21 +2980,23 @@ public class ProtocolProviderServiceJabberImpl } /** + * Obtains XMPP connection's socket. + * @return Socket instance used by the underlying XMPP connection + * or null if "non socket" type of transport is currently used. + */ + private Socket getSocket() + { + return connection != null ? connection.getSocket() : null; + } + + /** * Return the SSL socket (if TLS used). * @return The SSL socket or null if not used */ - public SSLSocket getSSLSocket() + SSLSocket getSSLSocket() { - final SSLSocket result; - final Socket socket = connection.getSocket(); - if (socket instanceof SSLSocket) - { - result = (SSLSocket) socket; - } - else - { - result = null; - } - return result; + final Socket socket = getSocket(); + + return (socket instanceof SSLSocket) ? (SSLSocket) socket : null; } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java index 4b3edab..de2ce3e 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ScServiceDiscoveryManager.java @@ -80,9 +80,9 @@ public class ScServiceDiscoveryManager private final ProtocolProviderService parentProvider; /** - * The {@link XMPPConnection} that this manager is responsible for. + * The {@link Connection} that this manager is responsible for. */ - private final XMPPConnection connection; + private final Connection connection; /** * A local copy that we keep in sync with {@link ServiceDiscoveryManager}'s @@ -130,7 +130,7 @@ public class ScServiceDiscoveryManager */ public ScServiceDiscoveryManager( ProtocolProviderService parentProvider, - XMPPConnection connection, + Connection connection, String[] featuresToRemove, String[] featuresToAdd, boolean cacheNonCaps) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java index c411726..97d9ff8 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java @@ -633,7 +633,7 @@ public class EntityCapsManager * @param connection the connection that we'd like this manager to register * with. */ - public void addPacketListener(XMPPConnection connection) + public void addPacketListener(Connection connection) { PacketFilter filter = new PacketTypeFilter(Presence.class); diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountCreationForm.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountCreationForm.java index 6288821..3e816cf 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountCreationForm.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/JabberAccountCreationForm.java @@ -93,7 +93,7 @@ public class JabberAccountCreationForm private JButton chooseButton = new JButton(); // Smack objects - private XMPPConnection xmppConnection = null; + private Connection xmppConnection = null; private AccountManager accountManager = null; -- cgit v1.1 From d52a2f32834186b3774800dac0674d56c5cbafb8 Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 28 Dec 2016 10:37:29 -0600 Subject: Adds BOSH_URL property to JabberAccountID --- .../service/protocol/jabber/JabberAccountID.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/net/java/sip/communicator/service/protocol/jabber/JabberAccountID.java b/src/net/java/sip/communicator/service/protocol/jabber/JabberAccountID.java index 81473c2..dce28d6 100644 --- a/src/net/java/sip/communicator/service/protocol/jabber/JabberAccountID.java +++ b/src/net/java/sip/communicator/service/protocol/jabber/JabberAccountID.java @@ -44,6 +44,12 @@ public class JabberAccountID public static final String ANONYMOUS_AUTH = "ANONYMOUS_AUTH"; /** + * Configures the URL which is to be used with BOSH transport. If the value + * is null or empty then the TCP transport will be used instead. + */ + public static final String BOSH_URL = "BOSH_URL"; + + /** * Account suffix for Google service. */ public static final String GOOGLE_USER_SUFFIX = "gmail.com"; @@ -119,6 +125,29 @@ public class JabberAccountID } /** + * Returns the BOSH URL which should be used to connect to the XMPP server. + * If the value is set then BOSH transport instead of TCP will be used. + * + * @return a String with the URL which should be used for BOSH + * transport or null if disabled. + */ + public String getBoshUrl() + { + return getAccountPropertyString(BOSH_URL); + } + + /** + * Sets new URL which should be used for the BOSH transport. + * + * @param boshPath a String with the new BOSH URL or null + * to disable BOSH. + */ + public void setBoshUrl(String boshPath) + { + putAccountProperty(BOSH_URL, boshPath); + } + + /** * Returns the override phone suffix. * * @return the phone suffix -- cgit v1.1 From ea1a5f2b61a187ff81ad076b495ee98e1bf0bf2f Mon Sep 17 00:00:00 2001 From: paweldomas Date: Wed, 28 Dec 2016 11:28:04 -0600 Subject: Create BOSH XMPP connection when BOSH_URL is set --- lib/installer-exclude/smack.jar | Bin 326629 -> 412905 bytes lib/installer-exclude/smackx-debug.jar | Bin 56389 -> 56538 bytes lib/installer-exclude/smackx.jar | Bin 669340 -> 662514 bytes m2/pom.xml | 2 +- .../jabber/ProtocolProviderFactoryJabberImpl.java | 2 +- .../jabber/ProtocolProviderServiceJabberImpl.java | 34 ++++++++++++++++----- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/installer-exclude/smack.jar b/lib/installer-exclude/smack.jar index b0cc856..4bda197 100644 Binary files a/lib/installer-exclude/smack.jar and b/lib/installer-exclude/smack.jar differ diff --git a/lib/installer-exclude/smackx-debug.jar b/lib/installer-exclude/smackx-debug.jar index 3311681..45bcaaf 100644 Binary files a/lib/installer-exclude/smackx-debug.jar and b/lib/installer-exclude/smackx-debug.jar differ diff --git a/lib/installer-exclude/smackx.jar b/lib/installer-exclude/smackx.jar index ba590ca..6362497 100644 Binary files a/lib/installer-exclude/smackx.jar and b/lib/installer-exclude/smackx.jar differ diff --git a/m2/pom.xml b/m2/pom.xml index 9d8e3d7..25d5efa 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -7,7 +7,7 @@ org.jitsi jitsi-universe - 1.0-20160511.125516-17 + 1.0-20161228.135522-20 jitsi diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java index a2b5fd0..86666f3 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderFactoryJabberImpl.java @@ -187,7 +187,7 @@ public class ProtocolProviderFactoryJabberImpl ProtocolProviderServiceJabberImpl service = new ProtocolProviderServiceJabberImpl(); - service.initialize(userID, accountID); + service.initialize(userID, (JabberAccountID) accountID); return service; } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java index 60f9629..47b9b75 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java @@ -42,6 +42,7 @@ import net.java.sip.communicator.service.certificate.*; import net.java.sip.communicator.service.dns.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; +import net.java.sip.communicator.service.protocol.jabber.*; import net.java.sip.communicator.service.protocol.jabberconstants.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.Logger; @@ -240,7 +241,7 @@ public class ProtocolProviderServiceJabberImpl /** * The identifier of the account that this provider represents. */ - private AccountID accountID = null; + private JabberAccountID accountID = null; /** * Used when we need to re-register @@ -1121,11 +1122,24 @@ public class ProtocolProviderServiceJabberImpl JabberLoginStrategy loginStrategy) throws XMPPException { - ConnectionConfiguration confConn = new ConnectionConfiguration( - address.getAddress().getHostAddress(), - address.getPort(), - serviceName, proxy - ); + // BOSH or TCP ? + ConnectionConfiguration confConn; + String boshURL = accountID.getBoshUrl(); + boolean isBosh = !org.jitsi.util.StringUtils.isNullOrEmpty(boshURL); + + if (isBosh) + { + confConn = new BOSHConfiguration(serviceName); + ((BOSHConfiguration)confConn).setBoshUrl(boshURL); + } + else + { + confConn + = new ConnectionConfiguration( + address.getAddress().getHostAddress(), + address.getPort(), + serviceName, proxy); + } // if we have OperationSetPersistentPresence skip sending initial // presence while login is executed, the OperationSet will take care @@ -1153,7 +1167,11 @@ public class ProtocolProviderServiceJabberImpl disconnectAndCleanConnection(); } - connection = new XMPPConnection(confConn); + connection + = isBosh + ? new XMPPBOSHConnection((BOSHConfiguration)confConn) + : new XMPPConnection(confConn); + this.address = address; try @@ -1551,7 +1569,7 @@ public class ProtocolProviderServiceJabberImpl * @see net.java.sip.communicator.service.protocol.AccountID */ protected void initialize(String screenname, - AccountID accountID) + JabberAccountID accountID) { synchronized(initializationLock) { -- cgit v1.1 From 5ef2ada60481f75d3f2579d77db9f5f657207696 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 28 Dec 2016 23:56:35 +0100 Subject: Update libjitsi Fix media issue (jitsi/libjitsi#225) Jenkins build 901 jitsi/libjitsi@c734e89ab7d20e1da883ec98e326d628aa69efe6 --- .classpath | 2 +- build.xml | 2 +- .../libjitsi-1.0-20161226.161151-208.jar | Bin 8791384 -> 0 bytes .../libjitsi-1.0-20161228.210146-211.jar | Bin 0 -> 8792616 bytes nbproject/project.xml | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar diff --git a/.classpath b/.classpath index 415a47e..d534251 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index 44f0ad0..fb24f99 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar b/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar deleted file mode 100644 index 280000b..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar b/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar new file mode 100644 index 0000000..3d00a3e Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar differ diff --git a/nbproject/project.xml b/nbproject/project.xml index d69b2de..d3c47a5 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161226.161151-208.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 63b420a0c10aa8d619e1c4a1816de7a98e59cfa3 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 2 Jan 2017 16:15:32 +0100 Subject: Update RPM spec file to be used directly from source control --- resources/install/rpm/Readme.txt | 6 ------ resources/install/rpm/SPECS/build-jitsi-rpm.sh | 11 ++++++++--- resources/install/rpm/SPECS/jitsi.spec | 25 +++++++++++++------------ resources/install/rpm/readme.txt | 6 ++++++ 4 files changed, 27 insertions(+), 21 deletions(-) delete mode 100644 resources/install/rpm/Readme.txt create mode 100644 resources/install/rpm/readme.txt diff --git a/resources/install/rpm/Readme.txt b/resources/install/rpm/Readme.txt deleted file mode 100644 index 03903da..0000000 --- a/resources/install/rpm/Readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -Packages needed subversion rpm-build java-devel ant. -Create folder ~/rpmbuild. -Copy or link the SPECS folder there. -To create rpm packages just need to call build-jitsi-rpm.sh script, like: -~/rpmbuild/SPECS/build-jitsi-rpm.sh 1.1 4454.10414 10414 - diff --git a/resources/install/rpm/SPECS/build-jitsi-rpm.sh b/resources/install/rpm/SPECS/build-jitsi-rpm.sh index f501d51..ca0af7a 100755 --- a/resources/install/rpm/SPECS/build-jitsi-rpm.sh +++ b/resources/install/rpm/SPECS/build-jitsi-rpm.sh @@ -5,11 +5,13 @@ cd $SCRIPT_DIR #exec > "${0%.*}.log" 2>&1 if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "-?" || $# -lt 1 ]]; then - echo "Usage $0 BUILD_NUMBER" + echo "Usage: $0 BUILD_NUMBER GOOGLE_API_ID GOOGLE_API_SECRET" exit 1 fi buildNumber=$1 +googleApiId=$2 +googleApiSecret=$3 # Deletes everything but the newest files matching the specified pattern clean_oldies() { @@ -24,6 +26,7 @@ clean_oldies() { ls -t $pattern | tail -$tailCount | xargs rm -f } +[[ ! -d SOURCES ]] && mkdir SOURCES cd SOURCES [[ ! -d jitsi ]] && git clone https://github.com/jitsi/jitsi.git @@ -43,11 +46,13 @@ rm -f jitsi-src*.zip zipFileName=jitsi-src-${version}-${buildNumber/./-}.zip zip -rq $zipFileName jitsi -x 'jitsi/.git/* jitsi/.gitignore' +[[ ! -d $SCRIPT_DIR/SPECS/ ]] && mkdir $SCRIPT_DIR/SPECS/ +cp jitsi/resources/install/rpm/SPECS/jitsi.spec $SCRIPT_DIR/SPECS/ sed -i \ -e "s@Version:\( *\).*@Version:\1$version@" \ -e "s@Release:\( *\).*@Release:\1$buildNumber@" \ --e "s@Source0:\( *\).*@Source0:\1http://download.jitsi.org/jitsi/nightly/src/$zipFileName@" \ --e "s@ant -Dlabel=.* rebuild@ant -Dlabel=$buildNumber rebuild@" \ +-e "s@Source0:\( *\).*@Source0:\1https://download.jitsi.org/jitsi/nightly/src/$zipFileName@" \ +-e "s@ant -Dlabel=.* rebuild@ant rebuild -Dlabel=$buildNumber -Dgoogle.api.client.id=$googleApiId -Dgoogle.api.client.secret=$googleApiSecret@" \ $SCRIPT_DIR/SPECS/jitsi.spec rm -f $SCRIPT_DIR/RPMS/i686/jitsi*.rpm diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index c427c4d..f7a8185 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -1,28 +1,29 @@ Name: jitsi -Version: 2.5 -Release: 5267 +Version: 2.9 +Release: 5537 Summary: Jitsi - Open Source Video Calls and Chat Packager: Damian Minkov Group: Applications/Internet License: Apache License 2.0 -URL: https://www.jitsi.org +URL: https://jitsi.org Source0: https://download.jitsi.org/jitsi/nightly/src/%{name}-src-%{version}-%{release}.zip BuildRoot: %{_topdir}/buildroot AutoReqProv: no -BuildRequires: java-devel >= 0:1.6 -BuildRequires: ant -BuildRequires: ant-nodeps -BuildRequires: gzip -BuildRequires: git-core +BuildRequires: java-devel >= 0:1.7, + ant, + ant-nodeps, + gzip, + git -Requires: java >= 0:1.6 +Requires: java >= 0:1.7, + speex, + speexdsp %description -Jitsi (formerly SIP Communicator) is an audio/video and chat communicator -that supports protocols such as SIP, XMPP/Jabber, AIM/ICQ, IRC -and many other useful features. +Jitsi is an audio/video and chat communicator that supports protocols +such as SIP, XMPP/Jabber, AIM/ICQ, IRC and many other useful features. %define debug_package %{nil} diff --git a/resources/install/rpm/readme.txt b/resources/install/rpm/readme.txt new file mode 100644 index 0000000..16d6b14 --- /dev/null +++ b/resources/install/rpm/readme.txt @@ -0,0 +1,6 @@ +Packages needed: git, rpm-build, java-devel, ant + +1) Create folder ~/rpmbuild +2) Copy build-jitsi-rpm.sh there +3) Call build-jitsi-rpm.sh script, like: + ~/rpmbuild/build-jitsi-rpm.sh VERSION GOOGLE_API_ID GOOGLE_API_SECRET -- cgit v1.1 From aae562567882cd14f4e0e465a649ddd6d2ebe9da Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 2 Jan 2017 17:25:05 +0100 Subject: Fix path to weupnp --- nbproject/project.xml | 2 +- resources/install/build.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nbproject/project.xml b/nbproject/project.xml index d3c47a5..15d2442 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.2-SNAPSHOT.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 diff --git a/resources/install/build.xml b/resources/install/build.xml index fe1ff31..41624fa 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -2882,7 +2882,7 @@ + link="${debian.src.dir}/lib/installer-exclude/weupnp-0.1.4.jar"/> Date: Mon, 2 Jan 2017 17:40:15 +0100 Subject: Remove unnecessary dependencies to Glassfish libs Closes Debian Bug #838897 --- resources/install/debian/control-src.tmpl | 2 -- resources/install/debian/control.tmpl | 2 -- 2 files changed, 4 deletions(-) diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index 1bfcee4..4c7dd51 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -47,8 +47,6 @@ Build-Depends: debhelper (>= 9), javahelper, libglib2.0-dev, libguava-java, libhsqldb-java, - glassfish-activation, - glassfish-mail, libjcalendar-java, libphonenumber6-java, libslf4j-java diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index e722ff7..79b363b 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -53,8 +53,6 @@ Build-Depends: debhelper (>= 9), javahelper, libglib2.0-dev, libpulse-dev, libgoogle-collections-java, - glassfish-activation, - glassfish-mail, libbcpkix-java Standards-Version: 3.9.5 -- cgit v1.1 From 3e2fd94a561324b331f444910d8a24749b8314ff Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 2 Jan 2017 18:20:52 +0100 Subject: Depend on normal minimal dnsjava version --- resources/install/debian/control-src.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index 4c7dd51..f7ad24f 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -108,7 +108,7 @@ Package: _PACKAGE_NAME_-common Section: libs Architecture: all Depends: ${misc:Depends}, ${shlibs:Depends}, - libdnsjava-java (>= 2.1.7~), + libdnsjava-java (>= 2.1.7), libxpp3-java, libjzlib-java, libbcpkix-java -- cgit v1.1 From 4dc9d121949e8888472a02451d5589c77358d737 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 3 Jan 2017 21:32:52 +0100 Subject: Update libjitsi Closes #113, #213 Jenkins build 907 jitsi/libjitsi@dbd426a43adee604795b2a83de16643f1cb6f8d2 --- .classpath | 2 +- build.xml | 2 +- .../libjitsi-1.0-20161228.210146-211.jar | Bin 8792616 -> 0 bytes .../libjitsi-1.0-20170103.173255-217.jar | Bin 0 -> 8996207 bytes nbproject/project.xml | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar diff --git a/.classpath b/.classpath index d534251..46ac7eb 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index fb24f99..59b0ce2 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar b/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar deleted file mode 100644 index 3d00a3e..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar b/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar new file mode 100644 index 0000000..4026149 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar differ diff --git a/nbproject/project.xml b/nbproject/project.xml index 15d2442..0617c0a 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20161228.210146-211.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From ea1068ae207ab9ec30b29bf1d618dd11156d2d31 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 3 Jan 2017 22:17:30 +0100 Subject: Realign RPM dependencies --- resources/install/rpm/SPECS/jitsi.spec | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index f7a8185..e896ddc 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -11,15 +11,15 @@ Source0: https://download.jitsi.org/jitsi/nightly/src/%{name}-src-%{version}-% BuildRoot: %{_topdir}/buildroot AutoReqProv: no -BuildRequires: java-devel >= 0:1.7, - ant, - ant-nodeps, - gzip, - git - -Requires: java >= 0:1.7, - speex, - speexdsp +BuildRequires: java-devel >= 1:1.7 +Buildrequires: ant +Buildrequires: ant-nodeps +Buildrequires: gzip +Buildrequires: git + +Requires: java >= 1:1.7 +Requires: speex +Requires: speexdsp %description Jitsi is an audio/video and chat communicator that supports protocols -- cgit v1.1 From ecf3954dd7f738e6f828da861788d9b3760b8468 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 3 Jan 2017 16:17:04 -0600 Subject: Updates smack's roster impl to filter bad packets. Filters received roster packets based on from field - should be empty user bare jid or service name. --- lib/installer-exclude/smack.jar | Bin 412905 -> 413550 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/installer-exclude/smack.jar b/lib/installer-exclude/smack.jar index 4bda197..80bd5c7 100644 Binary files a/lib/installer-exclude/smack.jar and b/lib/installer-exclude/smack.jar differ -- cgit v1.1 From 01bccdea45cdf07d5bbbc9c4e9f4073e88aee024 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 4 Jan 2017 23:09:46 +0100 Subject: Switch to database based configuration by default The properties file based configuration can be re-enabled by creating an empty text file named .usepropfileconfig in Jitsi's configuration directory (~/.jitsi, %appdata%\Jitsi) --- .../impl/configuration/ConfigurationActivator.java | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java index 1553658..a019c13 100644 --- a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java +++ b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java @@ -64,39 +64,38 @@ public class ConfigurationActivator if (fas != null) { - File useDatabaseConfig; - + File usePropFileConfig; try { - useDatabaseConfig + usePropFileConfig = fas.getPrivatePersistentFile( - ".usedatabaseconfig", + ".usepropfileconfig", FileCategory.PROFILE); } catch (Exception ise) { - // There is somewhat of a chicken-and-egg dependency between // FileConfigurationServiceImpl and ConfigurationServiceImpl: // FileConfigurationServiceImpl throws IllegalStateException if // certain System properties are not set, // ConfigurationServiceImpl will make sure that these properties - //are set but it will do that later. + // are set but it will do that later. // A SecurityException is thrown when the destination // is not writable or we do not have access to that folder - useDatabaseConfig = null; + usePropFileConfig = null; } - // BETA: if the marker file exists, use the database configuration - if ((useDatabaseConfig != null) && useDatabaseConfig.exists()) + if (usePropFileConfig != null && usePropFileConfig.exists()) { - logger.info("Using database configuration store."); - this.cs = new JdbcConfigService(fas); + logger.info("Using properties file configuration store."); + this.cs = LibJitsi.getConfigurationService(); } } if (this.cs == null) - this.cs = LibJitsi.getConfigurationService(); + { + this.cs = new JdbcConfigService(fas); + } bundleContext.registerService( ConfigurationService.class.getName(), -- cgit v1.1 From 169ace9e6b745530f17fc19b51fa19d30b809cdc Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 4 Jan 2017 23:13:56 +0100 Subject: Depend on generic Java 7 (or later) SDK/runtime Closes #265 --- resources/install/debian/control-src.tmpl | 4 ++-- resources/install/debian/control.tmpl | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index f7ad24f..fc677e2 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -6,7 +6,7 @@ Uploaders: Emil Ivov , Damian Minkov Homepage: _APP_WEB_ Build-Depends: debhelper (>= 9), javahelper, dpkg-dev (>= 1.16.1), - default-jdk, + default-jdk | java7-sdk, ant, ant-optional, ant-contrib-cpptasks, @@ -59,7 +59,7 @@ Depends: ${misc:Depends}, _PACKAGE_NAME_-common (= ${source:Version}), libjitsi (= ${libjitsi:version}), libjitsi-jni (= ${libjitsi:version}), - default-jre, + default-jre | java7-runtime, libunixsocket-java, libhttpcore-java, liblog4j1.2-java, diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index 79b363b..50f56a8 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -6,7 +6,7 @@ Uploaders: Emil Ivov Homepage: _APP_WEB_ Build-Depends: debhelper (>= 9), javahelper, dpkg-dev (>= 1.16.1), - default-jdk, + default-jdk | java7-sdk, ant, ant-optional, ant-contrib-cpptasks, @@ -58,7 +58,9 @@ Standards-Version: 3.9.5 Package: _PACKAGE_NAME_ Architecture: i386 amd64 -Depends: default-jre, libxss1, jitsi-archive-keyring +Depends: default-jre | java7-runtime, + libxss1, + jitsi-archive-keyring Description: VoIP and Instant Messaging client _APP_NAME_ is an application that allows you to do audio/video conversations over the Internet through the SIP and XMPP/Jabber protocol, -- cgit v1.1 From 0c47202e96e8461b6443d0b8f7cc2c5e0a93d654 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 4 Jan 2017 23:16:42 +0100 Subject: Debian (binary build): depend on libspeex (needed by libjitsi) --- resources/install/debian/control.tmpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index 50f56a8..a95fd02 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -60,6 +60,8 @@ Package: _PACKAGE_NAME_ Architecture: i386 amd64 Depends: default-jre | java7-runtime, libxss1, + libspeex1, + libspeexdsp1, jitsi-archive-keyring Description: VoIP and Instant Messaging client _APP_NAME_ is an application that allows you to do audio/video -- cgit v1.1 From 0929ebc962add1fe4e6f22d0d6efb3d676671466 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 00:25:00 +0100 Subject: Properly log IPv6 frames into .pcap --- .../impl/packetlogging/PacketLoggingServiceImpl.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java index 220f36b..1e459f1 100644 --- a/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java +++ b/src/net/java/sip/communicator/impl/packetlogging/PacketLoggingServiceImpl.java @@ -71,10 +71,17 @@ public class PacketLoggingServiceImpl new byte[]{ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x08, (byte)0x00 + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }; + /** IEEE 802.3 EtherType for IPv4 */ + private final static byte[] ipv4EtherType = + new byte[] { 0x08, 0x00 }; + + /** IEEE 802.3 EtherType for IPv6 */ + private final static byte[] ipv6EtherType = + new byte[] { (byte)0x86, (byte)0xdd }; + /** * The fake ipv4 header we use as template. */ @@ -562,6 +569,7 @@ public class PacketLoggingServiceImpl int tsSec = (int)(current/1000); int tsUsec = (int)((current%1000) * 1000); int feakHeaderLen = fakeEthernetHeader.length + + (isIPv4 ? ipv4EtherType : ipv6EtherType).length + ipHeader.length + transportHeader.length; int inclLen = packet.packetLength + feakHeaderLen; int origLen = inclLen; @@ -586,6 +594,7 @@ public class PacketLoggingServiceImpl addInt(origLen); outputStream.write(fakeEthernetHeader); + outputStream.write(isIPv4 ? ipv4EtherType : ipv6EtherType); outputStream.write(ipHeader); outputStream.write(transportHeader); outputStream.write( -- cgit v1.1 From 6296c62a54d81e14182bacc507361d7e07e89d69 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 12:49:30 +0100 Subject: Use NetworkUtils to handle all IPv6 formats --- .../communicator/impl/protocol/sip/AddressResolverImpl.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/AddressResolverImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/AddressResolverImpl.java index eba0da6..4fd1b6f 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/AddressResolverImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/AddressResolverImpl.java @@ -70,18 +70,8 @@ public class AddressResolverImpl // if it is a textual IP address, do no try to resolve it if(NetworkUtils.isValidIPAddress(hostAddress)) { - byte[] addr = null; - - addr = NetworkUtils.strToIPv4(hostAddress); - - // not an IPv4, try IPv6 - if (addr == null) - { - addr = NetworkUtils.strToIPv6(hostAddress); - } - InetSocketAddress hostSocketAddress = new InetSocketAddress( - InetAddress.getByAddress(hostAddress, addr), + NetworkUtils.getInetAddress(hostAddress), inputAddress.getPort()); return new HopImpl(hostSocketAddress.getHostName(), inputAddress.getPort(), -- cgit v1.1 From 6830162ae244f90c07bc43fb440039680641bbb9 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 12:50:34 +0100 Subject: Handle RFC2732 IPv6 addresses ([::1] or [::1%1]) --- src/net/java/sip/communicator/util/NetworkUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/net/java/sip/communicator/util/NetworkUtils.java b/src/net/java/sip/communicator/util/NetworkUtils.java index 427f176..310b8b1 100644 --- a/src/net/java/sip/communicator/util/NetworkUtils.java +++ b/src/net/java/sip/communicator/util/NetworkUtils.java @@ -420,6 +420,15 @@ public class NetworkUtils colonIndex = -1; int i = 0, j = 0; + + // Can be wrapped in [] + if (addrBuff[i] == '[') + { + ++i; + if (scopeID == -1) + --srcb_length; + } + // Starting : mean we need to have at least one more. if (addrBuff[i] == ':') if (addrBuff[++i] != ':') -- cgit v1.1 From d36e078228fbebf4a4c9cf003e05c6c150ed90e1 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 12:52:51 +0100 Subject: Log Java IP stack properties The generic logging of all system properties wouldn't log them if not set. Also specifically doesn't use Boolean.getBoolean to handle empty cases. --- src/net/java/sip/communicator/util/NetworkUtils.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/net/java/sip/communicator/util/NetworkUtils.java b/src/net/java/sip/communicator/util/NetworkUtils.java index 310b8b1..2bb4c2b 100644 --- a/src/net/java/sip/communicator/util/NetworkUtils.java +++ b/src/net/java/sip/communicator/util/NetworkUtils.java @@ -107,6 +107,14 @@ public class NetworkUtils */ private static final Random random = new Random(); + static + { + String prefer6 = System.getProperty("java.net.preferIPv6Addresses"); + String prefer4 = System.getProperty("java.net.preferIPv4Stack"); + logger.info("java.net.preferIPv6Addresses=" + prefer6); + logger.info("java.net.preferIPv4Stack=" + prefer4); + } + /** * Determines whether the address is the result of windows auto configuration. * (i.e. One that is in the 169.254.0.0 network) -- cgit v1.1 From 9bc6e3dd88084753480fa7f4700d0fd47f04e0d2 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 12:53:56 +0100 Subject: Log getting local address as this often fails --- src/net/java/sip/communicator/impl/protocol/sip/SipStackSharing.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/SipStackSharing.java b/src/net/java/sip/communicator/impl/protocol/sip/SipStackSharing.java index 2e714b5..c92782e 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/SipStackSharing.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/SipStackSharing.java @@ -1172,6 +1172,9 @@ public class SipStackSharing String transport) throws IOException { + logger.info("Gettting source address for " + + localAddress + " -> " + dst + ":" + dstPort + + "(" + transport + ")"); if(ListeningPoint.TLS.equalsIgnoreCase(transport)) return (java.net.InetSocketAddress)(((SipStackImpl)this.stack) .getLocalAddressForTlsDst(dst, dstPort, localAddress)); -- cgit v1.1 From f8811b82ed6aa4d9f96fd3f93fcf126b13b38a72 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 13:26:23 +0100 Subject: Ignore any routes in the SIP header when an outbound proxy is used If this isn't done, the next Hop will be DNS resolved to - a foreign address - another address than to which the account is currently connected - not resolved at all (e.g. an internal name behind the proxy) --- .../impl/protocol/sip/ProxyRouter.java | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProxyRouter.java b/src/net/java/sip/communicator/impl/protocol/sip/ProxyRouter.java index 5d60612..b6bf997 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProxyRouter.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProxyRouter.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.protocol.sip; import gov.nist.javax.sip.stack.*; +import java.net.*; import java.util.*; import javax.sip.*; @@ -26,6 +27,7 @@ import javax.sip.address.*; import javax.sip.header.*; import javax.sip.message.*; +import net.java.sip.communicator.impl.protocol.sip.net.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; @@ -137,7 +139,9 @@ public class ProxyRouter ProtocolProviderServiceSipImpl sipProvider = ((ProtocolProviderServiceSipImpl) service); - String proxy = sipProvider.getConnection().getOutboundProxyString(); + final ProxyConnection connection = sipProvider.getConnection(); + final String proxy = connection.getOutboundProxyString(); + logger.trace("Router for proxy: " + proxy); boolean forceLooseRouting = sipProvider.getAccountID() @@ -146,13 +150,30 @@ public class ProxyRouter // P2P case if (proxy == null || forceLooseRouting ) + { + logger.info("Returning default SIP router, P2P/loose routing"); return this.getDefaultRouter(); + } // outbound proxy case Router router = routerCache.get(proxy); if (router == null) { - router = new DefaultRouter(stack, proxy); + router = new DefaultRouter(stack, proxy) + { + @Override + public Hop getNextHop(Request request) throws SipException + { + logger.info("Outbound proxy mode, using proxy " + + proxy + " as hop instead of an address resolved" + + " by the SIP router"); + InetSocketAddress sa = connection.getAddress(); + return new HopImpl( + sa.getAddress().getHostAddress(), + sa.getPort(), + connection.getTransport()); + } + }; routerCache.put(proxy, router); } return router; @@ -164,6 +185,7 @@ public class ProxyRouter logger.error("unable to identify the service which created this " + "out-of-dialog request"); + logger.info("Returning default router"); return this.getDefaultRouter(); } -- cgit v1.1 From 53cea22e54546e8f52bccfec48a0c1949816c6b8 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 17:47:21 +0100 Subject: Update libjitsi Jenkins build 912 jitsi/libjitsi@8363e20e523aaa117250e40886e9f086f73a0245 --- .classpath | 2 +- build.xml | 2 +- .../libjitsi-1.0-20170103.173255-217.jar | Bin 8996207 -> 0 bytes .../libjitsi-1.0-20170107.144734-222.jar | Bin 0 -> 9007818 bytes nbproject/project.xml | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar diff --git a/.classpath b/.classpath index 46ac7eb..61d9df1 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index 59b0ce2..abd86a9 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar b/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar deleted file mode 100644 index 4026149..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar b/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar new file mode 100644 index 0000000..4313b83 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar differ diff --git a/nbproject/project.xml b/nbproject/project.xml index 0617c0a..bc1138b 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170103.173255-217.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 3416d6a124fffd8545f061b326d011048ff11be1 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 17:48:43 +0100 Subject: Load JNI lib into classloader of bundle rather than of libjitsi Needs libjitsi >= 912 Closes #288 --- .../sip/communicator/impl/sysactivity/SystemActivityNotifications.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java index 6d9edda..e2fb17a 100644 --- a/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java +++ b/src/net/java/sip/communicator/impl/sysactivity/SystemActivityNotifications.java @@ -115,7 +115,7 @@ public class SystemActivityNotifications if(!org.jitsi.util.OSUtils.IS_ANDROID) { JNIUtils.loadLibrary("sysactivitynotifications", - SystemActivityNotifications.class.getClassLoader()); + SystemActivityNotifications.class); ptr = allocAndInit(); if (ptr == -1) -- cgit v1.1 From a40120d960441339a0f5e372da23e60d93d9bc7c Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 18:56:44 +0100 Subject: Update jitsi-lgpl-dependencies jitsi/jitsi-lgpl-dependencies@def83cd3869eae7e314ddf4272c0b60fc1cfd4ba --- .../jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar | Bin 7902830 -> 7903378 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar index ec93db9..257e3ed 100644 Binary files a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar and b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar differ -- cgit v1.1 From cb3f6a35e91e23915663b54d579071a8d37e9394 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 19:58:24 +0100 Subject: Disable config service persistency test This test is based around the properties-file based ConfigService. It assumes knowledge about the inner workings and doesn't work when the database-based ConfigService is active, which is the default since 01bccdea45cdf07d5bbbc9c4e9f4073e88aee024 --- .../sip/communicator/slick/configuration/ConfigurationServiceLick.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/net/java/sip/communicator/slick/configuration/ConfigurationServiceLick.java b/test/net/java/sip/communicator/slick/configuration/ConfigurationServiceLick.java index 175f9ab..f56e755 100644 --- a/test/net/java/sip/communicator/slick/configuration/ConfigurationServiceLick.java +++ b/test/net/java/sip/communicator/slick/configuration/ConfigurationServiceLick.java @@ -52,7 +52,7 @@ public class ConfigurationServiceLick properties.put("service.pid", getName()); addTestSuite(TestConfigurationService.class); - addTestSuite(TestConfigurationServicePersistency.class); + //addTestSuite(TestConfigurationServicePersistency.class); addTestSuite(TestConfigurationSlickFinalizer.class); bundleContext.registerService(getClass().getName(), this, properties); -- cgit v1.1 From 589fd0b457db6d188de1a5961abb56586e136add Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:47:20 +0100 Subject: Add hashCode to classes overriding equals --- .../communicator/impl/gui/main/UINotification.java | 8 +++++++ .../impl/ldap/LdapPersonFoundImpl.java | 6 +++++ .../gibberish/ContactGroupGibberishImpl.java | 25 +++++++++++++++++++++ .../extensions/jingle/CryptoPacketExtension.java | 12 ++++++++++ .../impl/protocol/mock/MockContactGroup.java | 25 +++++++++++++++++++++ .../impl/protocol/sip/ContactGroupSipImpl.java | 26 ++++++++++++++++++++++ .../PhoneNumberSourceContact.java | 12 ++++++++++ .../sip/communicator/service/gui/Container.java | 6 +++++ .../service/protocol/RegistrationState.java | 6 +++++ .../service/protocol/ServerStoredDetails.java | 6 +++++ .../service/protocol/WhiteboardPoint.java | 8 +++++++ 11 files changed, 140 insertions(+) diff --git a/src/net/java/sip/communicator/impl/gui/main/UINotification.java b/src/net/java/sip/communicator/impl/gui/main/UINotification.java index fbfb6da..4304907 100644 --- a/src/net/java/sip/communicator/impl/gui/main/UINotification.java +++ b/src/net/java/sip/communicator/impl/gui/main/UINotification.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.impl.gui.main; +import java.util.Objects; + /** * The UINotification class represents a notification received in the * user interface. This could be a missed call, voicemail, email notification or @@ -172,4 +174,10 @@ public class UINotification return true; } + + @Override + public int hashCode() + { + return Objects.hash(notificationName, parentGroup); + } } diff --git a/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java b/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java index 3d8e6bf..36632fa 100644 --- a/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java +++ b/src/net/java/sip/communicator/impl/ldap/LdapPersonFoundImpl.java @@ -433,4 +433,10 @@ public class LdapPersonFoundImpl return this.toString().equals(o.toString()) && this.getDN().equals(((LdapPersonFound) o).getDN()); } + + @Override + public int hashCode() + { + return Objects.hash(toString(), getDN()); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/gibberish/ContactGroupGibberishImpl.java b/src/net/java/sip/communicator/impl/protocol/gibberish/ContactGroupGibberishImpl.java index 2a95493..8528267 100644 --- a/src/net/java/sip/communicator/impl/protocol/gibberish/ContactGroupGibberishImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/gibberish/ContactGroupGibberishImpl.java @@ -577,4 +577,29 @@ public class ContactGroupGibberishImpl return true; } + + @Override + public int hashCode() + { + List objects = new ArrayList(); + objects.add(getGroupName()); + objects.add(getUID()); + objects.add(countContacts()); + objects.add(countSubgroups()); + + //traverse child contacts + for (Contact c : contacts) + { + objects.add(c.getAddress()); + } + + + //traverse subgroups + for (ContactGroup g : subGroups) + { + objects.add(g.getGroupName()); + } + + return Objects.hash(objects.toArray()); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java index 69b2e47..3ccbd72 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle; +import java.util.Objects; + import ch.imvs.sdes4j.srtp.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.*; @@ -332,4 +334,14 @@ public class CryptoPacketExtension } return false; } + + @Override + public int hashCode() + { + return Objects.hash( + getCryptoSuite(), + getKeyParams(), + getSessionParams(), + getTag()); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockContactGroup.java b/src/net/java/sip/communicator/impl/protocol/mock/MockContactGroup.java index fa4fff1..e6cdd36 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockContactGroup.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockContactGroup.java @@ -506,6 +506,31 @@ public class MockContactGroup return true; } + @Override + public int hashCode() + { + List objects = new ArrayList(); + objects.add(getGroupName()); + objects.add(getUID()); + objects.add(countContacts()); + objects.add(countSubgroups()); + + //traverse child contacts + for (Contact c : contacts) + { + objects.add(c.getAddress()); + } + + + //traverse subgroups + for (ContactGroup g : subGroups) + { + objects.add(g.getGroupName()); + } + + return Objects.hash(objects.toArray()); + } + public void setPersistent(boolean isPersistent) { this.isPersistent = isPersistent; diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ContactGroupSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ContactGroupSipImpl.java index f5782f1..3c2aeb5 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ContactGroupSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ContactGroupSipImpl.java @@ -641,5 +641,31 @@ public class ContactGroupSipImpl return true; } + + @Override + public int hashCode() + { + List objects = new ArrayList(); + objects.add(getGroupName()); + objects.add(getUID()); + objects.add(countContacts()); + objects.add(countSubgroups()); + objects.add(getProtocolProvider()); + + //traverse child contacts + for (Contact c : contacts) + { + objects.add(c.getAddress()); + } + + + //traverse subgroups + for (ContactGroup g : subGroups) + { + objects.add(g.getGroupName()); + } + + return Objects.hash(objects.toArray()); + } } diff --git a/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberSourceContact.java b/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberSourceContact.java index ef7352f..d7ec804 100644 --- a/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberSourceContact.java +++ b/src/net/java/sip/communicator/plugin/phonenumbercontactsource/PhoneNumberSourceContact.java @@ -107,6 +107,18 @@ public class PhoneNumberSourceContact return true; } + @Override + public int hashCode() + { + String dn = getDisplayName(); + if (dn != null) + { + return getDisplayName().hashCode(); + } + + return 37; + } + /** * Returns the protocol contact used. * @return the protocol contact used. diff --git a/src/net/java/sip/communicator/service/gui/Container.java b/src/net/java/sip/communicator/service/gui/Container.java index 1b5e144..d0fcab7 100644 --- a/src/net/java/sip/communicator/service/gui/Container.java +++ b/src/net/java/sip/communicator/service/gui/Container.java @@ -257,4 +257,10 @@ public class Container else return false; } + + @Override + public int hashCode() + { + return containerName.hashCode(); + } } diff --git a/src/net/java/sip/communicator/service/protocol/RegistrationState.java b/src/net/java/sip/communicator/service/protocol/RegistrationState.java index 9bd3eb0..368e5b1 100644 --- a/src/net/java/sip/communicator/service/protocol/RegistrationState.java +++ b/src/net/java/sip/communicator/service/protocol/RegistrationState.java @@ -177,4 +177,10 @@ public class RegistrationState && obj != null && statusString.equals(((RegistrationState)obj).statusString); } + + @Override + public int hashCode() + { + return statusString.hashCode(); + } } diff --git a/src/net/java/sip/communicator/service/protocol/ServerStoredDetails.java b/src/net/java/sip/communicator/service/protocol/ServerStoredDetails.java index 23cb895..4d21864 100644 --- a/src/net/java/sip/communicator/service/protocol/ServerStoredDetails.java +++ b/src/net/java/sip/communicator/service/protocol/ServerStoredDetails.java @@ -156,6 +156,12 @@ public class ServerStoredDetails else return false; } + + @Override + public int hashCode() + { + return Objects.hash(detailDisplayName, value); + } } /** diff --git a/src/net/java/sip/communicator/service/protocol/WhiteboardPoint.java b/src/net/java/sip/communicator/service/protocol/WhiteboardPoint.java index 1774718..3e26e7a 100644 --- a/src/net/java/sip/communicator/service/protocol/WhiteboardPoint.java +++ b/src/net/java/sip/communicator/service/protocol/WhiteboardPoint.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.service.protocol; +import java.util.Objects; + /** * A point representing a location in {@code (x,y)} coordinate space, * specified in integer precision. @@ -126,6 +128,12 @@ public class WhiteboardPoint implements Cloneable return false; } + @Override + public int hashCode() + { + return Objects.hash(x, y); + } + /** * Returns a string representation of this point and its location * in the {@code (x,y)} coordinate space. This method is intended to be -- cgit v1.1 From 70b8b7d67b894fe7753b8681ee37cfa4721f589f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:48:14 +0100 Subject: Remove unused and long deprecated method --- .../AbstractOperationSetBasicInstantMessaging.java | 8 -------- .../protocol/OperationSetBasicInstantMessaging.java | 16 ---------------- 2 files changed, 24 deletions(-) diff --git a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java index 4270a78..6f038b5 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractOperationSetBasicInstantMessaging.java @@ -137,14 +137,6 @@ public abstract class AbstractOperationSetBasicInstantMessaging return createMessage(messageText); } - /** - * {@inheritDoc} - */ - public Message createMessageWithUID(String messageText, String messageUID) - { - return createMessage(messageText); - } - public abstract Message createMessage( String content, String contentType, String encoding, String subject); diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessaging.java b/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessaging.java index c0918cb..55dec9a 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessaging.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessaging.java @@ -80,22 +80,6 @@ public interface OperationSetBasicInstantMessaging String messageText, String contentType, String messageUID); /** - * Create a Message instance with the specified UID and a default - * (text/plain) content type and encoding. - * This method can be useful when message correction is required. One can - * construct the corrected message to have the same UID as the message - * before correction. - * - * @param messageText the string content of the message. - * @param messageUID the unique identifier of this message. - * @return Message the newly created message - * - * @deprecated Method will be removed once OTR bundle is updated on Android. - */ - @Deprecated - public Message createMessageWithUID(String messageText, String messageUID); - - /** * Sends the message to the destination indicated by the * to contact. * -- cgit v1.1 From 029753e4262330865773848b895c6ca2af16f5a5 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:48:51 +0100 Subject: Remove redundant casts --- .../impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java | 2 +- .../plugin/ircaccregwizz/IrcAccountRegistrationWizard.java | 3 +-- .../java/sip/communicator/plugin/pluginmanager/BundleComparator.java | 4 ++-- .../java/sip/communicator/plugin/skinmanager/BundleComparator.java | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java index 6b09978..7a1c2b3 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java @@ -275,7 +275,7 @@ public class OperationSetMultiUserChatIrcImpl */ protected ChatRoomIrcImpl getChatRoom(final String chatRoomName) { - return (ChatRoomIrcImpl) this.chatRoomCache.get(chatRoomName); + return this.chatRoomCache.get(chatRoomName); } /** diff --git a/src/net/java/sip/communicator/plugin/ircaccregwizz/IrcAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/ircaccregwizz/IrcAccountRegistrationWizard.java index f062058..962aeb1 100644 --- a/src/net/java/sip/communicator/plugin/ircaccregwizz/IrcAccountRegistrationWizard.java +++ b/src/net/java/sip/communicator/plugin/ircaccregwizz/IrcAccountRegistrationWizard.java @@ -358,8 +358,7 @@ public class IrcAccountRegistrationWizard ServiceReference serRef = providerFactory .getProviderForAccount(accountID); - protocolProvider = (ProtocolProviderService) - IrcAccRegWizzActivator.bundleContext + protocolProvider = IrcAccRegWizzActivator.bundleContext .getService(serRef); } catch (IllegalStateException exc) diff --git a/src/net/java/sip/communicator/plugin/pluginmanager/BundleComparator.java b/src/net/java/sip/communicator/plugin/pluginmanager/BundleComparator.java index 06d2db4..48a4305 100644 --- a/src/net/java/sip/communicator/plugin/pluginmanager/BundleComparator.java +++ b/src/net/java/sip/communicator/plugin/pluginmanager/BundleComparator.java @@ -37,8 +37,8 @@ public class BundleComparator implements Comparator */ public int compare(Bundle arg0, Bundle arg1) { - String n1 = (String) arg0.getHeaders().get(Constants.BUNDLE_NAME); - String n2 = (String) arg1.getHeaders().get(Constants.BUNDLE_NAME); + String n1 = arg0.getHeaders().get(Constants.BUNDLE_NAME); + String n2 = arg1.getHeaders().get(Constants.BUNDLE_NAME); if (n1 == null) { diff --git a/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java b/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java index b77bbbe..251052a 100644 --- a/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java +++ b/src/net/java/sip/communicator/plugin/skinmanager/BundleComparator.java @@ -38,8 +38,8 @@ public class BundleComparator */ public int compare(Bundle arg0, Bundle arg1) { - String n1 = (String) arg0.getHeaders().get(Constants.BUNDLE_NAME); - String n2 = (String) arg1.getHeaders().get(Constants.BUNDLE_NAME); + String n1 = arg0.getHeaders().get(Constants.BUNDLE_NAME); + String n2 = arg1.getHeaders().get(Constants.BUNDLE_NAME); if (n1 == null) { -- cgit v1.1 From d17512426ea790d7046b817b98c9fe8ce54e9322 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:49:32 +0100 Subject: Ignore all unknown MediaTypes --- .../communicator/impl/protocol/jabber/CallPeerJabberImpl.java | 8 +------- .../service/protocol/media/CallPeerMediaHandler.java | 11 +---------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java index 69af6ae..c257202 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java @@ -1588,16 +1588,10 @@ public class CallPeerJabberImpl { case AUDIO: return audioSenders; - case DATA: - /* - * FIXME DATA has been introduced as a MediaType but explicit - * support for DATA content has not been added yet. - */ - return SendersEnum.none; case VIDEO: return videoSenders; default: - throw new IllegalArgumentException("mediaType"); + return SendersEnum.none; } } diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java index de2d03a..c8a3a12 100644 --- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java +++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java @@ -622,10 +622,8 @@ public abstract class CallPeerMediaHandler> return audioDirectionUserPreference; case VIDEO: return videoDirectionUserPreference; - case DATA: - return MediaDirection.INACTIVE; default: - throw new IllegalArgumentException("mediaType"); + return MediaDirection.INACTIVE; } } @@ -1039,13 +1037,6 @@ public abstract class CallPeerMediaHandler> { case AUDIO: return audioStream; - case DATA: - /* - * DATA is a valid MediaType value and CallPeerMediaHandler does not - * utilize it at this time so no IllegalArgumentException is thrown - * and null is returned (as documented). - */ - return null; case VIDEO: return videoStream; default: -- cgit v1.1 From 1fb0c134342ad43da2d8217fbe81f0f5cf21ad7c Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:50:54 +0100 Subject: ZRTP: stop encryption processing if added to SDP --- .../sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java index 24c5f6f..b626dbb 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java @@ -1886,7 +1886,7 @@ public class CallPeerMediaHandlerSipImpl // ZRTP else if(srtpControlType == SrtpControlType.ZRTP) { - if(updateMediaDescriptionForZrtp(mediaType, localMd)); + if(updateMediaDescriptionForZrtp(mediaType, localMd)) { // Stop once an encryption advertisement has been chosen. return; -- cgit v1.1 From 0b278bf6748cb32b74c1731b83ebe1c0158bfaa7 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 7 Jan 2017 20:51:23 +0100 Subject: Use non-deprecated way to create FromFilter --- .../java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java index 1897b42..6c4c358 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java @@ -609,7 +609,7 @@ public class ChatRoomJabberImpl this.provider.getConnection().addPacketListener( presenceListener, new AndFilter( - new FromMatchesFilter(multiUserChat.getRoom()), + FromMatchesFilter.create(multiUserChat.getRoom()), new PacketTypeFilter( org.jivesoftware.smack.packet.Presence.class))); if(password == null) -- cgit v1.1 From 11d0c16f315806ed7cce19dfe235a1cd7823214f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 10 Jan 2017 02:04:00 +0100 Subject: Add support for AppIndicators See #192 Doesn't properly work on Debian because of outdated/mismatching GTK dependencies. Fixed in Ubuntu Launchpad bug #1203888, but not imported in Debian. See bug #850769. --- resources/install/debian/control-src.tmpl | 1 + resources/install/debian/control.tmpl | 1 + resources/install/rpm/SPECS/jitsi.spec | 9 +- .../impl/osdependent/jdic/StatusSubMenu.java | 15 +- .../osdependent/jdic/SystrayServiceJdicImpl.java | 79 ++- .../impl/osdependent/jdic/TrayMenuFactory.java | 21 +- .../impl/osdependent/osdependent.manifest.mf | 2 + .../impl/osdependent/systemtray/SystemTray.java | 36 ++ .../impl/osdependent/systemtray/TrayIcon.java | 2 +- .../systemtray/appindicator/AppIndicator1.java | 189 +++++++ .../systemtray/appindicator/AppIndicatorTray.java | 94 ++++ .../appindicator/AppIndicatorTrayIcon.java | 596 +++++++++++++++++++++ .../systemtray/appindicator/Gobject.java | 68 +++ .../osdependent/systemtray/appindicator/Gtk.java | 79 +++ .../osdependent/systemtray/awt/AWTSystemTray.java | 6 + .../osdependent/systemtray/awt/AWTTrayIcon.java | 21 +- 16 files changed, 1154 insertions(+), 65 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicator1.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java create mode 100644 src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java diff --git a/resources/install/debian/control-src.tmpl b/resources/install/debian/control-src.tmpl index fc677e2..cb9b08d 100644 --- a/resources/install/debian/control-src.tmpl +++ b/resources/install/debian/control-src.tmpl @@ -60,6 +60,7 @@ Depends: ${misc:Depends}, libjitsi (= ${libjitsi:version}), libjitsi-jni (= ${libjitsi:version}), default-jre | java7-runtime, + libappindicator1, libunixsocket-java, libhttpcore-java, liblog4j1.2-java, diff --git a/resources/install/debian/control.tmpl b/resources/install/debian/control.tmpl index a95fd02..b780bb4 100644 --- a/resources/install/debian/control.tmpl +++ b/resources/install/debian/control.tmpl @@ -59,6 +59,7 @@ Standards-Version: 3.9.5 Package: _PACKAGE_NAME_ Architecture: i386 amd64 Depends: default-jre | java7-runtime, + libappindicator1, libxss1, libspeex1, libspeexdsp1, diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index e896ddc..9449788 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -12,12 +12,13 @@ BuildRoot: %{_topdir}/buildroot AutoReqProv: no BuildRequires: java-devel >= 1:1.7 -Buildrequires: ant -Buildrequires: ant-nodeps -Buildrequires: gzip -Buildrequires: git +BuildRequires: ant +BuildRequires: ant-nodeps +BuildRequires: gzip +BuildRequires: git Requires: java >= 1:1.7 +Requires: libappindicator Requires: speex Requires: speexdsp diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/StatusSubMenu.java b/src/net/java/sip/communicator/impl/osdependent/jdic/StatusSubMenu.java index 2d77621..92088fa 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/StatusSubMenu.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/StatusSubMenu.java @@ -66,7 +66,7 @@ public class StatusSubMenu * @param swing true to represent this instance with a Swing * JMenu; false to use an AWT Menu */ - public StatusSubMenu(boolean swing) + public StatusSubMenu(boolean swing, boolean accountMenuSupported) { String text = Resources.getString("impl.systray.SET_STATUS"); @@ -86,6 +86,7 @@ public class StatusSubMenu this.menu = new Menu(text); } + if (accountMenuSupported) { String hideAccountStatusSelectorsProperty = "impl.gui.HIDE_ACCOUNT_STATUS_SELECTORS"; @@ -103,6 +104,10 @@ public class StatusSubMenu hideAccountStatusSelectorsProperty, hideAccountStatusSelectors); } + else + { + hideAccountStatusSelectors = true; + } PresenceStatus offlineStatus = null; // creates menu item entry for every global status @@ -116,9 +121,11 @@ public class StatusSubMenu // initially it is offline selectItemFromStatus(offlineStatus.getStatus()); - this.addSeparator(); - - addMenuItem(menu, new GlobalStatusMessageMenu(swing).getMenu()); + if (accountMenuSupported) + { + this.addSeparator(); + addMenuItem(menu, new GlobalStatusMessageMenu(swing).getMenu()); + } if(!hideAccountStatusSelectors) this.addSeparator(); diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index 6fd9d8c..fd9d43e 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -35,6 +35,7 @@ import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.service.systray.event.*; import net.java.sip.communicator.util.Logger; +import org.apache.commons.lang3.tuple.Pair; import org.jitsi.util.*; import org.osgi.framework.*; @@ -185,47 +186,34 @@ public class SystrayServiceJdicImpl return; } - menu = TrayMenuFactory.createTrayMenu(this, systray.useSwingPopupMenu()); + Pair createdMenu = TrayMenuFactory.createTrayMenu( + this, + systray.useSwingPopupMenu(), + systray.supportsDynamicMenu()); + menu = createdMenu.getLeft(); boolean isMac = OSUtils.IS_MAC; - // If we're running under Windows, we use a special icon without - // background. - if (OSUtils.IS_WINDOWS) - { - logoIcon = Resources.getImage("service.systray.TRAY_ICON_WINDOWS"); - logoIconOffline = Resources.getImage( - "service.systray.TRAY_ICON_WINDOWS_OFFLINE"); - logoIconAway = Resources.getImage( - "service.systray.TRAY_ICON_WINDOWS_AWAY"); - logoIconExtendedAway = Resources.getImage( - "service.systray.TRAY_ICON_WINDOWS_EXTENDED_AWAY"); - logoIconFFC = Resources.getImage( - "service.systray.TRAY_ICON_WINDOWS_FFC"); - logoIconDND = Resources.getImage( - "service.systray.TRAY_ICON_WINDOWS_DND"); - } - /* - * If we're running under Mac OS X, we use special black and white icons - * without background. - */ - else if (isMac) + logoIcon = Resources.getImage("service.systray.TRAY_ICON_WINDOWS"); + logoIconOffline = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_OFFLINE"); + logoIconAway = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_AWAY"); + logoIconExtendedAway = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_EXTENDED_AWAY"); + logoIconFFC = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_FFC"); + logoIconDND = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_DND"); + + // If we're running under Mac OS X, we use special black and white + // icons without background. + if (isMac) { logoIcon = Resources.getImage("service.systray.TRAY_ICON_MACOSX"); logoIconWhite = Resources.getImage( "service.systray.TRAY_ICON_MACOSX_WHITE"); } - else - { - logoIcon = Resources.getImage("service.systray.TRAY_ICON"); - logoIconOffline = Resources.getImage( - "service.systray.TRAY_ICON_OFFLINE"); - logoIconAway = Resources.getImage("service.systray.TRAY_ICON_AWAY"); - logoIconExtendedAway = Resources.getImage( - "service.systray.TRAY_ICON_EXTENDED_AWAY"); - logoIconFFC = Resources.getImage("service.systray.TRAY_ICON_FFC"); - logoIconDND = Resources.getImage("service.systray.TRAY_ICON_DND"); - } /* * Default to set offline , if any protocols become online will set it @@ -259,21 +247,15 @@ public class SystrayServiceJdicImpl } //Show/hide the contact list when user clicks on the systray. - trayIcon.addActionListener( - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - UIService uiService - = OsDependentActivator.getUIService(); - ExportedWindow mainWindow - = uiService.getExportedWindow( - ExportedWindow.MAIN_WINDOW); - boolean setIsVisible = !mainWindow.isVisible(); - - uiService.setVisible(setIsVisible); - } - }); + final Object defaultActionItem; + if (systray.useSwingPopupMenu()) + { + defaultActionItem = ((JMenuItem) createdMenu.getRight()); + } + else + { + defaultActionItem = ((MenuItem) createdMenu.getRight()); + } /* * Change the Mac OS X icon with the white one when the pop-up menu @@ -336,6 +318,7 @@ public class SystrayServiceJdicImpl public void run() { systray.addTrayIcon(trayIcon); + trayIcon.setDefaultAction(defaultActionItem); } }); diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java index c13a505..05fe771 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java @@ -26,6 +26,7 @@ import javax.swing.event.*; import net.java.sip.communicator.impl.osdependent.*; import net.java.sip.communicator.service.gui.*; +import org.apache.commons.lang3.tuple.*; import org.jitsi.util.*; /** @@ -139,12 +140,16 @@ public final class TrayMenuFactory * * @param tray the system tray for which we're creating a menu * @param swing indicates if we should create a Swing or an AWT menu - * @return a tray menu for the given system tray + * @return a tray menu for the given system tray (first) and the default + * menu item (second) */ - public static Object createTrayMenu(SystrayServiceJdicImpl tray, - boolean swing) + public static Pair createTrayMenu( + SystrayServiceJdicImpl tray, + boolean swing, + boolean accountMenuSupported + ) { - Object trayMenu = swing ? new JPopupMenu() : new PopupMenu(); + final Object trayMenu = swing ? new JPopupMenu() : new PopupMenu(); ActionListener listener = new ActionListener() { public void actionPerformed(ActionEvent event) @@ -182,7 +187,9 @@ public final class TrayMenuFactory if (!chatPresenceDisabled.booleanValue()) { - add(trayMenu, new StatusSubMenu(swing).getMenu()); + add( + trayMenu, + new StatusSubMenu(swing, accountMenuSupported).getMenu()); addSeparator(trayMenu); } @@ -197,9 +204,11 @@ public final class TrayMenuFactory showHideIconId = "service.gui.icons.SEARCH_ICON_16x16"; } else + { showHideName = "service.gui.SHOW"; showHideTextId = "service.gui.SHOW"; showHideIconId = "service.gui.icons.SEARCH_ICON_16x16"; + } final Object showHideMenuItem = createTrayMenuItem( showHideName, showHideTextId, @@ -241,7 +250,7 @@ public final class TrayMenuFactory } }); - return trayMenu; + return Pair.of(trayMenu, showHideMenuItem); } /** diff --git a/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf b/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf index bc56371..91f2791 100644 --- a/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf +++ b/src/net/java/sip/communicator/impl/osdependent/osdependent.manifest.mf @@ -27,6 +27,7 @@ Import-Package: com.apple.cocoa.application, net.java.sip.communicator.plugin.desktoputil.presence, javax.accessibility, javax.imageio, + javax.imageio.stream, javax.swing, javax.swing.border, javax.swing.event, @@ -39,6 +40,7 @@ Import-Package: com.apple.cocoa.application, javax.swing.text.html, javax.swing.tree, javax.swing.undo, + org.apache.commons.lang3.tuple, org.jitsi.service.configuration, org.jitsi.service.resources, org.jitsi.util, diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java index 125a190..eeffd29 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java @@ -19,13 +19,22 @@ package net.java.sip.communicator.impl.osdependent.systemtray; import javax.swing.*; +import org.jitsi.util.*; + +import net.java.sip.communicator.impl.osdependent.*; +import net.java.sip.communicator.impl.osdependent.systemtray.appindicator.*; import net.java.sip.communicator.impl.osdependent.systemtray.awt.*; +import net.java.sip.communicator.util.Logger; /** * Base class for all wrappers of SystemTray implementations. */ public abstract class SystemTray { + private static final String PNMAE_DISABLE_TRY = + "net.java.sip.communicator.osdependent.systemtray.DISABLE"; + + private static final Logger logger = Logger.getLogger(SystemTray.class); private static SystemTray systemTray; /** @@ -34,8 +43,28 @@ public abstract class SystemTray */ public final static SystemTray getSystemTray() { + boolean disable = OsDependentActivator.getConfigurationService() + .getBoolean(PNMAE_DISABLE_TRY, false); + if (disable) + { + return null; + } + if (systemTray == null) { + if (OSUtils.IS_LINUX) + { + try + { + systemTray = new AppIndicatorTray(); + return systemTray; + } + catch(Exception ex) + { + logger.info(ex.getMessage()); + } + } + if (java.awt.SystemTray.isSupported()) { systemTray = new AWTSystemTray(); @@ -75,4 +104,11 @@ public abstract class SystemTray * PopupMenu */ public abstract boolean useSwingPopupMenu(); + + /** + * Determines if the tray icon supports dynamic menus. + * + * @return True if the menu can be changed while running, false otherwise. + */ + public abstract boolean supportsDynamicMenu(); } diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java index 39fa6bd..78df44c 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/TrayIcon.java @@ -29,7 +29,7 @@ import javax.swing.*; */ public interface TrayIcon { - public void addActionListener(ActionListener listener); + public void setDefaultAction(Object menuItem); public void addBalloonActionListener(ActionListener listener); diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicator1.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicator1.java new file mode 100644 index 0000000..85fbd73 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicator1.java @@ -0,0 +1,189 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.*; + +/** + * JNA mappings for libappindicator1. + * + * @author Ingo Bauersachs + */ +interface AppIndicator1 extends Library +{ + static final AppIndicator1 INSTANCE = + (AppIndicator1) Native.loadLibrary("appindicator", AppIndicator1.class); + + static final String APP_INDICATOR_SIGNAL_NEW_ICON = "new-icon"; + static final String APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON = "new-attention-icon"; + static final String APP_INDICATOR_SIGNAL_NEW_STATUS = "new-status"; + static final String APP_INDICATOR_SIGNAL_NEW_LABEL = "new-label"; + static final String APP_INDICATOR_SIGNAL_CONNECTION_CHANGED = "connection-changed"; + static final String APP_INDICATOR_SIGNAL_NEW_ICON_THEME_PATH = "new-icon-theme-path"; + static final String APP_INDICATOR_SIGNAL_SCROLL_EVENT = "scroll-event"; + + /** + * The category provides grouping for the indicators so that users can find + * indicators that are similar together. + */ + enum APP_INDICATOR_CATEGORY + { + /** The indicator is used to display the status of the application. */ + APPLICATION_STATUS, + + /** The application is used for communication with other people. */ + COMMUNICATIONS, + + /** A system indicator relating to something in the user's system. */ + SYSTEM_SERVICES, + + /** An indicator relating to the user's hardware. */ + HARDWARE, + + /** + * Something not defined in this enum, please don't use unless you + * really need it. + */ + OTHER + } + + /** + * These are the states that the indicator can be on in the user's panel. + * The indicator by default starts in the state {@link #PASSIVE} and can be + * shown by setting it to {@link #ACTIVE}. + */ + enum APP_INDICATOR_STATUS + { + /** The indicator should not be shown to the user. */ + PASSIVE, + + /** The indicator should be shown in it's default state. */ + ACTIVE, + + /** The indicator should show it's attention icon. */ + ATTENTION + } + + class AppIndicatorClass extends Structure + { + // Parent + public /*Gobject.GObjectClass*/ Pointer parent_class; + + // DBus Signals + public Pointer new_icon; + public Pointer new_attention_icon; + public Pointer new_status; + public Pointer new_icon_theme_path; + public Pointer new_label; + + // Local Signals + public Pointer connection_changed; + public Pointer scroll_event; + public Pointer app_indicator_reserved_ats; + + // Overridable Functions + public Pointer fallback; + public Pointer unfallback; + + // Reserved + public Pointer app_indicator_reserved_1; + public Pointer app_indicator_reserved_2; + public Pointer app_indicator_reserved_3; + public Pointer app_indicator_reserved_4; + public Pointer app_indicator_reserved_5; + public Pointer app_indicator_reserved_6; + + @Override + protected List getFieldOrder() { + return Arrays.asList( + "parent_class", + "new_icon", + "new_attention_icon", + "new_status", + "new_icon_theme_path", + "new_label", + + "connection_changed", + "scroll_event", + "app_indicator_reserved_ats", + + "fallback", + "unfallback", + + "app_indicator_reserved_1", + "app_indicator_reserved_2", + "app_indicator_reserved_3", + "app_indicator_reserved_4", + "app_indicator_reserved_5", + "app_indicator_reserved_6"); + } + } + + class AppIndicator extends Structure + { + public /*Gobject.GObject*/ Pointer parent; + public Pointer priv; + + @Override + protected List getFieldOrder() + { + return Arrays.asList("parent", "priv"); + } + } + + // GObject Stuff + NativeLong app_indicator_get_type(); + AppIndicator app_indicator_new(String id, String icon_name, int category); + AppIndicator app_indicator_new_with_path(String id, String icon_name, int category, String icon_theme_path); + + // Set properties + void app_indicator_set_status(AppIndicator self, int status); + void app_indicator_set_attention_icon(AppIndicator self, String icon_name); + void app_indicator_set_attention_icon_full(AppIndicator self, String name, String icon_desc); + void app_indicator_set_menu(AppIndicator self, Pointer menu); + void app_indicator_set_icon(AppIndicator self, String icon_name); + void app_indicator_set_icon_full(AppIndicator self, String icon_name, String icon_desc); + void app_indicator_set_label(AppIndicator self, String label, String guide); + void app_indicator_set_icon_theme_path(AppIndicator self, String icon_theme_path); + void app_indicator_set_ordering_index(AppIndicator self, int ordering_index); + void app_indicator_set_secondary_activate_target(AppIndicator self, Pointer menuitem); + void app_indicator_set_title(AppIndicator self, String title); + + // Get properties + String app_indicator_get_id(AppIndicator self); + int app_indicator_get_category(AppIndicator self); + int app_indicator_get_status(AppIndicator self); + String app_indicator_get_icon(AppIndicator self); + String app_indicator_get_icon_desc(AppIndicator self); + String app_indicator_get_icon_theme_path(AppIndicator self); + String app_indicator_get_attention_icon(AppIndicator self); + String app_indicator_get_attention_icon_desc(AppIndicator self); + String app_indicator_get_title(AppIndicator self); + + Pointer app_indicator_get_menu(AppIndicator self); + String app_indicator_get_label(AppIndicator self); + String app_indicator_get_label_guide(AppIndicator self); + int app_indicator_get_ordering_index(AppIndicator self); + Pointer app_indicator_get_secondary_activate_target(AppIndicator self, Pointer widget); + + // Helpers + void app_indicator_build_menu_from_desktop(AppIndicator self, String desktop_file, String destkop_profile); +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java new file mode 100644 index 0000000..3f4e267 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java @@ -0,0 +1,94 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; + +import javax.swing.*; + +import org.jitsi.util.*; + +import net.java.sip.communicator.impl.osdependent.*; +import net.java.sip.communicator.impl.osdependent.systemtray.*; +import net.java.sip.communicator.util.*; + +/** + * Jitsi system tray abstraction for libappindicator. + * + * @author Ingo Bauersachs + */ +public class AppIndicatorTray extends SystemTray +{ + private static final String PNMAE_APPINDICATOR_DISABLED = + "net.java.sip.communicator.osdependent.systemtray.appindicator.DISABLED"; + private static final String PNMAE_APPINDICATOR_DYNAMIC_MENU = + "net.java.sip.communicator.osdependent.systemtray.appindicator.DYNAMIC_MENU"; + + public AppIndicatorTray() throws Exception + { + boolean disable = OsDependentActivator.getConfigurationService() + .getBoolean(PNMAE_APPINDICATOR_DISABLED, false); + if (disable) + { + throw new Exception("AppIndicator is disabled"); + } + + if (!OSUtils.IS_LINUX) + { + throw new Exception("Not running Linux, AppIndicator1 is not available"); + } + + try + { + // pre-initialize the JNA libraries before attempting to use them + AppIndicator1.INSTANCE.toString(); + Gtk.INSTANCE.toString(); + Gobject.INSTANCE.toString(); + Gtk.INSTANCE.gtk_init(0, null); + } + catch (Throwable t) + { + throw new Exception("AppIndicator1 tray icon not available", t); + } + } + + @Override + public void addTrayIcon(TrayIcon trayIcon) + { + ((AppIndicatorTrayIcon) trayIcon).createTray(); + } + + @Override + public TrayIcon createTrayIcon(ImageIcon icon, String tooltip, Object popup) + { + + return new AppIndicatorTrayIcon(icon, tooltip, (JPopupMenu) popup); + } + + @Override + public boolean useSwingPopupMenu() + { + // we want icons + return true; + } + + @Override + public boolean supportsDynamicMenu() + { + return OsDependentActivator.getConfigurationService() + .getBoolean(PNMAE_APPINDICATOR_DYNAMIC_MENU, true); + } +} diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java new file mode 100644 index 0000000..8779312 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java @@ -0,0 +1,596 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; + +import java.awt.*; +import java.awt.TrayIcon.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.beans.*; +import java.io.*; +import java.net.*; +import java.nio.file.*; +import java.util.*; +import java.util.List; +import java.util.Timer; + +import javax.accessibility.*; +import javax.imageio.*; +import javax.imageio.stream.*; +import javax.print.attribute.standard.*; +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import org.jitsi.util.*; +import org.jitsi.util.Logger; + +import com.sun.jna.*; + +import net.java.sip.communicator.impl.osdependent.*; +import net.java.sip.communicator.impl.osdependent.systemtray.*; +import net.java.sip.communicator.impl.osdependent.systemtray.TrayIcon; +import net.java.sip.communicator.impl.osdependent.systemtray.appindicator.Gobject.*; +import net.java.sip.communicator.util.*; + +/** + * System tray icon implementation based on libappindicator1. + * + * @author Ingo Bauersachs + */ +class AppIndicatorTrayIcon implements TrayIcon +{ + private static final Logger logger = + Logger.getLogger(AppIndicatorTrayIcon.class); + + // shortcuts + private static Gobject gobject = Gobject.INSTANCE; + private static Gtk gtk = Gtk.INSTANCE; + private static AppIndicator1 ai = AppIndicator1.INSTANCE; + + // references to the root menu and the native icon + private ImageIcon mainIcon; + private String title; + private JPopupMenu popup; + private Map extractedFiles = new HashMap<>(); + private PopupMenuPeer popupPeer; + private AppIndicator1.AppIndicator appIndicator; + + public AppIndicatorTrayIcon(ImageIcon mainIcon, String title, + JPopupMenu popup) + { + this.mainIcon = mainIcon; + this.title = title; + this.popup = popup; + this.popupPeer = null; + } + + /** + * Combines the references of each swing menu item with the GTK counterpart + */ + private class PopupMenuPeer implements ContainerListener + { + public PopupMenuPeer(PopupMenuPeer parent, Component em) + { + menuItem = em; + + // if this menu item is a submenu, add ourselves as listener to + // add or remove the native counterpart + if (em instanceof JMenu) + { + ((JMenu)em).getPopupMenu().addContainerListener(this); + ((JMenu)em).addContainerListener(this); + } + } + + public List children = new ArrayList<>(); + public Pointer gtkMenuItem; + public Pointer gtkMenu; + public Pointer gtkImage; + public Memory gtkImageBuffer; + public Pointer gtkPixbuf; + public Component menuItem; + public MenuItemSignalHandler signalHandler; + + @Override + public void componentAdded(ContainerEvent e) + { + AppIndicatorTrayIcon.this.printMenu(popup.getComponents(), 1); + gtk.gdk_threads_enter(); + createGtkMenuItems(this, new Component[]{e.getChild()}); + gtk.gtk_widget_show_all(popupPeer.gtkMenu); + gtk.gdk_threads_leave(); + } + + @Override + public void componentRemoved(ContainerEvent e) + { + AppIndicatorTrayIcon.this.printMenu(popup.getComponents(), 1); + for (PopupMenuPeer c : children) + { + if (c.menuItem == e.getChild()) + { + gtk.gdk_threads_enter(); + gtk.gtk_widget_destroy(c.gtkMenuItem); + gtk.gdk_threads_leave(); + cleanMenu(c); + break; + } + } + } + } + + public void createTray() + { + appIndicator = ai.app_indicator_new( + "jitsi", + "indicator-messages-new", + AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal()); + + ai.app_indicator_set_title(appIndicator, title); + setupGtkMenu(); + + String path = imageIconToPath(mainIcon); + if (path != null) + { + ai.app_indicator_set_icon_full(appIndicator, path, "Jitsi"); + } + + ai.app_indicator_set_status( + appIndicator, + AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal()); + + new Thread() + { + public void run() + { + gtk.gtk_main(); + } + }.start(); + } + + private void setupGtkMenu() + { + // create root menu + popupPeer = new PopupMenuPeer(null, popup); + popupPeer.gtkMenu = gtk.gtk_menu_new(); + + // transfer everything in the swing menu to the gtk menu + createGtkMenuItems(popupPeer, popup.getComponents()); + gtk.gtk_widget_show_all(popupPeer.gtkMenu); + + // attach the menu to the indicator + ai.app_indicator_set_menu(appIndicator, popupPeer.gtkMenu); + } + + private void cleanMenu(PopupMenuPeer peer) + { + for (PopupMenuPeer p : peer.children) + { + cleanMenu(p); + } + + // - the root menu is released when it's unset from the indicator + // - gtk auto-frees menu item, submenu, image, and pixbuf + // - the imagebuffer was jna allocated, GC should take care of freeing + peer.gtkImageBuffer = null; + removeListeners(peer); + } + + private void removeListeners(PopupMenuPeer peer) + { + if (peer.menuItem instanceof JMenu) + { + ((JMenu)peer.menuItem).removeContainerListener(peer); + ((JMenu)peer.menuItem).getPopupMenu().removeContainerListener(peer); + } + + for (PopupMenuPeer p : peer.children) + { + removeListeners(p); + } + } + + private void createGtkMenuItems( + PopupMenuPeer parent, + Component[] components) + { + for (Component em : components) + { + logger.debug("Creating item for " + em.getClass().getName()); + PopupMenuPeer peer = new PopupMenuPeer(parent, em); + if (em instanceof JPopupMenu.Separator) + { + peer.gtkMenuItem = gtk.gtk_separator_menu_item_new(); + } + + if (em instanceof JMenuItem) + { + JMenuItem m = (JMenuItem)em; + logger.debug(" title: " + m.getText()); + createGtkMenuItem(peer); + } + + if (em instanceof JMenu && peer.gtkMenuItem != null) + { + JMenu m = (JMenu)em; + logger.debug("Creating submenu on " + m.getText()); + peer.gtkMenu = gtk.gtk_menu_new(); + createGtkMenuItems(peer, m.getMenuComponents()); + gtk.gtk_menu_item_set_submenu(peer.gtkMenuItem, peer.gtkMenu); + } + + if (peer.gtkMenuItem != null) + { + parent.children.add(peer); + gtk.gtk_menu_shell_append(parent.gtkMenu, peer.gtkMenuItem); + } + } + } + + private void createGtkMenuItem(PopupMenuPeer peer) + { + JMenuItem m = (JMenuItem)peer.menuItem; + if (m instanceof JCheckBoxMenuItem) + { + peer.gtkMenuItem = gtk.gtk_check_menu_item_new_with_label( + m.getText()); + JCheckBoxMenuItem cb = (JCheckBoxMenuItem)m; + gtk.gtk_check_menu_item_set_active( + peer.gtkMenuItem, + cb.isSelected() ? 1 : 0); + } + else + { + peer.gtkMenuItem = gtk.gtk_image_menu_item_new_with_label( + m.getText()); + if (m.getIcon() instanceof ImageIcon) + { + ImageIcon ii = ((ImageIcon) m.getIcon()); + imageIconToGtkWidget(peer, ii); + if (peer.gtkImage != null) + { + gtk.gtk_image_menu_item_set_image( + peer.gtkMenuItem, + peer.gtkImage); + gtk.gtk_image_menu_item_set_always_show_image( + peer.gtkMenuItem, + 1); + } + } + } + + if (peer.gtkMenuItem == null) + { + logger.debug("Could not create menu item for " + m.getText()); + return; + } + + MenuItemChangeListener micl = new MenuItemChangeListener(peer); + m.addPropertyChangeListener(micl); + m.addChangeListener(micl); + + // skip GTK events if it's a submenu + if (!(m instanceof JMenu)) + { + gtk.gtk_widget_set_sensitive( + peer.gtkMenuItem, + m.isEnabled() ? 1 : 0); + peer.signalHandler = new MenuItemSignalHandler(peer); + gobject.g_signal_connect_data( + peer.gtkMenuItem, + "activate", + peer.signalHandler, + null, + null, + 0); + } + } + + private String imageIconToPath(ImageIcon ii) + { + if (ii.getDescription() != null) + { + String path = extractedFiles.get(ii.getDescription()); + if (path != null) + { + return path; + } + } + + try + { + File f = File.createTempFile("jitsi-appindicator", ".png"); + f.deleteOnExit(); + try (FileImageOutputStream fios = new FileImageOutputStream(f)) + { + if (!ImageIO.write(getBufferedImage(ii), "png", fios)) + { + return null; + } + + if (ii.getDescription() != null) + { + extractedFiles.put( + ii.getDescription(), + f.getAbsolutePath()); + } + + return f.getAbsolutePath(); + } + } + catch (IOException e) + { + logger.debug("Failed to extract image: " + ii.getDescription(), e); + } + + return null; + } + + BufferedImage getBufferedImage(ImageIcon ii) + { + Image img = ii.getImage(); + if (img == null) + { + return null; + } + + if (img instanceof BufferedImage) + { + return (BufferedImage) img; + } + + BufferedImage bi = new BufferedImage( + img.getWidth(null), + img.getHeight(null), + BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.createGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + return bi; + } + + private void imageIconToGtkWidget(PopupMenuPeer peer, ImageIcon ii) + { + BufferedImage bi = getBufferedImage(ii); + if (bi == null) + { + return; + } + + int[] pixels = bi.getRGB( + 0, + 0, + bi.getWidth(), + bi.getHeight(), + null, + 0, + bi.getWidth()); + + peer.gtkImageBuffer = new Memory(pixels.length * 4); + for (int i = 0; i < pixels.length; i++) + { + // convert from argb (big endian) -> rgba (little endian) => abgr + peer.gtkImageBuffer.setInt(i * 4, (pixels[i] & 0xFF000000) | + (pixels[i] << 16) | + (pixels[i] & 0xFF00) | + (pixels[i] >>> 16 & 0xFF)); + } + + peer.gtkPixbuf = gtk.gdk_pixbuf_new_from_data( + peer.gtkImageBuffer, + 0, + 1, + 8, + bi.getWidth(), + bi.getHeight(), + bi.getWidth() * 4, + null, + null); + peer.gtkImage = gtk.gtk_image_new_from_pixbuf(peer.gtkPixbuf); + + // Now that the image ref's the buffer, we can release our own ref and + // the buffer will be free'd along with the image + gobject.g_object_unref(peer.gtkPixbuf); + } + + private static class MenuItemChangeListener + implements PropertyChangeListener, ChangeListener + { + private PopupMenuPeer peer; + private JMenuItem menu; + + public MenuItemChangeListener(PopupMenuPeer peer) + { + this.peer = peer; + this.menu = (JMenuItem)peer.menuItem; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) + { + if (logger.isDebugEnabled()) + { + logger.debug(menu.getText() + "::" + evt); + } + + switch (evt.getPropertyName()) + { + case JMenuItem.TEXT_CHANGED_PROPERTY: + gtk.gdk_threads_enter(); + gtk.gtk_menu_item_set_label( + peer.gtkMenuItem, + evt.getNewValue().toString()); + gtk.gdk_threads_leave(); + break; +// case JMenuItem.ICON_CHANGED_PROPERTY: +// gtk.gtk_image_menu_item_set_image(gtkMenuItem, image); +// break; + case AccessibleContext.ACCESSIBLE_STATE_PROPERTY: + gtk.gtk_widget_set_sensitive( + peer.gtkMenuItem, + AccessibleState.ENABLED.equals(evt.getNewValue()) ? 1 : 0); + break; + } + } + + @Override + public void stateChanged(ChangeEvent e) + { + logger.debug(menu.getText() + " -> " + menu.isSelected()); + gtk.gdk_threads_enter(); + gtk.gtk_check_menu_item_set_active( + peer.gtkMenuItem, + menu.isSelected() ? 1 : 0); + gtk.gdk_threads_leave(); + } + } + + private static class MenuItemSignalHandler + implements SignalHandler, Runnable + { + private PopupMenuPeer peer; + + MenuItemSignalHandler(PopupMenuPeer peer) + { + this.peer = peer; + } + + @Override + public void signal(Pointer widget, Pointer data) + { + SwingUtilities.invokeLater(this); + } + + @Override + public void run() + { + JMenuItem menu = (JMenuItem)peer.menuItem; + if (menu instanceof JCheckBoxMenuItem) + { + // Ignore GTK callback events if the menu state is + // already the same. Setting the selected state on the + // GTK sends the "activate" event, and would cause + // a loop + if (menu.isSelected() == isGtkSelected()) + { + return; + } + } + + for (ActionListener l : menu.getActionListeners()) + { + logger.debug("Invoking " + l + " on " + menu.getText()); + l.actionPerformed(new ActionEvent(menu, 0, "activate")); + } + } + + private boolean isGtkSelected() + { + return (gtk.gtk_check_menu_item_get_active(peer.gtkMenuItem) == 1); + } + } + + @Override + public void setDefaultAction(Object menuItem) + { + Pointer gtkMenuItem = findMenuItem(popupPeer, menuItem); + if (gtkMenuItem != null) + { + ai.app_indicator_set_secondary_activate_target( + appIndicator, + gtkMenuItem); + } + } + + private Pointer findMenuItem(PopupMenuPeer peer, Object menuItem) + { + if (peer.menuItem == menuItem) + { + return peer.gtkMenuItem; + } + + for (PopupMenuPeer p : peer.children) + { + Pointer found = findMenuItem(p, menuItem); + if (found != null) + { + return found; + } + } + + return null; + } + + @Override + public void addBalloonActionListener(ActionListener listener) + { + // not supported + } + + @Override + public void displayMessage(String caption, String text, + MessageType messageType) + { + // not supported + } + + @Override + public void setIcon(ImageIcon icon) throws NullPointerException + { + ai.app_indicator_set_icon_full( + appIndicator, + imageIconToPath(icon), + "Jitsi"); + } + + @Override + public void setIconAutoSize(boolean autoSize) + { + // nothing to do + } + + private void printMenu(Component[] components, int indent) + { + if (!logger.isDebugEnabled()) + { + return; + } + + String p = String.format("%0" + indent * 4 + "d", 0).replace('0', ' '); + for (Component em : components) + { + if (em instanceof JPopupMenu.Separator) + { + logger.debug(p + "-----------------------"); + } + + if (em instanceof JMenuItem) + { + JMenuItem m = (JMenuItem) em; + logger.debug(p + em.getClass().getName() + ": " + m.getText()); + } + + if (em instanceof JMenu) + { + JMenu m = (JMenu) em; + printMenu(m.getMenuComponents(), indent + 1); + } + } + } +}; \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java new file mode 100644 index 0000000..8a2349e --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java @@ -0,0 +1,68 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; + +import java.util.*; + +import com.sun.jna.*; + +/** + * JNA mappings for GTK GObject types that are required for the tray menu. + * + * @author Ingo Bauersachs + */ +interface Gobject extends Library +{ + static final Gobject INSTANCE = + (Gobject) Native.loadLibrary("gobject-2.0", Gobject.class); + + interface SignalHandler extends Callback + { + void signal(Pointer widget, Pointer data); + } + + /** + * Connects a GCallback function to a signal for a particular object. + * Similar to g_signal_connect(), but allows to provide a GClosureNotify for + * the data which will be called when the signal handler is disconnected and + * no longer used. Specify connect_flags if you need ..._after() or + * ..._swapped() variants of this function. + * + * @param instance the instance to connect to. + * @param detailed_signal a string of the form "signal-name::detail". + * @param c_handler the GCallback to connect. + * @param data data to pass to c_handler calls. + * @param destroy_data a GClosureNotify for data. + * @param connect_flags a combination of GConnectFlags. + */ + void g_signal_connect_data(Pointer instance, String detailed_signal, + SignalHandler c_handler, Pointer data, Pointer destroy_data, + int connect_flags); + + /** + * Decreases the reference count of object. When its reference count drops + * to 0, the object is finalized (i.e. its memory is freed). If the pointer + * to the GObject may be reused in future (for example, if it is an instance + * variable of another object), it is recommended to clear the pointer to + * NULL rather than retain a dangling pointer to a potentially invalid + * GObject instance. Use g_clear_object() for this. + * + * @param object a GObject. + */ + void g_object_unref(Pointer object); +} diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java new file mode 100644 index 0000000..7b74428 --- /dev/null +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java @@ -0,0 +1,79 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Copyright @ 2015 Atlassian Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; + +import com.sun.jna.*; + +/** + * JNA mappings for the gtk2 library. Only functions required for the try menu + * are defined. + * + * @author Ingo Bauersachs + */ +interface Gtk extends Library +{ + static final Gtk INSTANCE = + (Gtk) Native.loadLibrary("gtk-x11-2.0", Gtk.class); + + public enum GtkIconSize + { + INVALID, + MENU, + SMALL_TOOLBAR, + LARGE_TOOLBAR, + BUTTON, + DND, + DIALOG + } + + void gtk_init(int argc, String[] argv); + void gtk_main(); + Pointer gtk_menu_new(); + Pointer gtk_menu_item_new(); + Pointer gtk_menu_item_new_with_label(String label); + Pointer gtk_image_menu_item_new_with_mnemonic(String label); + Pointer gtk_image_menu_item_new_with_label(String label); + Pointer gtk_image_new_from_gicon(Pointer icon, int size); + Pointer gtk_image_new_from_stock(String stock_id, int size); + Pointer gtk_image_new_from_icon_name(String icon_name, int size); + Pointer gtk_image_new_from_file(String filename); + Pointer gtk_separator_menu_item_new(); + void gtk_menu_item_set_submenu(Pointer menu_item, Pointer submenu); + void gtk_image_menu_item_set_image(Pointer image_menu_item, Pointer image); + void gtk_image_menu_item_set_always_show_image(Pointer image_menu_item, int always_show); + void gtk_menu_item_set_label(Pointer menu_item, String label); + void gtk_menu_shell_append(Pointer menu_shell, Pointer child); + void gtk_widget_set_sensitive(Pointer widget, int sesitive); + void gtk_widget_show_all(Pointer widget); + //void gtk_container_remove(Pointer container, Pointer widget); + void gtk_widget_destroy(Pointer widget); + void gtk_widget_show(Pointer widget); + Pointer gtk_check_menu_item_new_with_label(String label); + int gtk_check_menu_item_get_active(Pointer check_menu_item); + void gtk_check_menu_item_set_active(Pointer check_menu_item, int is_active); + + Pointer g_file_new_for_uri(String uri); + Pointer g_file_icon_new(Pointer file); + void gdk_threads_enter(); + void gdk_threads_leave(); + + Pointer gdk_pixbuf_new_from_data(Pointer data, int colorspace, int has_alpha, + int bits_per_sample, int width, int height, int rowstride, + Pointer destroy_fn, Pointer destroy_fn_data); + Pointer gtk_image_new_from_pixbuf(Pointer pixbuf); +} diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java index 2fa25b3..1f211c7 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTSystemTray.java @@ -69,4 +69,10 @@ public class AWTSystemTray // enable swing for Java 1.6 except for the mac version return !OSUtils.IS_MAC; } + + @Override + public boolean supportsDynamicMenu() + { + return true; + } } \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java index 54d97ec..0aef71b 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java @@ -63,9 +63,26 @@ public class AWTTrayIcon } } - public void addActionListener(ActionListener listener) + public void setDefaultAction(Object menuItem) { - impl.addActionListener(listener); + ActionListener[] listeners; + if (menuItem instanceof JMenuItem) + { + listeners = ((JMenuItem) menuItem).getActionListeners(); + } + else if (menuItem instanceof MenuItem) + { + listeners = ((MenuItem) menuItem).getActionListeners(); + } + else + { + return; + } + + for (ActionListener l : listeners) + { + impl.addActionListener(l); + } } public void addBalloonActionListener(ActionListener listener) -- cgit v1.1 From 59c28f3b0eed75ed0f88bcda00f379906c3d00c9 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 10 Jan 2017 10:01:21 +0100 Subject: Ignore SystemTray when running in headless mode --- .../java/sip/communicator/impl/osdependent/systemtray/SystemTray.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java index eeffd29..74baa16 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.impl.osdependent.systemtray; +import java.awt.*; + import javax.swing.*; import org.jitsi.util.*; @@ -45,7 +47,7 @@ public abstract class SystemTray { boolean disable = OsDependentActivator.getConfigurationService() .getBoolean(PNMAE_DISABLE_TRY, false); - if (disable) + if (disable || GraphicsEnvironment.isHeadless()) { return null; } -- cgit v1.1 From 56944196405c61da3e407cbaa4e4a76017ac43d2 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 00:32:32 +0100 Subject: AppIndicator logging and clean up --- .../appindicator/AppIndicatorTrayIcon.java | 114 +++++++++++++-------- .../systemtray/appindicator/Gobject.java | 16 ++- .../osdependent/systemtray/appindicator/Gtk.java | 13 +-- 3 files changed, 88 insertions(+), 55 deletions(-) diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java index 8779312..a5bbee1 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java @@ -106,15 +106,22 @@ class AppIndicatorTrayIcon implements TrayIcon public Pointer gtkPixbuf; public Component menuItem; public MenuItemSignalHandler signalHandler; + public long gtkSignalHandler; @Override public void componentAdded(ContainerEvent e) { AppIndicatorTrayIcon.this.printMenu(popup.getComponents(), 1); gtk.gdk_threads_enter(); - createGtkMenuItems(this, new Component[]{e.getChild()}); - gtk.gtk_widget_show_all(popupPeer.gtkMenu); - gtk.gdk_threads_leave(); + try + { + createGtkMenuItems(this, new Component[]{e.getChild()}); + gtk.gtk_widget_show_all(popupPeer.gtkMenu); + } + finally + { + gtk.gdk_threads_leave(); + } } @Override @@ -126,9 +133,16 @@ class AppIndicatorTrayIcon implements TrayIcon if (c.menuItem == e.getChild()) { gtk.gdk_threads_enter(); - gtk.gtk_widget_destroy(c.gtkMenuItem); - gtk.gdk_threads_leave(); - cleanMenu(c); + try + { + cleanMenu(c); + } + finally + { + gtk.gdk_threads_leave(); + } + + children.remove(c); break; } } @@ -137,20 +151,16 @@ class AppIndicatorTrayIcon implements TrayIcon public void createTray() { - appIndicator = ai.app_indicator_new( + File iconFile = new File(imageIconToPath(mainIcon)); + appIndicator = ai.app_indicator_new_with_path( "jitsi", - "indicator-messages-new", - AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal()); + iconFile.getName().replaceFirst("[.][^.]+$", ""), + AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal(), + iconFile.getParent()); ai.app_indicator_set_title(appIndicator, title); setupGtkMenu(); - String path = imageIconToPath(mainIcon); - if (path != null) - { - ai.app_indicator_set_icon_full(appIndicator, path, "Jitsi"); - } - ai.app_indicator_set_status( appIndicator, AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal()); @@ -180,6 +190,7 @@ class AppIndicatorTrayIcon implements TrayIcon private void cleanMenu(PopupMenuPeer peer) { + logger.debug("Clean requested for: " + peer.menuItem); for (PopupMenuPeer p : peer.children) { cleanMenu(p); @@ -188,22 +199,20 @@ class AppIndicatorTrayIcon implements TrayIcon // - the root menu is released when it's unset from the indicator // - gtk auto-frees menu item, submenu, image, and pixbuf // - the imagebuffer was jna allocated, GC should take care of freeing - peer.gtkImageBuffer = null; - removeListeners(peer); - } + if (peer.gtkSignalHandler > 0) + { + gobject.g_signal_handler_disconnect( + peer.gtkMenuItem, + peer.gtkSignalHandler); + } - private void removeListeners(PopupMenuPeer peer) - { + gtk.gtk_widget_destroy(peer.gtkMenuItem); + peer.gtkImageBuffer = null; if (peer.menuItem instanceof JMenu) { ((JMenu)peer.menuItem).removeContainerListener(peer); ((JMenu)peer.menuItem).getPopupMenu().removeContainerListener(peer); } - - for (PopupMenuPeer p : peer.children) - { - removeListeners(p); - } } private void createGtkMenuItems( @@ -212,17 +221,15 @@ class AppIndicatorTrayIcon implements TrayIcon { for (Component em : components) { - logger.debug("Creating item for " + em.getClass().getName()); PopupMenuPeer peer = new PopupMenuPeer(parent, em); if (em instanceof JPopupMenu.Separator) { + logger.debug("Creating separator"); peer.gtkMenuItem = gtk.gtk_separator_menu_item_new(); } if (em instanceof JMenuItem) { - JMenuItem m = (JMenuItem)em; - logger.debug(" title: " + m.getText()); createGtkMenuItem(peer); } @@ -246,6 +253,8 @@ class AppIndicatorTrayIcon implements TrayIcon private void createGtkMenuItem(PopupMenuPeer peer) { JMenuItem m = (JMenuItem)peer.menuItem; + logger.debug("Creating item for " + m.getClass().getName() + ": " + + m.getText()); if (m instanceof JCheckBoxMenuItem) { peer.gtkMenuItem = gtk.gtk_check_menu_item_new_with_label( @@ -292,13 +301,14 @@ class AppIndicatorTrayIcon implements TrayIcon peer.gtkMenuItem, m.isEnabled() ? 1 : 0); peer.signalHandler = new MenuItemSignalHandler(peer); - gobject.g_signal_connect_data( + peer.gtkSignalHandler = gobject.g_signal_connect_data( peer.gtkMenuItem, "activate", peer.signalHandler, null, null, 0); + logger.debug("Signal for " + ((JMenuItem)m).getText() + " is " + peer.gtkSignalHandler); } } @@ -426,17 +436,24 @@ class AppIndicatorTrayIcon implements TrayIcon { if (logger.isDebugEnabled()) { - logger.debug(menu.getText() + "::" + evt); + logger.debug(menu.getText() + "::" + evt.getPropertyName()); } switch (evt.getPropertyName()) { case JMenuItem.TEXT_CHANGED_PROPERTY: gtk.gdk_threads_enter(); - gtk.gtk_menu_item_set_label( - peer.gtkMenuItem, - evt.getNewValue().toString()); - gtk.gdk_threads_leave(); + try + { + gtk.gtk_menu_item_set_label( + peer.gtkMenuItem, + evt.getNewValue().toString()); + } + finally + { + gtk.gdk_threads_leave(); + } + break; // case JMenuItem.ICON_CHANGED_PROPERTY: // gtk.gtk_image_menu_item_set_image(gtkMenuItem, image); @@ -454,10 +471,16 @@ class AppIndicatorTrayIcon implements TrayIcon { logger.debug(menu.getText() + " -> " + menu.isSelected()); gtk.gdk_threads_enter(); - gtk.gtk_check_menu_item_set_active( - peer.gtkMenuItem, - menu.isSelected() ? 1 : 0); - gtk.gdk_threads_leave(); + try + { + gtk.gtk_check_menu_item_set_active( + peer.gtkMenuItem, + menu.isSelected() ? 1 : 0); + } + finally + { + gtk.gdk_threads_leave(); + } } } @@ -522,6 +545,9 @@ class AppIndicatorTrayIcon implements TrayIcon { if (peer.menuItem == menuItem) { + logger.debug("Setting default action to: " + + ((JMenuItem)menuItem).getText() + + " @" + peer.gtkMenuItem); return peer.gtkMenuItem; } @@ -553,10 +579,14 @@ class AppIndicatorTrayIcon implements TrayIcon @Override public void setIcon(ImageIcon icon) throws NullPointerException { - ai.app_indicator_set_icon_full( - appIndicator, - imageIconToPath(icon), - "Jitsi"); + mainIcon = icon; + if (appIndicator != null) + { + ai.app_indicator_set_icon_full( + appIndicator, + imageIconToPath(icon), + "Jitsi"); + } } @Override diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java index 8a2349e..72c96cb 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java @@ -49,10 +49,24 @@ interface Gobject extends Library * @param data data to pass to c_handler calls. * @param destroy_data a GClosureNotify for data. * @param connect_flags a combination of GConnectFlags. + * + * @return the handler id (always greater than 0 for successful connections) */ - void g_signal_connect_data(Pointer instance, String detailed_signal, + long g_signal_connect_data(Pointer instance, String detailed_signal, SignalHandler c_handler, Pointer data, Pointer destroy_data, int connect_flags); + + /** + * Disconnects a handler from an instance so it will not be called during + * any future or currently ongoing emissions of the signal it has been + * connected to. The handler_id becomes invalid and may be reused. The + * handler_id has to be a valid signal handler id, connected to a signal of + * instance . + * + * @param instance The instance to remove the signal handler from. + * @param handler_id Handler id of the handler to be disconnected. + */ + void g_signal_handler_disconnect(Pointer instance, long handler_id); /** * Decreases the reference count of object. When its reference count drops diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java index 7b74428..b66d59f 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gtk.java @@ -20,7 +20,7 @@ package net.java.sip.communicator.impl.osdependent.systemtray.appindicator; import com.sun.jna.*; /** - * JNA mappings for the gtk2 library. Only functions required for the try menu + * JNA mappings for the gtk2 library. Only functions required for the tray menu * are defined. * * @author Ingo Bauersachs @@ -44,14 +44,7 @@ interface Gtk extends Library void gtk_init(int argc, String[] argv); void gtk_main(); Pointer gtk_menu_new(); - Pointer gtk_menu_item_new(); - Pointer gtk_menu_item_new_with_label(String label); - Pointer gtk_image_menu_item_new_with_mnemonic(String label); Pointer gtk_image_menu_item_new_with_label(String label); - Pointer gtk_image_new_from_gicon(Pointer icon, int size); - Pointer gtk_image_new_from_stock(String stock_id, int size); - Pointer gtk_image_new_from_icon_name(String icon_name, int size); - Pointer gtk_image_new_from_file(String filename); Pointer gtk_separator_menu_item_new(); void gtk_menu_item_set_submenu(Pointer menu_item, Pointer submenu); void gtk_image_menu_item_set_image(Pointer image_menu_item, Pointer image); @@ -60,15 +53,11 @@ interface Gtk extends Library void gtk_menu_shell_append(Pointer menu_shell, Pointer child); void gtk_widget_set_sensitive(Pointer widget, int sesitive); void gtk_widget_show_all(Pointer widget); - //void gtk_container_remove(Pointer container, Pointer widget); void gtk_widget_destroy(Pointer widget); - void gtk_widget_show(Pointer widget); Pointer gtk_check_menu_item_new_with_label(String label); int gtk_check_menu_item_get_active(Pointer check_menu_item); void gtk_check_menu_item_set_active(Pointer check_menu_item, int is_active); - Pointer g_file_new_for_uri(String uri); - Pointer g_file_icon_new(Pointer file); void gdk_threads_enter(); void gdk_threads_leave(); -- cgit v1.1 From a0e3eea89f590605ca3490f2ddf0fae078b57183 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 15:55:58 +0100 Subject: Sysactivity notifications require libxss, not installed by default --- resources/install/rpm/SPECS/jitsi.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/install/rpm/SPECS/jitsi.spec b/resources/install/rpm/SPECS/jitsi.spec index 9449788..38aa215 100644 --- a/resources/install/rpm/SPECS/jitsi.spec +++ b/resources/install/rpm/SPECS/jitsi.spec @@ -21,6 +21,7 @@ Requires: java >= 1:1.7 Requires: libappindicator Requires: speex Requires: speexdsp +Requires: libXScrnSaver %description Jitsi is an audio/video and chat communicator that supports protocols -- cgit v1.1 From 2fb4e9d83c9704859200621ee9e79d5ea6f70203 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 15:59:50 +0100 Subject: Update systray to handle old libdbusmenu quirks (Debian, RPM distros) --- .../impl/osdependent/jdic/TrayMenuFactory.java | 2 +- .../appindicator/AppIndicatorTrayIcon.java | 131 ++++++++++++++++----- .../systemtray/appindicator/Gobject.java | 8 ++ 3 files changed, 109 insertions(+), 32 deletions(-) diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java index 05fe771..cae3ada 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/TrayMenuFactory.java @@ -185,7 +185,7 @@ public final class TrayMenuFactory + "CHAT_PRESENCE_DISABLED", false); - if (!chatPresenceDisabled.booleanValue()) + if (!chatPresenceDisabled.booleanValue() && accountMenuSupported) { add( trayMenu, diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java index a5bbee1..12334f3 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTrayIcon.java @@ -71,6 +71,8 @@ class AppIndicatorTrayIcon implements TrayIcon private PopupMenuPeer popupPeer; private AppIndicator1.AppIndicator appIndicator; + private PopupMenuPeer defaultMenuPeer; + public AppIndicatorTrayIcon(ImageIcon mainIcon, String title, JPopupMenu popup) { @@ -98,6 +100,16 @@ class AppIndicatorTrayIcon implements TrayIcon } } + @Override + protected void finalize() throws Throwable + { + super.finalize(); + if (isDefaultMenuItem) + { + gobject.g_object_unref(gtkMenuItem); + } + } + public List children = new ArrayList<>(); public Pointer gtkMenuItem; public Pointer gtkMenu; @@ -107,6 +119,7 @@ class AppIndicatorTrayIcon implements TrayIcon public Component menuItem; public MenuItemSignalHandler signalHandler; public long gtkSignalHandler; + public boolean isDefaultMenuItem; @Override public void componentAdded(ContainerEvent e) @@ -151,19 +164,15 @@ class AppIndicatorTrayIcon implements TrayIcon public void createTray() { - File iconFile = new File(imageIconToPath(mainIcon)); - appIndicator = ai.app_indicator_new_with_path( - "jitsi", - iconFile.getName().replaceFirst("[.][^.]+$", ""), - AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal(), - iconFile.getParent()); - - ai.app_indicator_set_title(appIndicator, title); - setupGtkMenu(); - - ai.app_indicator_set_status( - appIndicator, - AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal()); + gtk.gdk_threads_enter(); + try + { + setupGtkMenu(); + } + finally + { + gtk.gdk_threads_leave(); + } new Thread() { @@ -176,6 +185,19 @@ class AppIndicatorTrayIcon implements TrayIcon private void setupGtkMenu() { + File iconFile = new File(imageIconToPath(mainIcon)); + appIndicator = ai.app_indicator_new_with_path( + "jitsi", + iconFile.getName().replaceFirst("[.][^.]+$", ""), + AppIndicator1.APP_INDICATOR_CATEGORY.COMMUNICATIONS.ordinal(), + iconFile.getParent()); + + ai.app_indicator_set_title(appIndicator, title); + ai.app_indicator_set_icon_full( + appIndicator, + iconFile.getAbsolutePath(), + "Jitsi"); + // create root menu popupPeer = new PopupMenuPeer(null, popup); popupPeer.gtkMenu = gtk.gtk_menu_new(); @@ -186,11 +208,14 @@ class AppIndicatorTrayIcon implements TrayIcon // attach the menu to the indicator ai.app_indicator_set_menu(appIndicator, popupPeer.gtkMenu); + ai.app_indicator_set_status( + appIndicator, + AppIndicator1.APP_INDICATOR_STATUS.ACTIVE.ordinal()); } private void cleanMenu(PopupMenuPeer peer) { - logger.debug("Clean requested for: " + peer.menuItem); + assert !peer.isDefaultMenuItem; for (PopupMenuPeer p : peer.children) { cleanMenu(p); @@ -308,7 +333,6 @@ class AppIndicatorTrayIcon implements TrayIcon null, null, 0); - logger.debug("Signal for " + ((JMenuItem)m).getText() + " is " + peer.gtkSignalHandler); } } @@ -459,9 +483,18 @@ class AppIndicatorTrayIcon implements TrayIcon // gtk.gtk_image_menu_item_set_image(gtkMenuItem, image); // break; case AccessibleContext.ACCESSIBLE_STATE_PROPERTY: - gtk.gtk_widget_set_sensitive( - peer.gtkMenuItem, - AccessibleState.ENABLED.equals(evt.getNewValue()) ? 1 : 0); + gtk.gdk_threads_enter(); + try + { + gtk.gtk_widget_set_sensitive( + peer.gtkMenuItem, + AccessibleState.ENABLED.equals( + evt.getNewValue()) ? 1 : 0); + } + finally + { + gtk.gdk_threads_leave(); + } break; } } @@ -510,6 +543,7 @@ class AppIndicatorTrayIcon implements TrayIcon // already the same. Setting the selected state on the // GTK sends the "activate" event, and would cause // a loop + logger.debug("Checking selected state on: " + menu.getText()); if (menu.isSelected() == isGtkSelected()) { return; @@ -525,35 +559,63 @@ class AppIndicatorTrayIcon implements TrayIcon private boolean isGtkSelected() { - return (gtk.gtk_check_menu_item_get_active(peer.gtkMenuItem) == 1); + gtk.gdk_threads_enter(); + try + { + return gtk.gtk_check_menu_item_get_active(peer.gtkMenuItem) == 1; + } + finally + { + gtk.gdk_threads_leave(); + } } } @Override public void setDefaultAction(Object menuItem) { - Pointer gtkMenuItem = findMenuItem(popupPeer, menuItem); - if (gtkMenuItem != null) + // It shouldn't be necessary that we hold a reference to the + // default item, it is contained in the menu. It might even create + // a memory leak. But if not set, the indicator loses track of it + // (at least on Debian). Unref an existing item, then ref the newly + // set + if (defaultMenuPeer != null) + { + gobject.g_object_unref(defaultMenuPeer.gtkMenuItem); + } + + PopupMenuPeer peer = findMenuItem(popupPeer, menuItem); + if (peer != null && peer.gtkMenuItem != null) { - ai.app_indicator_set_secondary_activate_target( - appIndicator, - gtkMenuItem); + gtk.gdk_threads_enter(); + try + { + defaultMenuPeer = peer; + gobject.g_object_ref(peer.gtkMenuItem); + ai.app_indicator_set_secondary_activate_target( + appIndicator, + peer.gtkMenuItem); + } + finally + { + gtk.gdk_threads_leave(); + } } } - private Pointer findMenuItem(PopupMenuPeer peer, Object menuItem) + private PopupMenuPeer findMenuItem(PopupMenuPeer peer, Object menuItem) { if (peer.menuItem == menuItem) { logger.debug("Setting default action to: " + ((JMenuItem)menuItem).getText() + " @" + peer.gtkMenuItem); - return peer.gtkMenuItem; + return peer; } for (PopupMenuPeer p : peer.children) { - Pointer found = findMenuItem(p, menuItem); + PopupMenuPeer found = findMenuItem(p, menuItem); if (found != null) { return found; @@ -582,10 +644,17 @@ class AppIndicatorTrayIcon implements TrayIcon mainIcon = icon; if (appIndicator != null) { - ai.app_indicator_set_icon_full( - appIndicator, - imageIconToPath(icon), - "Jitsi"); + gtk.gdk_threads_enter(); + try + { + ai.app_indicator_set_icon( + appIndicator, + imageIconToPath(icon)); + } + finally + { + gtk.gdk_threads_leave(); + } } } diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java index 72c96cb..cfc7805 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/Gobject.java @@ -79,4 +79,12 @@ interface Gobject extends Library * @param object a GObject. */ void g_object_unref(Pointer object); + + /** + * Increases the reference count of object. + * + * @param object a GObject. + * @return the same object. + */ + Pointer g_object_ref(Pointer object); } -- cgit v1.1 From 2b819cf74759aff7842698e7abd403798c4dd441 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 16:04:21 +0100 Subject: Add option to choose tray icon mode (Native, Disabled, AppIndicator) --- resources/languages/resources.properties | 11 ++- .../sip/communicator/impl/gui/UIServiceImpl.java | 39 +++------- .../sip/communicator/impl/gui/main/MainFrame.java | 57 +++++++++++---- .../osdependent/jdic/SystrayServiceJdicImpl.java | 40 +++++++++-- .../impl/osdependent/systemtray/SystemTray.java | 72 ++++++++++++++----- .../systemtray/appindicator/AppIndicatorTray.java | 24 ++----- .../generalconfig/GeneralConfigurationPanel.java | 82 +++++++++++++++++++++- .../sip/communicator/service/gui/UIService.java | 26 ++----- .../service/systray/SystrayService.java | 20 ++++++ .../util/launchutils/LaunchArgHandler.java | 6 ++ 10 files changed, 268 insertions(+), 109 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index deea410..156c911 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -840,6 +840,15 @@ service.gui.security.encryption.required=Encryption required! service.protocol.ICE_FAILED=Could not establish connection (ICE failed and no relay found) +service.systray.MODE=Tray implementation +service.systray.mode.NATIVE=Default +service.systray.mode.DISABLED=Disabled +service.systray.mode.APPINDICATOR=AppIndicator (Unity, KDE, not plain Gnome 3; may crash on Debian) +service.systray.mode.APPINDICATOR_STATIC=AppIndicator Static (no account status menus) +service.systray.CLI_NOTE=If your choice does not work, you can start {0} with the "--notray" option. \ + This forces the mode to "Disabled" and shows the GUI. \ + Changing the tray implementation requires a restart. + # impl.protocol.ssh #Contact Details Seperator(must not be part of contact data stored as persistent # data) @@ -1089,7 +1098,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Always assume packet loss: plugin.generalconfig.SILK_SAT=Speech activity threshold (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Advertise FEC support in SDP: plugin.generalconfig.RESTORE=Restore defaults -plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimize the main window instead of hiding it +plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimize the main window instead of closing or hiding it # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish diff --git a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java index b7e1d9c..db2eac9 100644 --- a/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java +++ b/src/net/java/sip/communicator/impl/gui/UIServiceImpl.java @@ -200,6 +200,7 @@ public class UIServiceImpl } if(ConfigurationUtils.isApplicationVisible() + || Boolean.getBoolean("disable-tray") || ConfigurationUtils.isMinimizeInsteadOfHide()) { mainFrame.setFrameVisible(true); @@ -433,38 +434,16 @@ public class UIServiceImpl } /** - * Implements {@link UIService#setExitOnMainWindowClose}. Sets the boolean - * property which indicates whether the application should be exited when - * the main application window is closed. - * - * @param exitOnMainWindowClose true if closing the main - * application window should also be exiting the application; otherwise, - * false - */ - public void setExitOnMainWindowClose(boolean exitOnMainWindowClose) - { - mainFrame.setDefaultCloseOperation( - exitOnMainWindowClose - ? JFrame.DISPOSE_ON_CLOSE - : ConfigurationUtils.isMinimizeInsteadOfHide() - ? JFrame.DO_NOTHING_ON_CLOSE - : JFrame.HIDE_ON_CLOSE); - } - - /** - * Implements {@link UIService#getExitOnMainWindowClose()}. Gets the boolean - * property which indicates whether the application should be exited when - * the main application window is closed. - * - * @return determines whether the UI impl would exit the application when - * the main application window is closed. + * Called from the systray service when a tray has been initialized and + * hiding (instead of minimizing or exiting) is possible). If hiding is + * possible and the option to minimize is not selected, the application + * gets hidden on clicking 'X'. + * + * @param true if a tray icon was loaded. */ - public boolean getExitOnMainWindowClose() + public void setMainWindowCanHide(boolean canHide) { - return - (mainFrame != null) - && (mainFrame.getDefaultCloseOperation() - == JFrame.DISPOSE_ON_CLOSE); + mainFrame.updateCloseAction(canHide); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java index 4762df8..b450efe 100644 --- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java @@ -334,13 +334,9 @@ public class MainFrame */ private void init() { - setDefaultCloseOperation( - GuiActivator.getUIService().getExitOnMainWindowClose() - ? JFrame.DISPOSE_ON_CLOSE - : JFrame.HIDE_ON_CLOSE); - + // at startup, we cannot hide yet + updateCloseAction(false); registerKeyActions(); - JComponent northPanel = createTopComponent(); this.setJMenuBar(menu); @@ -394,6 +390,30 @@ public class MainFrame } } + /** + * If hiding is possible and the option to minimize is not selected, the + * application gets hidden on clicking 'X'. + * + * @param true if hiding is possible, i.e. a tray icon is loaded + */ + public void updateCloseAction(boolean canHide) + { + if (ConfigurationUtils.isMinimizeInsteadOfHide()) + { + logger.info("Updating close action: DO_NOTHING_ON_CLOSE"); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + } + else + { + logger.info("Updating close action: " + (canHide + ? "HIDE_ON_CLOSE" + : "DISPOSE_ON_CLOSE")); + setDefaultCloseOperation(canHide + ? JFrame.HIDE_ON_CLOSE + : JFrame.DISPOSE_ON_CLOSE); + } + } + private Component createButtonPanel() { boolean isCallButtonEnabled = false; @@ -1885,7 +1905,8 @@ public class MainFrame */ protected void windowClosed(WindowEvent event) { - if(GuiActivator.getUIService().getExitOnMainWindowClose()) + if(getDefaultCloseOperation() == JFrame.EXIT_ON_CLOSE || + getDefaultCloseOperation() == JFrame.DISPOSE_ON_CLOSE) { try { @@ -1919,10 +1940,17 @@ public class MainFrame // On Mac systems the application is not quited on window close, so we // don't need to warn the user. - if (!GuiActivator.getUIService().getExitOnMainWindowClose() - && !OSUtils.IS_MAC - && GuiActivator.getSystrayService().checkInitialized()) + if (OSUtils.IS_MAC) { + return; + } + + switch (getDefaultCloseOperation()) + { + case JFrame.EXIT_ON_CLOSE: + case JFrame.DISPOSE_ON_CLOSE: + return; + case JFrame.HIDE_ON_CLOSE: SwingUtilities.invokeLater(new Runnable() { public void run() @@ -1941,12 +1969,11 @@ public class MainFrame } } }); - ConfigurationUtils.setApplicationVisible(false); - if (ConfigurationUtils.isMinimizeInsteadOfHide()) - { - this.minimize(); - } + break; + case JFrame.DO_NOTHING_ON_CLOSE: + this.minimize(); + break; } } diff --git a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java index fd9d43e..0b40798 100644 --- a/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/osdependent/jdic/SystrayServiceJdicImpl.java @@ -21,6 +21,8 @@ import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.net.*; +import java.util.HashMap; +import java.util.Map; import javax.swing.*; import javax.swing.event.*; @@ -54,7 +56,6 @@ import com.apple.eawt.*; public class SystrayServiceJdicImpl extends AbstractSystrayService { - /** * The systray. */ @@ -130,7 +131,6 @@ public class SystrayServiceJdicImpl super(OsDependentActivator.bundleContext); SystemTray systray; - try { systray = SystemTray.getSystemTray(); @@ -146,10 +146,39 @@ public class SystrayServiceJdicImpl logger.error("Failed to create a systray!", t); } } - this.systray = systray; + this.systray = systray; if (this.systray != null) + { initSystray(); + } + } + + @Override + public Map getSystrayModes() + { + return new HashMap() + {{ + put("disabled", "service.systray.mode.DISABLED"); + if (java.awt.SystemTray.isSupported()) + { + put("native", "service.systray.mode.NATIVE"); + } + + if (!OSUtils.IS_MAC && !OSUtils.IS_WINDOWS) + { + put("appindicator", + "service.systray.mode.APPINDICATOR"); + put("appindicator_static", + "service.systray.mode.APPINDICATOR_STATIC"); + } + }}; + } + + @Override + public String getActiveSystrayMode() + { + return SystemTray.getSystemTrayMode(); } /** @@ -323,8 +352,7 @@ public class SystrayServiceJdicImpl }); initialized = true; - - uiService.setExitOnMainWindowClose(false); + uiService.setMainWindowCanHide(true); } /** @@ -432,8 +460,6 @@ public class SystrayServiceJdicImpl @Override public boolean checkInitialized() { - if (!initialized) - logger.error("Systray not init"); return initialized; } diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java index 74baa16..818d1e7 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/SystemTray.java @@ -26,6 +26,7 @@ import org.jitsi.util.*; import net.java.sip.communicator.impl.osdependent.*; import net.java.sip.communicator.impl.osdependent.systemtray.appindicator.*; import net.java.sip.communicator.impl.osdependent.systemtray.awt.*; +import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.util.Logger; /** @@ -33,11 +34,9 @@ import net.java.sip.communicator.util.Logger; */ public abstract class SystemTray { - private static final String PNMAE_DISABLE_TRY = - "net.java.sip.communicator.osdependent.systemtray.DISABLE"; - private static final Logger logger = Logger.getLogger(SystemTray.class); private static SystemTray systemTray; + private static final String DISABLED_TRAY_MODE = "disabled"; /** * Gets or creates the supported SystemTray implementations. @@ -45,37 +44,78 @@ public abstract class SystemTray */ public final static SystemTray getSystemTray() { - boolean disable = OsDependentActivator.getConfigurationService() - .getBoolean(PNMAE_DISABLE_TRY, false); - if (disable || GraphicsEnvironment.isHeadless()) - { - return null; - } - if (systemTray == null) { - if (OSUtils.IS_LINUX) + String mode = getSystemTrayMode(); + logger.info("Tray for " + mode + " requested"); + switch (mode) { + case DISABLED_TRAY_MODE: + return null; + case "native": + if (java.awt.SystemTray.isSupported()) + { + systemTray = new AWTSystemTray(); + } + + break; + case "appindicator": + try + { + systemTray = new AppIndicatorTray(true); + } + catch(Exception ex) + { + logger.error("AppIndicator tray not available", ex); + } + break; + case "appindicator_static": try { - systemTray = new AppIndicatorTray(); - return systemTray; + systemTray = new AppIndicatorTray(false); } catch(Exception ex) { - logger.info(ex.getMessage()); + logger.error("AppIndicator tray not available", ex); } + + break; } - if (java.awt.SystemTray.isSupported()) + if (systemTray == null) { - systemTray = new AWTSystemTray(); + OsDependentActivator.getConfigurationService() + .setProperty(SystrayService.PNMAE_TRAY_MODE, "disabled"); } } return systemTray; } + public static String getSystemTrayMode() + { + String defaultTrayMode = DISABLED_TRAY_MODE; + if (GraphicsEnvironment.isHeadless()) + { + return DISABLED_TRAY_MODE; + } + + // setting from cmd-line: request to disable tray in case it failed + if (Boolean.getBoolean("disable-tray")) + { + OsDependentActivator.getConfigurationService().setProperty( + SystrayService.PNMAE_TRAY_MODE, DISABLED_TRAY_MODE); + } + + if (OSUtils.IS_WINDOWS || OSUtils.IS_MAC) + { + defaultTrayMode = "native"; + } + + return OsDependentActivator.getConfigurationService() + .getString(SystrayService.PNMAE_TRAY_MODE, defaultTrayMode); + } + /** * Adds a TrayIcon to this system tray implementation. * diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java index 3f4e267..90c949a 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/appindicator/AppIndicatorTray.java @@ -32,25 +32,11 @@ import net.java.sip.communicator.util.*; */ public class AppIndicatorTray extends SystemTray { - private static final String PNMAE_APPINDICATOR_DISABLED = - "net.java.sip.communicator.osdependent.systemtray.appindicator.DISABLED"; - private static final String PNMAE_APPINDICATOR_DYNAMIC_MENU = - "net.java.sip.communicator.osdependent.systemtray.appindicator.DYNAMIC_MENU"; + private boolean dynamicMenu; - public AppIndicatorTray() throws Exception + public AppIndicatorTray(boolean dynamicMenu) throws Exception { - boolean disable = OsDependentActivator.getConfigurationService() - .getBoolean(PNMAE_APPINDICATOR_DISABLED, false); - if (disable) - { - throw new Exception("AppIndicator is disabled"); - } - - if (!OSUtils.IS_LINUX) - { - throw new Exception("Not running Linux, AppIndicator1 is not available"); - } - + this.dynamicMenu = dynamicMenu; try { // pre-initialize the JNA libraries before attempting to use them @@ -74,7 +60,6 @@ public class AppIndicatorTray extends SystemTray @Override public TrayIcon createTrayIcon(ImageIcon icon, String tooltip, Object popup) { - return new AppIndicatorTrayIcon(icon, tooltip, (JPopupMenu) popup); } @@ -88,7 +73,6 @@ public class AppIndicatorTray extends SystemTray @Override public boolean supportsDynamicMenu() { - return OsDependentActivator.getConfigurationService() - .getBoolean(PNMAE_APPINDICATOR_DYNAMIC_MENU, true); + return dynamicMenu; } } diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java index 6319455..04d55a5 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java @@ -98,6 +98,13 @@ public class GeneralConfigurationPanel = "net.java.sip.communicator.plugin.generalconfig.localeconfig.DISABLED"; + /** + * Indicates if the systray config panel should be disabled, i.e. not + * visible to the user. + */ + private static final String SYSTRAY_CONFIG_DISABLED_PROP = + "net.java.sip.communicator.plugin.generalconfig.systrayconfig.DISABLED"; + /** * Indicates if the Call configuration panel should be disabled, i.e. * not visible to the user. @@ -169,6 +176,13 @@ public class GeneralConfigurationPanel } if(!GeneralConfigPluginActivator.getConfigurationService() + .getBoolean(SYSTRAY_CONFIG_DISABLED_PROP, false)) + { + mainPanel.add(createSystrayeConfigPanel()); + mainPanel.add(Box.createVerticalStrut(10)); + } + + if(!GeneralConfigPluginActivator.getConfigurationService() .getBoolean(CALL_CONFIG_DISABLED_PROP, false)) { mainPanel.add(createCallConfigPanel()); @@ -251,7 +265,7 @@ public class GeneralConfigurationPanel { boolean value = ((JCheckBox) e.getSource()).isSelected(); ConfigurationUtils.setIsMinimizeInsteadOfHide(value); - UtilActivator.getUIService().setExitOnMainWindowClose( + UtilActivator.getUIService().setMainWindowCanHide( !UtilActivator.getSystrayService().checkInitialized()); } }); @@ -856,6 +870,72 @@ public class GeneralConfigurationPanel return localeConfigPanel; } + private static class Item + { + public String key; + public String value; + + public Item(String key, String value) + { + this.key = key; + this.value = value; + } + + @Override + public String toString() + { + return GeneralConfigPluginActivator.getResources() + .getI18NString(value); + } + } + + /** + * Initializes the systray configuration panel. + * @return the created component + */ + private Component createSystrayeConfigPanel() + { + JPanel panel = GeneralConfigPluginActivator. + createConfigSectionComponent( + Resources.getString("service.systray.MODE")); + + final JComboBox systrayModes = new JComboBox<>(); + SystrayService ss = GeneralConfigPluginActivator.getSystrayService(); + for (Map.Entry mode : ss.getSystrayModes().entrySet()) + { + Item i = new Item(mode.getKey(), mode.getValue()); + systrayModes.addItem(i); + if (mode.getKey().equals(ss.getActiveSystrayMode())) + { + systrayModes.setSelectedItem(i); + } + } + + systrayModes.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + GeneralConfigPluginActivator.getConfigurationService() + .setProperty(SystrayService.PNMAE_TRAY_MODE, + ((Item) systrayModes.getSelectedItem()).key); + } + }); + + panel.add(systrayModes); + String label = "* " + + Resources.getString("service.systray.CLI_NOTE", new String[]{ + Resources.getSettingsString("service.gui.APPLICATION_NAME") + }) + ""; + JLabel warnLabel = new JLabel(label); + warnLabel.setToolTipText(label); + warnLabel.setForeground(Color.GRAY); + warnLabel.setFont(warnLabel.getFont().deriveFont(8)); + warnLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); + panel.add(warnLabel); + return panel; + } + /** * Creates the call configuration panel. * diff --git a/src/net/java/sip/communicator/service/gui/UIService.java b/src/net/java/sip/communicator/service/gui/UIService.java index 33219d8..48994d4 100644 --- a/src/net/java/sip/communicator/service/gui/UIService.java +++ b/src/net/java/sip/communicator/service/gui/UIService.java @@ -157,26 +157,14 @@ public interface UIService public void bringToFront(); /** - * Sets the exitOnClose property. When TRUE, the user could exit the - * application by simply closing the main application window (by clicking - * the X button or pressing Alt-F4). When set to FALSE the main application - * window will be only hidden. - * - * @param exitOnClose When TRUE, the user could exit the application by - * simply closing the main application window (by clicking the X - * button or pressing Alt-F4). When set to FALSE the main - * application window will be only hidden. - */ - public void setExitOnMainWindowClose(boolean exitOnClose); - - /** - * Returns TRUE if the application could be exited by closing the main - * application window, otherwise returns FALSE. - * - * @return Returns TRUE if the application could be exited by closing the - * main application window, otherwise returns FALSE + * Called from the systray service when a tray has been initialized and + * hiding (instead of minimizing or exiting) is possible). If hiding is + * possible and the option to minimize is not selected, the application + * gets hidden on clicking 'X'. + * + * @param true if a tray icon was loaded. */ - public boolean getExitOnMainWindowClose(); + public void setMainWindowCanHide(boolean exitOnClose); /** * Returns an exported window given by the WindowID. This could be diff --git a/src/net/java/sip/communicator/service/systray/SystrayService.java b/src/net/java/sip/communicator/service/systray/SystrayService.java index bcde841..9d88852 100644 --- a/src/net/java/sip/communicator/service/systray/SystrayService.java +++ b/src/net/java/sip/communicator/service/systray/SystrayService.java @@ -17,6 +17,8 @@ */ package net.java.sip.communicator.service.systray; +import java.util.*; + import net.java.sip.communicator.service.systray.event.*; /** @@ -27,6 +29,9 @@ import net.java.sip.communicator.service.systray.event.*; */ public interface SystrayService { + public static final String PNMAE_TRAY_MODE = + "net.java.sip.communicator.osdependent.systemtray.MODE"; + /** * Message type corresponding to an error message. */ @@ -136,4 +141,19 @@ public interface SystrayService * @param count The number of pending notifications. */ public void setNotificationCount(int count); + + /** + * Gets a map of systray modes and resource-keys that describe them. + * @return key: mode for config property, value: resource key + */ + public Map getSystrayModes(); + + /** + * Gets the systray mode that was chosen at startup, either by default or as + * an override selected by the user. + * + * @return The selected mode or {@code disabled} if the user selected mode + * is not available. + */ + public String getActiveSystrayMode(); } diff --git a/src/net/java/sip/communicator/util/launchutils/LaunchArgHandler.java b/src/net/java/sip/communicator/util/launchutils/LaunchArgHandler.java index 90041fc..d5cbf14 100644 --- a/src/net/java/sip/communicator/util/launchutils/LaunchArgHandler.java +++ b/src/net/java/sip/communicator/util/launchutils/LaunchArgHandler.java @@ -299,6 +299,11 @@ public class LaunchArgHandler // do nothing already handled by startup script/binary continue; } + else if (args[i].startsWith("--notray")) + { + System.setProperty("disable-tray", "true"); + continue; + } //if this is the last arg and it's not an option then it's probably //an URI else if ( i == args.length - 1 @@ -521,6 +526,7 @@ public class LaunchArgHandler System.out.println(" -6, --ipv6 prefer IPv6 addresses where possible only"); System.out.println(" -4, --ipv4 forces use of IPv4 only"); System.out.println(" -v, --version display the current version and exit"); + System.out.println(" -n, --notray disable the tray icon and show the GUI"); } /** -- cgit v1.1 From 712e73d685f808048d8a6e0f51554eb07daccc74 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 16:22:30 +0100 Subject: Update libraries jitsi/ice4j@cefd96450947bad93eff9d4b5fc95af25dcb9ae3 Jenkins build 302 jitsi/libjitsi@48ce8b6848a6ed76f9e80045f29a7f4940230e28 Jenkins build 211 jitsi/jitsi-lgpl-dependencies@a747366e838b623a2c79cb4fefc120d2fc8990e7 local build --- .classpath | 4 ++-- build.xml | 4 ++-- .../ice4j-1.1-20160706.192041-13.jar | Bin 473184 -> 0 bytes .../ice4j-2.0-20170111.193659-7.jar | Bin 0 -> 500574 bytes .../jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar | Bin 7903378 -> 7903428 bytes .../libjitsi-1.0-20170107.144734-222.jar | Bin 9007818 -> 0 bytes .../libjitsi-1.0-20170110.164740-224.jar | Bin 0 -> 9007861 bytes nbproject/project.xml | 2 +- 8 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar create mode 100644 lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar delete mode 100644 lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar diff --git a/.classpath b/.classpath index 61d9df1..303f939 100755 --- a/.classpath +++ b/.classpath @@ -30,7 +30,7 @@ - + @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index abd86a9..81e44a2 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + @@ -996,7 +996,7 @@ - + diff --git a/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar b/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar deleted file mode 100644 index 5c0a83e..0000000 Binary files a/lib/installer-exclude/ice4j-1.1-20160706.192041-13.jar and /dev/null differ diff --git a/lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar b/lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar new file mode 100644 index 0000000..752334b Binary files /dev/null and b/lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar differ diff --git a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar index 257e3ed..36202ae 100644 Binary files a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar and b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar b/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar deleted file mode 100644 index 4313b83..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar b/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar new file mode 100644 index 0000000..4c55d46 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar differ diff --git a/nbproject/project.xml b/nbproject/project.xml index bc1138b..05e3010 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170107.144734-222.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 4ad81d511ab6f77883e40dbbd7515a08950a9b29 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:11:28 +0100 Subject: Replace deprecated calls to ice4j --- .../impl/gui/main/call/CallInfoFrame.java | 24 ++++++++------- .../sip/communicator/impl/gui/swing.ui.manifest.mf | 1 + .../protocol/jabber/IceUdpTransportManager.java | 35 ++++++++++------------ .../impl/protocol/jabber/JingleNodesCandidate.java | 4 +-- .../impl/protocol/jabber/JingleNodesHarvester.java | 2 +- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallInfoFrame.java b/src/net/java/sip/communicator/impl/gui/main/call/CallInfoFrame.java index ad8f6fd..872e861 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallInfoFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallInfoFrame.java @@ -34,6 +34,7 @@ import net.java.sip.communicator.util.*; import org.ice4j.ice.*; import org.jitsi.service.neomedia.*; +import org.jitsi.service.neomedia.stats.*; import org.jitsi.service.resources.*; import org.jitsi.util.*; @@ -469,7 +470,7 @@ public class CallInfoFrame StringBuffer stringBuffer, MediaType mediaType) { - MediaStreamStats mediaStreamStats + MediaStreamStats2 mediaStreamStats = mediaStream.getMediaStreamStats(); if(mediaStreamStats == null) @@ -624,18 +625,19 @@ public class CallInfoFrame resources.getI18NString( "service.gui.callinfo.BANDWITH"), "↓ " - + (int) mediaStreamStats.getDownloadRateKiloBitPerSec() + + (int) mediaStreamStats.getReceiveStats().getBitrate()/1024 + " Kbps " + " ↑ " - + (int) mediaStreamStats.getUploadRateKiloBitPerSec() + + (int) mediaStreamStats.getSendStats().getBitrate()/1024 + " Kbps")); stringBuffer.append( getLineString( resources.getI18NString("service.gui.callinfo.LOSS_RATE"), - "↓ " + (int) mediaStreamStats.getDownloadPercentLoss() + "↓" + + (int) (mediaStreamStats.getReceiveStats().getLossRate() * 100) + "% ↑ " - + (int) mediaStreamStats.getUploadPercentLoss() + + (int) (mediaStreamStats.getSendStats().getLossRate() * 100) + "%")); stringBuffer.append( getLineString( @@ -668,21 +670,23 @@ public class CallInfoFrame + mediaStreamStats.getPacketQueueCountPackets() + "/" + mediaStreamStats.getPacketQueueSize() + " packets")); - long rttMs = mediaStreamStats.getRttMs(); - if(rttMs != -1) + long sendRttMs = mediaStreamStats.getSendStats().getRtt(); + long recvRttMs = mediaStreamStats.getReceiveStats().getRtt(); + if(recvRttMs != -1 || sendRttMs != -1) { stringBuffer.append( getLineString(resources.getI18NString( "service.gui.callinfo.RTT"), - rttMs + " ms")); + (recvRttMs != -1 ? "↓ " + recvRttMs + " ms" : "") + + (sendRttMs != -1 ? "↑ " + sendRttMs + " ms" : ""))); } stringBuffer.append( getLineString(resources.getI18NString( "service.gui.callinfo.JITTER"), - "↓ " + (int) mediaStreamStats.getDownloadJitterMs() + "↓ " + (int) mediaStreamStats.getReceiveStats().getJitter() + " ms ↑ " - + (int) mediaStreamStats.getUploadJitterMs() + " ms")); + + (int) mediaStreamStats.getSendStats().getJitter() + " ms")); } /** diff --git a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf index 95d51fb..2795ef9 100644 --- a/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf +++ b/src/net/java/sip/communicator/impl/gui/swing.ui.manifest.mf @@ -72,6 +72,7 @@ Import-Package: com.apple.eawt, org.jitsi.service.neomedia.event, org.jitsi.service.neomedia.format, org.jitsi.service.neomedia.recording, + org.jitsi.service.neomedia.stats, org.jitsi.service.resources, org.jitsi.util, org.jitsi.util.event, diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java index 7305f5c..c3c852c 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java @@ -397,32 +397,29 @@ public class IceUdpTransportManager for (int i = 0; i < COMPONENT_IDS.length; i++) { Component component = stream.getComponent(COMPONENT_IDS[i]); - - if (component != null) + if (component == null) { - CandidatePair selectedPair = component.getSelectedPair(); - - if (selectedPair != null) - { - DatagramSocket streamConnectorSocket - = selectedPair.getDatagramSocket(); - - if (streamConnectorSocket != null) - { - streamConnectorSockets[i] = streamConnectorSocket; - streamConnectorSocketCount++; - logger.trace("Added a streamConnectorSocket to the array " + - "StreamConnectorSocket and increased " + - "the count of streamConnectorSocketCount by one to " + - streamConnectorSocketCount); + continue; + } - } - } + DatagramSocket streamConnectorSocket = component.getSocket(); + if (streamConnectorSocket != null) + { + streamConnectorSockets[i] = streamConnectorSocket; + streamConnectorSocketCount++; + logger.trace("Added a streamConnectorSocket to the array " + + "StreamConnectorSocket and increased " + + "the count of streamConnectorSocketCount by one to " + + streamConnectorSocketCount); } } + if (streamConnectorSocketCount > 0) + { return streamConnectorSockets; + } } + return null; } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java index 0ea9a54..f2473dd 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesCandidate.java @@ -87,7 +87,7 @@ public class JingleNodesCandidate * @return the RelayedCandidateDatagramSocket of this * RelayedCandidate */ - public synchronized JingleNodesCandidateDatagramSocket + private synchronized JingleNodesCandidateDatagramSocket getRelayedCandidateDatagramSocket() { if (jingleNodesCandidateDatagramSocket == null) @@ -113,7 +113,7 @@ public class JingleNodesCandidate * Candidate */ @Override - public IceSocketWrapper getIceSocketWrapper() + protected IceSocketWrapper getCandidateIceSocketWrapper() { if (socket == null) { diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java index 32ee849..d29be03 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/JingleNodesHarvester.java @@ -36,7 +36,7 @@ import org.xmpp.jnodes.smack.*; * @author Sebastien Vincent */ public class JingleNodesHarvester - extends CandidateHarvester + extends AbstractCandidateHarvester { /** * The Logger used by the JingleNodesHarvester class and -- cgit v1.1 From c7bdaa5539e796e6507b08ff0f87e5c955fb451f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:12:15 +0100 Subject: Use Java 7 instead of JNA to update home dir permissions --- .../impl/configuration/ConfigurationActivator.java | 46 ++++++++++------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java index a019c13..a77b2f5 100644 --- a/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java +++ b/src/net/java/sip/communicator/impl/configuration/ConfigurationActivator.java @@ -28,6 +28,9 @@ import org.jitsi.util.*; import org.osgi.framework.*; import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.*; /** * @@ -138,17 +141,30 @@ public class ConfigurationActivator // let's check config file and config folder File homeFolder = new File(cs.getScHomeDirLocation(), cs.getScHomeDirName()); - CLibrary libc = (CLibrary) Native.loadLibrary("c", CLibrary.class); - - libc.chmod(homeFolder.getAbsolutePath(), 0700); + Set perms = + new HashSet() + {{ + add(PosixFilePermission.OWNER_READ); + add(PosixFilePermission.OWNER_WRITE); + add(PosixFilePermission.OWNER_EXECUTE); + }}; + Files.setPosixFilePermissions( + Paths.get(homeFolder.getAbsolutePath()), perms); String fileName = cs.getConfigurationFilename(); - if(fileName != null) { File cf = new File(homeFolder, fileName); if(cf.exists()) - libc.chmod(cf.getAbsolutePath(), 0600); + { + perms = new HashSet() + {{ + add(PosixFilePermission.OWNER_READ); + add(PosixFilePermission.OWNER_WRITE); + }}; + Files.setPosixFilePermissions( + Paths.get(cf.getAbsolutePath()), perms); + } } } catch(Throwable t) @@ -163,24 +179,4 @@ public class ConfigurationActivator throw (ThreadDeath) t; } } - - /** - * The JNA interface to the c library and the chmod - * function we use to fix permissions of user files and folders. - */ - public interface CLibrary - extends Library - { - /** - * Changes file permissions. - * - * @param path the path to the file or folder the permissions of which - * are to be changed. - * @param mode the mode operand - * @return 0 upon successful completion; otherwise, - * -1. If -1 is returned, no change to the file mode - * occurs. - */ - public int chmod(String path, int mode); - } } -- cgit v1.1 From 79bb78b83c1b797a6091de2d8c82591ab5724283 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:25:18 +0100 Subject: Fix layout of call config options in general config --- .../generalconfig/GeneralConfigurationPanel.java | 62 +++++----------------- 1 file changed, 12 insertions(+), 50 deletions(-) diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java index 04d55a5..03fc308 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java @@ -960,13 +960,11 @@ public class GeneralConfigurationPanel */ private Component createNormalizeNumberCheckBox() { - JPanel checkBoxPanel = new TransparentPanel(new BorderLayout()); - - SIPCommCheckBox formatPhoneNumber = new SIPCommCheckBox("", + SIPCommCheckBox formatPhoneNumber = new SIPCommCheckBox( + GeneralConfigPluginActivator.getResources().getI18NString( + "plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS"), ConfigurationUtils.isNormalizePhoneNumber()); - formatPhoneNumber.setAlignmentY(Component.TOP_ALIGNMENT); - formatPhoneNumber.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) @@ -976,22 +974,7 @@ public class GeneralConfigurationPanel } }); - StyledHTMLEditorPane checkBoxTextLabel = new StyledHTMLEditorPane(); - - checkBoxTextLabel.setContentType("text/html"); - checkBoxTextLabel.appendToEnd( - "" + GeneralConfigPluginActivator.getResources().getI18NString( - "plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS") + ""); - - checkBoxTextLabel.setBorder( - BorderFactory.createEmptyBorder(3, 0, 0, 0)); - checkBoxTextLabel.setOpaque(false); - checkBoxTextLabel.setEditable(false); - - checkBoxPanel.add(formatPhoneNumber, BorderLayout.WEST); - checkBoxPanel.add(checkBoxTextLabel, BorderLayout.CENTER); - - return checkBoxPanel; + return formatPhoneNumber; } /** @@ -1001,17 +984,17 @@ public class GeneralConfigurationPanel */ private Component createAcceptPhoneNumberWithAlphaCharCheckBox() { - JPanel checkBoxPanel = new TransparentPanel(new BorderLayout()); + JPanel checkBoxPanel = new TransparentPanel(); + checkBoxPanel.setLayout(new BoxLayout(checkBoxPanel, BoxLayout.Y_AXIS)); // Checkbox to accept string with alphabetical characters as potential // phone numbers. - SIPCommCheckBox acceptPhoneNumberWithAlphaChars - = new SIPCommCheckBox("", + SIPCommCheckBox alphaCharNumbers = new SIPCommCheckBox( + GeneralConfigPluginActivator.getResources().getI18NString( + "plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS"), ConfigurationUtils.acceptPhoneNumberWithAlphaChars()); - acceptPhoneNumberWithAlphaChars.setAlignmentY(Component.TOP_ALIGNMENT); - - acceptPhoneNumberWithAlphaChars.addActionListener(new ActionListener() + alphaCharNumbers.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -1020,21 +1003,6 @@ public class GeneralConfigurationPanel } }); - StyledHTMLEditorPane acceptPhoneNumberWithAlphaCharsTextLabel - = new StyledHTMLEditorPane(); - - acceptPhoneNumberWithAlphaCharsTextLabel.setContentType("text/html"); - acceptPhoneNumberWithAlphaCharsTextLabel.appendToEnd( - "" - + GeneralConfigPluginActivator.getResources().getI18NString( - "plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS") - + ""); - - acceptPhoneNumberWithAlphaCharsTextLabel.setBorder( - BorderFactory.createEmptyBorder(3, 0, 0, 0)); - acceptPhoneNumberWithAlphaCharsTextLabel.setOpaque(false); - acceptPhoneNumberWithAlphaCharsTextLabel.setEditable(false); - // The example of changing letters to numbers in a phone number. String label = "* " + Resources.getString( "plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE"); @@ -1046,14 +1014,8 @@ public class GeneralConfigurationPanel exampleLabel.setHorizontalAlignment(JLabel.LEFT); // Adds the components to the current panel. - checkBoxPanel.add(acceptPhoneNumberWithAlphaChars, BorderLayout.WEST); - checkBoxPanel.add( - acceptPhoneNumberWithAlphaCharsTextLabel, - BorderLayout.CENTER); - checkBoxPanel.add( - exampleLabel, - BorderLayout.SOUTH); - + checkBoxPanel.add(alphaCharNumbers); + checkBoxPanel.add(exampleLabel); return checkBoxPanel; } -- cgit v1.1 From 6cead8e8e1a40096e0d9c33156820f59694a21db Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:33:52 +0100 Subject: Remove SIP Communicator rename information --- resources/languages/resources.properties | 11 +- .../plugin/branding/BrandingActivator.java | 4 - .../plugin/branding/JitsiWarningWindow.java | 203 --------------------- 3 files changed, 3 insertions(+), 215 deletions(-) delete mode 100644 src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 156c911..6d18122 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -326,11 +326,6 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Invite contacts to video bridge service.gui.INVITE_REASON=Invite reason service.gui.IS_CALLING={0} is calling... service.gui.IS_NOW={0} is now {1} -service.gui.JITSI_WARNING=SIP Communicator has recently been renamed to Jitsi.
    \ - If you want your version to remain up-to-date, then please download Jitsi now.\ -

    We are sorry for any inconvenience that this may be causing you.\ -

    The Jitsi Dev Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator becomes Jitsi service.gui.JOIN=&Join service.gui.JOIN_AS=J&oin as service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Join an existing video conference @@ -1023,9 +1018,9 @@ plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright \ https://jitsi.org.\
    plugin.branding.LICENSE=
    Jitsi is distributed under \ - the terms of the Apache \ - (\ - http://www.apache.org/licenses/LICENSE-2.0).
    + the terms of the \ + \ + Apache License 2.0. plugin.busylampfield.PICKUP=Pickup call diff --git a/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java b/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java index 6d8bdfd..f145dfb 100644 --- a/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java +++ b/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java @@ -86,10 +86,6 @@ public class BrandingActivator else welcomeWindow = null; - if (getResources().getSettingsString( - "service.gui.APPLICATION_NAME").equals("SIP Communicator")) - new JitsiWarningWindow(null).setVisible(true); - bundleContext.addBundleListener(this); } diff --git a/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java b/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java deleted file mode 100644 index 23c9880..0000000 --- a/src/net/java/sip/communicator/plugin/branding/JitsiWarningWindow.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.*; -import java.awt.event.*; - -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; -import net.java.sip.communicator.service.browserlauncher.*; - -import org.jitsi.service.resources.*; -import org.jitsi.util.*; -import org.osgi.framework.*; - -/** - * The JitsiWarningWindow. - * - * @author Yana Stamcheva - */ -public class JitsiWarningWindow - extends SIPCommDialog -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * Creates an JitsiWarningWindow by specifying the parent frame - * owner. - * @param owner the parent owner - */ - public JitsiWarningWindow(Frame owner) - { - super(owner, false); - - ResourceManagementService resources = BrandingActivator.getResources(); - - this.setTitle( - resources.getI18NString("service.gui.UPDATE") - + " " + resources.getSettingsString( - "service.gui.APPLICATION_NAME")); - - setModal(false); - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - - StyledHTMLEditorPane textArea = new StyledHTMLEditorPane(); - textArea.setContentType("text/html"); - textArea.setText(resources.getI18NString("service.gui.JITSI_WARNING")); - textArea.setOpaque(false); - textArea.setEditable(false); - - JLabel titleLabel = new JLabel( - resources.getI18NString("service.gui.JITSI_WARNING_TITLE")); - titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 14f)); - titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); - titleLabel.setMaximumSize(new Dimension(400, 50)); - - JPanel textPanel = new TransparentPanel(); - textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); - - textPanel.add(titleLabel); - textPanel.add(Box.createRigidArea(new Dimension(20, 20))); - textPanel.add(textArea); - - JButton downloadButton = new JButton( - resources.getI18NString("service.gui.DOWNLOAD_NOW")); - JButton remindButton = new JButton( - resources.getI18NString("service.gui.REMIND_ME_LATER")); - - this.getRootPane().setDefaultButton(downloadButton); - - downloadButton.setMnemonic( - resources.getI18nMnemonic("service.gui.DOWNLOAD_NOW")); - downloadButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - openURL(getDownloadLink()); - dispose(); - } - }); - remindButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - dispose(); - } - }); - - JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - buttonPanel.add(remindButton); - buttonPanel.add(downloadButton); - buttonPanel.setOpaque(false); - - JPanel mainPanel = new TransparentPanel(new BorderLayout(10, 10)); - mainPanel.add(new JLabel(resources.getImage( - "service.gui.SIP_COMMUNICATOR_LOGO_128x128")), BorderLayout.WEST); - mainPanel.add(textPanel, BorderLayout.CENTER); - mainPanel.add(buttonPanel, BorderLayout.SOUTH); - mainPanel.setPreferredSize(new Dimension(500, 200)); - mainPanel.setBorder( - BorderFactory.createEmptyBorder(20, 20, 20, 20)); - - getContentPane().add(mainPanel); - - this.pack(); - this.setResizable(false); - - setLocationRelativeTo(getParent()); - - this.getRootPane().getActionMap().put("close", new CloseAction()); - - InputMap imap = this.getRootPane().getInputMap( - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); - - if(OSUtils.IS_MAC) - { - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK), - "close"); - imap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK), - "close"); - } - } - - /** - * The action invoked when user presses Escape key. - */ - private class CloseAction extends UIAction - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public void actionPerformed(ActionEvent e) - { - setVisible(false); - dispose(); - } - } - - /** - * Opens the given url in a new browser window. - * @param url the url to open - */ - private void openURL(String url) - { - ServiceReference serviceReference = BrandingActivator - .getBundleContext().getServiceReference( - BrowserLauncherService.class.getName()); - - if (serviceReference != null) - { - BrowserLauncherService browserLauncherService - = (BrowserLauncherService) BrandingActivator - .getBundleContext().getService( - serviceReference); - - browserLauncherService.openURL(url); - } - } - - /** - * Indicates if the application name should be shown. - * - * @return true if the application name should be shown, - * false - otherwise - */ - private String getDownloadLink() - { - if (OSUtils.IS_WINDOWS) - return "http://download.jitsi.org/jitsi/windows/"; - else if (OSUtils.IS_MAC) - return "http://download.jitsi.org/jitsi/macosx/"; - - return "http://download.jitsi.org"; - } - - @Override - protected void close(boolean escaped) {} -} -- cgit v1.1 From a35090a49c279a07f72a76ab3cf2006158bbc75f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:50:27 +0100 Subject: Remove dict protocol translations --- resources/languages/resources.properties | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 6d18122..9fcbdbd 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1024,33 +1024,6 @@ plugin.branding.LICENSE=
    Jitsi is distributed under \ plugin.busylampfield.PICKUP=Pickup call -# Dict protocol -service.protocol.DICTIONARIES=Dictionaries -plugin.dictaccregwizz.ANY_DICTIONARY=Any Dictionary -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Any Dictionary from {0} -plugin.dictaccregwizz.FIRST_MATCH=First Match -plugin.dictaccregwizz.NO_MATCH=No match -plugin.dictaccregwizz.MATCH_RESULT=No definitions found for "{0}", perhaps you mean:\n -plugin.dictaccregwizz.INVALID_DATABASE=The current dictionary "{0}" doesn''t exist anymore on the server. -plugin.dictaccregwizz.INVALID_STRATEGY=The current strategy isn't available on the server. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=The Dict service protocol -plugin.dictaccregwizz.HOST=Host -plugin.dictaccregwizz.SERVER_INFO=Server informations -plugin.dictaccregwizz.STRATEGY_SELECTION=Strategy selection -plugin.dictaccregwizz.STRATEGY_LIST=List of strategies: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Search strategies -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategy is use to search similar words,if a translation was not found, thanks to different approaches. For example the Prefix strategies will search words which begin like the word you would translate. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict Account Information -plugin.dictaccregwizz.FIRST_ACCOUNT=This wizard will create your first Dict Account for you on dict.org.\n\n\ -You can add new dictionary by going on Account Registration Wizard. Fill the host Field with dictionary you would like to add. -plugin.dictaccregwizz.THREAD_CONNECT=Trying to connect to server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Connexion attempt failed, this isn't a dict server or the server is offline -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Retrieving strategies -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=No strategy found on the server -plugin.dictaccregwizz.POPULATE_LIST=Populating list -plugin.dictaccregwizz.CLOSING_CONNECTION=Closing connection - # generalconfig plugin.generalconfig.AUTO_START=Auto-start {0} when computer restarts or reboots plugin.generalconfig.CHATALERTS_ON_MESSAGE=Use task bar / dock alerts on incoming calls and chats -- cgit v1.1 From 4f8149f99ab23b4b1d20c650501bd833b1dab547 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:55:24 +0100 Subject: Remove long disabled sip2sip account wizard --- build.xml | 10 - resources/images/images.properties | 4 - .../images/protocol/sip2sip/sip16x16-away.png | Bin 2081 -> 0 bytes .../images/protocol/sip2sip/sip16x16-busy.png | Bin 2041 -> 0 bytes .../images/protocol/sip2sip/sip16x16-meeting.png | Bin 2101 -> 0 bytes .../images/protocol/sip2sip/sip16x16-offline.png | Bin 1775 -> 0 bytes .../images/protocol/sip2sip/sip16x16-online.png | Bin 1859 -> 0 bytes .../images/protocol/sip2sip/sip16x16-phone.png | Bin 2075 -> 0 bytes resources/images/protocol/sip2sip/sip16x16.png | Bin 1859 -> 0 bytes resources/images/protocol/sip2sip/sip32x32.png | Bin 2494 -> 0 bytes resources/images/protocol/sip2sip/sip48x48.png | Bin 4545 -> 0 bytes resources/images/protocol/sip2sip/sip64x64.png | Bin 6662 -> 0 bytes resources/languages/resources.properties | 10 +- .../CreateSip2SipAccountForm.java | 382 --------------------- .../Sip2SipAccRegWizzActivator.java | 136 -------- .../Sip2SipAccountRegistrationWizard.java | 269 --------------- .../sip2sipaccregwizz.manifest.mf | 43 --- 17 files changed, 1 insertion(+), 853 deletions(-) delete mode 100644 resources/images/protocol/sip2sip/sip16x16-away.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16-busy.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16-meeting.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16-offline.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16-online.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16-phone.png delete mode 100644 resources/images/protocol/sip2sip/sip16x16.png delete mode 100644 resources/images/protocol/sip2sip/sip32x32.png delete mode 100644 resources/images/protocol/sip2sip/sip48x48.png delete mode 100644 resources/images/protocol/sip2sip/sip64x64.png delete mode 100644 src/net/java/sip/communicator/plugin/sip2sipaccregwizz/CreateSip2SipAccountForm.java delete mode 100644 src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java delete mode 100644 src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java delete mode 100644 src/net/java/sip/communicator/plugin/sip2sipaccregwizz/sip2sipaccregwizz.manifest.mf diff --git a/build.xml b/build.xml index 81e44a2..c273fb8 100644 --- a/build.xml +++ b/build.xml @@ -1670,16 +1670,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - diff --git a/resources/images/images.properties b/resources/images/images.properties index 643e9ca..b7de44a 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -465,10 +465,6 @@ service.protocol.googletalk.GTALK_64x64=resources/images/protocol/googletalk/log service.protocol.iptel.IPTEL_16x16=resources/images/protocol/iptel/sip16x16.png service.protocol.iptel.IPTEL_64x64=resources/images/protocol/iptel/sip64x64.png -# sip2sip accregwizz -service.protocol.sip2sip.SIP2SIP_16x16=resources/images/protocol/sip2sip/sip16x16.png -service.protocol.sip2sip.SIP2SIP_64x64=resources/images/protocol/sip2sip/sip64x64.png - # ippi accregwizz service.protocol.ippi.IPPI_16x16=resources/images/protocol/ippi/sip16x16.png service.protocol.ippi.IPPI_64x64=resources/images/protocol/ippi/sip64x64.png diff --git a/resources/images/protocol/sip2sip/sip16x16-away.png b/resources/images/protocol/sip2sip/sip16x16-away.png deleted file mode 100644 index cc2d146..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-away.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16-busy.png b/resources/images/protocol/sip2sip/sip16x16-busy.png deleted file mode 100644 index b3e14e2..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-busy.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16-meeting.png b/resources/images/protocol/sip2sip/sip16x16-meeting.png deleted file mode 100644 index 20b191a..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-meeting.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16-offline.png b/resources/images/protocol/sip2sip/sip16x16-offline.png deleted file mode 100644 index ca74f64..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-offline.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16-online.png b/resources/images/protocol/sip2sip/sip16x16-online.png deleted file mode 100644 index cd05e31..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-online.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16-phone.png b/resources/images/protocol/sip2sip/sip16x16-phone.png deleted file mode 100644 index 0babceb..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16-phone.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip16x16.png b/resources/images/protocol/sip2sip/sip16x16.png deleted file mode 100644 index cd05e31..0000000 Binary files a/resources/images/protocol/sip2sip/sip16x16.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip32x32.png b/resources/images/protocol/sip2sip/sip32x32.png deleted file mode 100644 index 2b77182..0000000 Binary files a/resources/images/protocol/sip2sip/sip32x32.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip48x48.png b/resources/images/protocol/sip2sip/sip48x48.png deleted file mode 100644 index ffcaeeb..0000000 Binary files a/resources/images/protocol/sip2sip/sip48x48.png and /dev/null differ diff --git a/resources/images/protocol/sip2sip/sip64x64.png b/resources/images/protocol/sip2sip/sip64x64.png deleted file mode 100644 index 9c7babe..0000000 Binary files a/resources/images/protocol/sip2sip/sip64x64.png and /dev/null differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 9fcbdbd..2a36c4f 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1356,19 +1356,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, the IP Telecommunications plugin.iptelaccregwizz.USERNAME=User name plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Subscribe to iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP and chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Username plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Retype password plugin.sip2sipaccregwizz.EMAIL=Email address -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=For help about this service visit
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=The email address is used to send voicemail messages,
    missed calls notifications and to recover a lost password -plugin.sip2sipaccregwizz.INFO_NOTE=For help about this service visit http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Existing sip2sip.info account -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Create a free sip2sip.info account - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Instant Messaging plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=For help about this service visit
    http://ippi.fr diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/CreateSip2SipAccountForm.java b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/CreateSip2SipAccountForm.java deleted file mode 100644 index aa38c69..0000000 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/CreateSip2SipAccountForm.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sip2sipaccregwizz; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.net.*; - -import javax.swing.*; -import javax.swing.text.*; - -import net.java.sip.communicator.plugin.ippiaccregwizz.*; -import net.java.sip.communicator.plugin.sipaccregwizz.*; -import net.java.sip.communicator.util.*; -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.json.simple.*; - -/** - * @author Yana Stamcheva - */ -public class CreateSip2SipAccountForm - extends TransparentPanel - implements SIPAccountCreationFormService -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - /** - * The logger. - */ - private static final Logger logger - = Logger.getLogger(CreateSip2SipAccountForm.class); - - /** - * The user name text field. - */ - private final JTextField usernameField = new TrimTextField(); - - /** - * The display name text field. - */ - private final JTextField displayNameField = new JTextField(); - - /** - * The password field. - */ - private final JPasswordField passField = new JPasswordField(); - - /** - * The retype password field. - */ - private final JPasswordField retypePassField = new JPasswordField(); - - /** - * The email field. - */ - private final JTextField emailField = new JTextField(); - - /** - * The error text pane. - */ - private final JTextPane errorPane = new JTextPane(); - - /** - * The register link. - */ - private static String registerLink - = "https://enrollment.sipthor.net/enrollment.phtml?"; - - /** - * Creates an instance of RegisterSip2SipAccountForm. - */ - public CreateSip2SipAccountForm() - { - super(new BorderLayout()); - - this.init(); - } - - /** - * Initializes this panel. - */ - private void init() - { - JPanel mainPanel = new TransparentPanel(new BorderLayout()); - - mainPanel.setBorder(BorderFactory.createTitledBorder( - Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sipaccregwizz.CREATE_ACCOUNT_TITLE"))); - - JPanel labelsPanel = new TransparentPanel(new GridLayout(0, 1)); - - JPanel valuesPanel = new TransparentPanel(new GridLayout(0, 1)); - - JLabel usernameLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sip2sipaccregwizz.USERNAME")); - - JLabel displayNameLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sipaccregwizz.DISPLAY_NAME")); - - JLabel passLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("service.gui.PASSWORD")); - - JLabel retypePasswordLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sip2sipaccregwizz.RETYPE_PASSWORD")); - - JLabel emailLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sip2sipaccregwizz.EMAIL")); - - labelsPanel.add(displayNameLabel); - labelsPanel.add(usernameLabel); - labelsPanel.add(passLabel); - labelsPanel.add(retypePasswordLabel); - labelsPanel.add(emailLabel); - - valuesPanel.add(displayNameField); - valuesPanel.add(usernameField); - valuesPanel.add(passField); - valuesPanel.add(retypePassField); - valuesPanel.add(emailField); - - JLabel emailDescriptionLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sip2sipaccregwizz.EMAIL_NOTE"), - SwingConstants.CENTER); - emailDescriptionLabel.setForeground(Color.GRAY); - emailDescriptionLabel.setFont(emailDescriptionLabel.getFont().deriveFont(8)); - emailDescriptionLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 8, 10)); - - initErrorArea(); - - mainPanel.add(labelsPanel, BorderLayout.WEST); - mainPanel.add(valuesPanel, BorderLayout.CENTER); - mainPanel.add(emailDescriptionLabel, BorderLayout.SOUTH); - - this.add(mainPanel, BorderLayout.CENTER); - - JLabel infoLabel - = new JLabel(Sip2SipAccRegWizzActivator.getResources() - .getI18NString("plugin.sip2sipaccregwizz.INFO_NOTE"), - SwingConstants.RIGHT); - infoLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); - infoLabel.setForeground(Color.GRAY); - infoLabel.setFont(emailDescriptionLabel.getFont().deriveFont(8)); - infoLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0)); - infoLabel.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent e) - { - Sip2SipAccRegWizzActivator.getBrowserLauncher() - .openURL("http://wiki.sip2sip.info"); - } - }); - - this.add(infoLabel, BorderLayout.SOUTH); - } - - /** - * Creates the error area component. - */ - private void initErrorArea() - { - SimpleAttributeSet attribs = new SimpleAttributeSet(); - StyleConstants.setAlignment(attribs, StyleConstants.ALIGN_RIGHT); - StyleConstants.setFontFamily(attribs, errorPane.getFont().getFamily()); - StyleConstants.setForeground(attribs, Color.RED); - errorPane.setParagraphAttributes(attribs, true); - errorPane.setPreferredSize(new Dimension(100, 50)); - errorPane.setMinimumSize(new Dimension(100, 50)); - errorPane.setOpaque(false); - } - - /** - * Creates this account on the server. - * @return the created account - */ - public NewAccount createAccount() - { - // Check if the two passwords match. - String pass1 = new String( passField.getPassword()); - String pass2 = new String( retypePassField.getPassword()); - if (!pass1.equals(pass2)) - { - showErrorMessage( - IppiAccRegWizzActivator.getResources().getI18NString( - "plugin.sipaccregwizz.NOT_SAME_PASSWORD")); - - return null; - } - - NewAccount newAccount = null; - try - { - StringBuilder registerLinkBuilder = new StringBuilder(registerLink); - registerLinkBuilder - .append(URLEncoder.encode("email", "UTF-8")) - .append("=").append( - URLEncoder.encode(emailField.getText(), "UTF-8")) - .append("&").append(URLEncoder.encode("password", "UTF-8")) - .append("=").append( - URLEncoder.encode(new String(passField.getPassword()), "UTF-8")) - .append("&").append(URLEncoder.encode("display_name", "UTF-8")) - .append("=").append( - URLEncoder.encode(displayNameField.getText(), "UTF-8")) - .append("&").append(URLEncoder.encode("username", "UTF-8")) - .append("=").append( - URLEncoder.encode(usernameField.getText(), "UTF-8")) - .append("&").append(URLEncoder.encode("user_agent", "UTF-8")) - .append("=").append( - URLEncoder.encode("sip-communicator.org", "UTF-8")); - - URL url = new URL(registerLinkBuilder.toString()); - URLConnection conn = url.openConnection(); - - // If this is not an http connection we have nothing to do here. - if (!(conn instanceof HttpURLConnection)) - { - return null; - } - - HttpURLConnection httpConn = (HttpURLConnection) conn; - - int responseCode = httpConn.getResponseCode(); - - if (responseCode == HttpURLConnection.HTTP_OK) - { - // Read all the text returned by the server - BufferedReader in = new BufferedReader( - new InputStreamReader(conn.getInputStream())); - String str; - - StringBuffer stringBuffer = new StringBuffer(); - while ((str = in.readLine()) != null) - { - stringBuffer.append(str); - } - - if (logger.isInfoEnabled()) - logger.info("JSON response to create account request: " - + stringBuffer.toString()); - - newAccount = parseHttpResponse(stringBuffer.toString()); - } - } - catch (MalformedURLException e1) - { - if (logger.isInfoEnabled()) - logger.info("Failed to create URL with string: " - + registerLink, e1); - } - catch (IOException e1) - { - if (logger.isInfoEnabled()) - logger.info("Failed to open connection.", e1); - } - return newAccount; - } - - /** - * Returns the form, which would be used by the user to create a new - * account. - * @return the component of the form - */ - public Component getForm() - { - return this; - } - - /** - * Clears all the data previously entered in the form. - */ - public void clear() - { - usernameField.setText(""); - displayNameField.setText(""); - passField.setText(""); - retypePassField.setText(""); - emailField.setText(""); - errorPane.setText(""); - - remove(errorPane); - } - - /** - * Parses the given http response. - * @param response the http response to parse - * @return the new account - */ - private NewAccount parseHttpResponse(String response) - { - NewAccount newAccount = null; - try - { - JSONObject jsonObject = (JSONObject)JSONValue - .parseWithException(response); - boolean isSuccess = (Boolean)jsonObject.get("success"); - - if (isSuccess) - { - newAccount = new NewAccount( - (String)jsonObject.get("sip_address"), - passField.getPassword(), - null, - (String)jsonObject.get("outbound_proxy")); - - String xcapRoot = (String)jsonObject.get("xcap_root"); - - // as sip2sip adds @sip2sip.info at the end of the - // xcap_uri but doesn't report it in resullt after - // creating account, we add it - String domain = null; - int delimIndex = newAccount.getUserName().indexOf("@"); - if (delimIndex != -1) - { - domain = newAccount.getUserName().substring(delimIndex); - } - if(domain != null) - { - if(xcapRoot.endsWith("/")) - xcapRoot = - xcapRoot.substring(0, xcapRoot.length() - 1) - + domain; - else - xcapRoot += domain; - } - - newAccount.setXcapRoot(xcapRoot); - } - else - { - showErrorMessage((String)jsonObject.get("error_message")); - } - } - catch (Throwable e1) - { - if (logger.isInfoEnabled()) - logger.info("Failed Json parsing.", e1); - } - - return newAccount; - } - - /** - * Shows the given error message. - * - * @param text the text of the error - */ - private void showErrorMessage(String text) - { - errorPane.setText(text); - - if (errorPane.getParent() == null) - add(errorPane, BorderLayout.NORTH); - - SwingUtilities.getWindowAncestor(CreateSip2SipAccountForm.this).pack(); - } -} diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java deleted file mode 100644 index bb13f2b..0000000 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccRegWizzActivator.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sip2sipaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.service.browserlauncher.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.resources.*; - -import org.jitsi.service.resources.*; -import org.osgi.framework.*; - -/** - * Registers the GoogleTalkAccountRegistrationWizard in the UI Service. - * - * @author Lubomir Marinov - * @author Yana Stamcheva - */ -public class Sip2SipAccRegWizzActivator - implements BundleActivator -{ - /** - * The bundle context. - */ - public static BundleContext bundleContext; - - /** - * The browser launcher service. - */ - private static BrowserLauncherService browserLauncherService; - - /** - * The resources service. - */ - private static ResourceManagementService resourcesService; - - /** - * The ui service. - */ - private static UIService uiService; - - /** - * Starts this bundle. - * @param bc BundleContext - * @throws Exception - */ - public void start(BundleContext bc) - throws Exception - { - bundleContext = bc; - - System.setProperty( - "http.agent", - System.getProperty("sip-communicator.application.name") - + "/" - + System.getProperty("sip-communicator.version")); - - uiService = - (UIService) bundleContext.getService(bundleContext - .getServiceReference(UIService.class.getName())); - - Sip2SipAccountRegistrationWizard wizard - = new Sip2SipAccountRegistrationWizard(uiService - .getAccountRegWizardContainer()); - - Hashtable containerFilter - = new Hashtable(); - containerFilter.put( - ProtocolProviderFactory.PROTOCOL, - Sip2SipAccountRegistrationWizard.PROTOCOL); - - bundleContext.registerService( - AccountRegistrationWizard.class.getName(), - wizard, - containerFilter); - } - - public void stop(BundleContext bundleContext) throws Exception {} - - /** - * Returns the UIService. - * - * @return the UIService - */ - public static UIService getUIService() - { - return uiService; - } - - /** - * Returns the BrowserLauncherService obtained from the bundle - * context. - * @return the BrowserLauncherService obtained from the bundle - * context - */ - public static BrowserLauncherService getBrowserLauncher() - { - if (browserLauncherService == null) - { - browserLauncherService - = (BrowserLauncherService) bundleContext.getService( - bundleContext.getServiceReference( - BrowserLauncherService.class.getName())); - } - return browserLauncherService; - } - - /** - * Returns the service giving access to resources. - * @return the service giving access to resources - */ - public static ResourceManagementService getResources() - { - if (resourcesService == null) - resourcesService = ResourceManagementServiceUtils - .getService(Sip2SipAccRegWizzActivator.bundleContext); - return resourcesService; - } -} diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java deleted file mode 100644 index 55e6f36..0000000 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/Sip2SipAccountRegistrationWizard.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.sip2sipaccregwizz; - -import java.util.*; - -import net.java.sip.communicator.plugin.sipaccregwizz.*; -import net.java.sip.communicator.service.gui.*; -import net.java.sip.communicator.service.protocol.sip.*; - -/** - * The Sip2SipAccountRegistrationWizard is an implementation of the - * AccountRegistrationWizard for the SIP protocol. It should allow - * the user to create and configure a new IP Tel SIP account. - * - * @author Yana Stamcheva - */ -public class Sip2SipAccountRegistrationWizard - extends SIPAccountRegistrationWizard -{ - /** - * A constant pointing to the IP Tel protocol logo image. - */ - private static final String PROTOCOL_ICON - = "service.protocol.sip2sip.SIP2SIP_16x16"; - - /** - * A constant pointing to the IP Tel protocol wizard page image. - */ - private static final String PAGE_IMAGE - = "service.protocol.sip2sip.SIP2SIP_64x64"; - - /** - * The protocol name. - */ - public static final String PROTOCOL = "sip2sip.info"; - - /** - * The create account form. - */ - CreateSip2SipAccountForm createAccountForm = new CreateSip2SipAccountForm(); - - /** - * Creates an instance of IptelAccountRegistrationWizard. - * @param wizardContainer the wizard container - */ - public Sip2SipAccountRegistrationWizard(WizardContainer wizardContainer) - { - super(wizardContainer); - } - - /** - * Returns the set of pages contained in this wizard. - * @return Iterator - */ - @Override - public Iterator getPages() - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getPages(reg); - } - - /** - * Returns a simple account registration form that would be the first form - * shown to the user. Only if the user needs more settings she'll choose - * to open the advanced wizard, consisted by all pages. - * - * @param isCreateAccount indicates if the simple form should be opened as - * a create account form or as a login form - * @return a simple account registration form - */ - @Override - public Object getSimpleForm(boolean isCreateAccount) - { - SIPAccountRegistration reg = new SIPAccountRegistration(); - - setPredefinedProperties(reg); - - return getSimpleForm(reg, isCreateAccount); - } - - /** - * Sets all predefined properties specific for this account wizard. - * - * @param reg the registration object - */ - private void setPredefinedProperties(SIPAccountRegistration reg) - { - // set properties common for sip2sip - reg.setKeepAliveMethod("NONE"); - reg.setDefaultDomain("sip2sip.info"); - reg.setXCapEnable(true); - reg.setClistOptionServerUri( - "https://xcap.sipthor.net/xcap-root@sip2sip.info"); - reg.setClistOptionUseSipCredentials(true); - } - - /** - * Implements the AccountRegistrationWizard.getIcon method. - * Returns the icon to be used for this wizard. - * @return byte[] - */ - @Override - public byte[] getIcon() - { - return Sip2SipAccRegWizzActivator.getResources() - .getImageInBytes(PROTOCOL_ICON); - } - - /** - * Implements the AccountRegistrationWizard.getPageImage method. - * Returns the image used to decorate the wizard page - * - * @return byte[] the image used to decorate the wizard page - */ - @Override - public byte[] getPageImage() - { - return Sip2SipAccRegWizzActivator.getResources() - .getImageInBytes(PAGE_IMAGE); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolName - * method. Returns the protocol name for this wizard. - * @return String - */ - @Override - public String getProtocolName() - { - return Resources.getString( - "plugin.sip2sipaccregwizz.PROTOCOL_NAME"); - } - - /** - * Implements the AccountRegistrationWizard.getProtocolDescription - * method. Returns the description of the protocol for this wizard. - * @return String - */ - @Override - public String getProtocolDescription() - { - return Resources.getString( - "plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION"); - } - - /** - * Returns an example string, which should indicate to the user how the - * user name should look like. - * @return an example string, which should indicate to the user how the - * user name should look like. - */ - @Override - public String getUserNameExample() - { - return "Ex: myusername or myusername@sip2sip.info"; - } - - /** - * Returns the protocol name as listed in "ProtocolNames" or just the name - * of the service. - * @return the protocol name - */ - @Override - public String getProtocol() - { - return PROTOCOL; - } - - /** - * Returns the protocol icon path. - * @return the protocol icon path - */ - @Override - public String getProtocolIconPath() - { - return "resources/images/protocol/sip2sip"; - } - - /** - * Returns the account icon path. - * @return the account icon path - */ - @Override - public String getAccountIconPath() - { - return "resources/images/protocol/sip2sip/sip32x32.png"; - } - - /** - * Opens the browser on the page sign up - */ - @Override - public void webSignup() - { - Sip2SipAccRegWizzActivator.getBrowserLauncher() - .openURL("http://wiki.sip2sip.info"); - } - - /** - * Returns the name of the web sign up link. - * @return the name of the web sign up link - */ - @Override - public String getWebSignupLinkName() - { - return Resources.getString("plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE"); - } - - /** - * Returns an instance of CreateAccountService through which the - * user could create an account. This method is meant to be implemented by - * specific protocol provider wizards. - * @return an instance of CreateAccountService - */ - @Override - protected SIPAccountCreationFormService getCreateAccountService() - { - return createAccountForm; - } - - /** - * Returns the display label used for the sip id field. - * @return the sip id display label string. - */ - @Override - protected String getUsernameLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.USERNAME"); - } - - /** - * Return the string for add existing account button. - * @return the string for add existing account button. - */ - @Override - protected String getExistingAccountLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.EXISTING_ACCOUNT"); - } - - /** - * Return the string for create new account button. - * @return the string for create new account button. - */ - @Override - protected String getCreateAccountLabel() - { - return Resources.getString("plugin.sip2sipaccregwizz.CREATE_ACCOUNT"); - } -} diff --git a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/sip2sipaccregwizz.manifest.mf b/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/sip2sipaccregwizz.manifest.mf deleted file mode 100644 index 7ebbd1c..0000000 --- a/src/net/java/sip/communicator/plugin/sip2sipaccregwizz/sip2sipaccregwizz.manifest.mf +++ /dev/null @@ -1,43 +0,0 @@ -Bundle-Activator: net.java.sip.communicator.plugin.sip2sipaccregwizz.Sip2SipAccRegWizzActivator -Bundle-Name: Sip 2 Sip account registration wizard -Bundle-Description: Sip 2 Sip account registration wizard. -Bundle-Vendor: jitsi.org -Bundle-Version: 0.0.1 -Bundle-SymbolicName: net.java.sip.communicator.plugin.sip2sipaccregwizz -Import-Package: org.osgi.framework, - net.java.sip.communicator.service.browserlauncher, - org.jitsi.service.configuration, - net.java.sip.communicator.service.contactlist, - net.java.sip.communicator.service.contactlist.event, - org.jitsi.service.fileaccess, - net.java.sip.communicator.service.gui, - net.java.sip.communicator.service.gui.event, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, - net.java.sip.communicator.service.protocol.icqconstants, - net.java.sip.communicator.service.protocol.sip, - org.jitsi.service.resources, net.java.sip.communicator.service.resources, - net.java.sip.communicator.util, - net.java.sip.communicator.plugin.desktoputil, - net.java.sip.communicator.plugin.sipaccregwizz, - javax.naming, - javax.naming.directory, - javax.xml.parsers, - org.w3c.dom, - org.xml.sax, - org.json.simple, - javax.swing, - javax.swing.event, - javax.swing.table, - javax.swing.text, - javax.swing.text.html, - javax.accessibility, - javax.swing.plaf, - javax.swing.plaf.metal, - javax.swing.plaf.basic, - javax.imageio, - javax.swing.filechooser, - javax.swing.tree, - javax.swing.undo, - javax.swing.border, - org.jivesoftware.smack -- cgit v1.1 From 75631826fc3f5fc4bc58ffb65be875131002137d Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:55:37 +0100 Subject: Remove SSH account translations --- resources/languages/resources.properties | 9 --------- 1 file changed, 9 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 2a36c4f..51813fd 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1277,15 +1277,6 @@ plugin.skinmanager.DEFAULT_SKIN=Default skin plugin.skinmanager.ADD_NEW_SKIN=Add new skin... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=The default skin of the application. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=A Protocol to connect to remote machines over SSH. -plugin.sshaccregwizz.USERNAME=Account ID: -plugin.sshaccregwizz.IDENTITY_FILE=Identity File: -plugin.sshaccregwizz.KNOWN_HOSTS=Known Hosts: -plugin.sshaccregwizz.OPTIONAL=Optional -plugin.sshaccregwizz.ACCOUNT_DETAILS=Account details - # status update plugin.autoaway.AUTO_STATUS=Auto Away plugin.autoaway.ENABLE_CHANGE_STATUS=Change status while away -- cgit v1.1 From 0c2e1e5844234fa2f4c5ebe475c88e3e0382f878 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 17:55:59 +0100 Subject: Remove Zeroconf account translations --- resources/languages/resources.properties | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 51813fd..c35bacf 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1324,16 +1324,6 @@ plugin.whiteboard.DESELECT=Deselect plugin.whiteboard.DELETE=Delete plugin.whiteboard.PROPERTIES=Properties -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=The Zeroconf (Bonjour) service protocol. -plugin.zeroaccregwizz.FIRST_NAME=First name: -plugin.zeroaccregwizz.LAST_NAME=Last name: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Remember Bonjour contacts? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID and Password -plugin.zeroaccregwizz.USERID=User ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=The Google Talk protocol -- cgit v1.1 From 6eaa56d09126da3599180d34edb01eeba3aa724e Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 18:22:15 +0100 Subject: Update about window to current license, remove in-app splashscreen --- resources/config/defaults.properties | 5 - resources/images/images.properties | 1 - .../plugin/branding/splashScreenBackground.png | Bin 56561 -> 0 bytes resources/languages/resources.properties | 16 +- .../communicator/plugin/branding/AboutWindow.java | 105 ++--- .../plugin/branding/BrandingActivator.java | 134 +------ .../plugin/branding/WelcomeWindow.java | 443 --------------------- 7 files changed, 48 insertions(+), 656 deletions(-) delete mode 100644 resources/images/plugin/branding/splashScreenBackground.png delete mode 100644 src/net/java/sip/communicator/plugin/branding/WelcomeWindow.java diff --git a/resources/config/defaults.properties b/resources/config/defaults.properties index f126476..38bb564 100644 --- a/resources/config/defaults.properties +++ b/resources/config/defaults.properties @@ -54,14 +54,9 @@ net.java.sip.communicator.service.msghistory.IS_MESSAGE_HISTORY_ENABLED=true plugin.branding.ABOUT_LOGO_FONT_SIZE=14 plugin.branding.ABOUT_TEXT_INDENT=180 plugin.branding.SPLASH_SCREEN_TEXT_INDENT=190 -plugin.branding.LOADING_BUNDLE_PANEL_HEIGHT=40 plugin.branding.LOADING_BUNDLE_PANEL_BORDER=10 plugin.branding.ABOUT_PARAGRAPH_GAP=10 -# Application name could be present in the background image and in this case -# we may not want to show it again. -plugin.branding.IS_APPLICATION_NAME_SHOWN=true - # jabber accregwizz plugin.jabberaccregwizz.SERVER_COMMENTS=net/java/sip/communicator/plugin/jabberaccregwizz/resources/servercomments.xml diff --git a/resources/images/images.properties b/resources/images/images.properties index b7de44a..e9ac9ea 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -471,7 +471,6 @@ service.protocol.ippi.IPPI_64x64=resources/images/protocol/ippi/sip64x64.png # branding plugin images plugin.branding.ABOUT_WINDOW_BACKGROUND=resources/images/plugin/branding/aboutWindowBackground.png -plugin.branding.SPLASH_SCREEN_BACKGROUND=resources/images/plugin/branding/splashScreenBackground.png #plugin busylampfield plugin.busylampfield.PICKUP_CALL=resources/images/impl/gui/buttons/pickupCall.png diff --git a/resources/images/plugin/branding/splashScreenBackground.png b/resources/images/plugin/branding/splashScreenBackground.png deleted file mode 100644 index 5754b26..0000000 Binary files a/resources/images/plugin/branding/splashScreenBackground.png and /dev/null differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index c35bacf..89de334 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -1008,19 +1008,11 @@ plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Override server default opt # branding plugin.branding.ABOUT_WINDOW_TITLE=About {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Instant Messaging -plugin.branding.LOADING=Loading plugin.branding.ABOUT_MENU_ENTRY=&About -plugin.branding.WELCOME_MESSAGE=
    The {1} is currently under active development. \ - The version you are running is only experimental and MAY NOT \ - work as expected. Please refer to {2} for more information.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright \ - jitsi.org. All rights reserved. Visit \ - https://jitsi.org.\ -
    -plugin.branding.LICENSE=
    Jitsi is distributed under \ - the terms of the \ - \ - Apache License 2.0.
    +plugin.branding.COPYRIGHT_LICENSE=
    Copyright 2003-{1} \ + {3}, All rights reserved.\ +

    {4} is distributed under \ + the terms of the {6}.
    plugin.busylampfield.PICKUP=Pickup call diff --git a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java index a010592..1f75f1d 100644 --- a/src/net/java/sip/communicator/plugin/branding/AboutWindow.java +++ b/src/net/java/sip/communicator/plugin/branding/AboutWindow.java @@ -20,6 +20,8 @@ package net.java.sip.communicator.plugin.branding; import java.awt.*; import java.awt.event.*; import java.io.*; +import java.net.*; +import java.util.*; import javax.imageio.*; import javax.swing.*; @@ -56,9 +58,6 @@ public class AboutWindow */ private static final long serialVersionUID = 0L; - /** - * The global/shared AboutWindow currently showing. - */ private static AboutWindow aboutWindow; /** @@ -120,8 +119,10 @@ public class AboutWindow ResourceManagementService resources = BrandingActivator.getResources(); - String applicationName - = resources.getSettingsString("service.gui.APPLICATION_NAME"); + String applicationName = + resources.getSettingsString("service.gui.APPLICATION_NAME"); + String website = + resources.getSettingsString("service.gui.APPLICATION_WEB_SITE"); this.setTitle( resources.getI18NString("plugin.branding.ABOUT_WINDOW_TITLE", @@ -141,14 +142,10 @@ public class AboutWindow .createEmptyBorder(15, 15, 15, 15)); textPanel.setOpaque(false); - JLabel titleLabel = null; - if (isApplicationNameShown()) - { - titleLabel = new JLabel(applicationName); - titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28)); - titleLabel.setForeground(Constants.TITLE_COLOR); - titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - } + JLabel titleLabel = new JLabel(applicationName); + titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 28)); + titleLabel.setForeground(Constants.TITLE_COLOR); + titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); // Force the use of the custom text field UI in order to fix an // incorrect rendering on Ubuntu. @@ -181,7 +178,6 @@ public class AboutWindow int logoAreaFontSize = resources.getSettingsInt("plugin.branding.ABOUT_LOGO_FONT_SIZE"); - // FIXME: the message exceeds the window length JTextArea logoArea = new JTextArea(resources.getI18NString( "plugin.branding.LOGO_MESSAGE")); @@ -192,7 +188,6 @@ public class AboutWindow logoArea.setLineWrap(true); logoArea.setWrapStyleWord(true); logoArea.setEditable(false); - logoArea.setPreferredSize(new Dimension(100, 20)); logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); logoArea.setBorder(BorderFactory .createEmptyBorder(30, DEFAULT_TEXT_INDENT, 0, 0)); @@ -200,44 +195,38 @@ public class AboutWindow StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); rightsArea.setContentType("text/html"); + String host = website; + try + { + host = new URL(website).getHost(); + } + catch (Exception ex) + {} + rightsArea.appendToEnd(resources.getI18NString( - "plugin.branding.COPYRIGHT", + "plugin.branding.COPYRIGHT_LICENSE", new String[] - { Constants.TEXT_COLOR })); - - rightsArea.setPreferredSize(new Dimension(50, 20)); - rightsArea - .setBorder(BorderFactory + { + Constants.TEXT_COLOR, + Integer.toString(Calendar.getInstance().get(Calendar.YEAR)), + website, + host, + applicationName, + "http://www.apache.org/licenses/LICENSE-2.0", + "Apache License 2.0" + })); + + rightsArea.setBorder(BorderFactory .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); rightsArea.setOpaque(false); rightsArea.setEditable(false); rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); rightsArea.addHyperlinkListener(this); - StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); - licenseArea.setContentType("text/html"); - licenseArea.appendToEnd(resources. - getI18NString("plugin.branding.LICENSE", - new String[]{Constants.TEXT_COLOR})); - - licenseArea.setPreferredSize(new Dimension(50, 20)); - licenseArea.setBorder( - BorderFactory.createEmptyBorder( - resources.getSettingsInt("plugin.branding.ABOUT_PARAGRAPH_GAP"), - DEFAULT_TEXT_INDENT, - 0, 0)); - licenseArea.setOpaque(false); - licenseArea.setEditable(false); - licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - licenseArea.addHyperlinkListener(this); - - if (titleLabel != null) - textPanel.add(titleLabel); - + textPanel.add(titleLabel); textPanel.add(versionLabel); textPanel.add(logoArea); textPanel.add(rightsArea); - textPanel.add(licenseArea); JButton okButton = new JButton(resources.getI18NString("service.gui.OK")); @@ -375,18 +364,17 @@ public class AboutWindow { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - String href = e.getDescription(); - ServiceReference serviceReference = BrandingActivator - .getBundleContext().getServiceReference( - BrowserLauncherService.class.getName()); + ServiceReference serviceReference = + BrandingActivator.getBundleContext().getServiceReference( + BrowserLauncherService.class); if (serviceReference != null) { BrowserLauncherService browserLauncherService - = (BrowserLauncherService) BrandingActivator + = BrandingActivator .getBundleContext().getService(serviceReference); - browserLauncherService.openURL(href); + browserLauncherService.openURL(e.getDescription()); } } } @@ -463,25 +451,4 @@ public class AboutWindow dispose(); } } - - /** - * Indicates if the application name should be shown. - * - * @return true if the application name should be shown, - * false - otherwise - */ - private boolean isApplicationNameShown() - { - String showApplicationNameProp - = BrandingActivator.getResources().getSettingsString( - "plugin.branding.IS_APPLICATION_NAME_SHOWN"); - - if (showApplicationNameProp != null - && showApplicationNameProp.length() > 0) - { - return Boolean.parseBoolean(showApplicationNameProp); - } - - return true; - } } diff --git a/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java b/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java index f145dfb..f6de958 100644 --- a/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java +++ b/src/net/java/sip/communicator/plugin/branding/BrandingActivator.java @@ -33,87 +33,12 @@ import org.osgi.framework.*; */ public class BrandingActivator extends AbstractServiceDependentActivator - implements BundleListener { private final Logger logger = Logger.getLogger(BrandingActivator.class); - - /** - * The name of the boolean property which indicates whether the splash - * screen (i.e. WelcomeWindow) is to be shown or to not be - * utilized for the sake of better memory consumption and faster startup. - */ - private static final String PNAME_SHOW_SPLASH_SCREEN - = "net.java.sip.communicator.plugin.branding.SHOW_SPLASH_SCREEN"; - private static BundleContext bundleContext; - private static ResourceManagementService resourcesService; /** - * The welcome window. - */ - private WelcomeWindow welcomeWindow; - - @Override - public void start(BundleContext bc) throws Exception - { - super.start(bc); - - ConfigurationService config = getConfigurationService(); - boolean showSplashScreen - = (config == null) - ? true /* - * Having no ConfigurationService reference is not good - * for the application so we are better off with the - * splash screen to actually see which bundles get loaded - * and maybe be able to debug the problem. - */ - : config.getBoolean(PNAME_SHOW_SPLASH_SCREEN, false); - - /* - * WelcomeWindow is huge because it has a large image spread all over it - * so, given it's only necessary before the UIService gets activated, we - * certainly don't want to keep it around (e.g. as an instance field or - * as a final variable used inside a BundleListener which never gets - * removed). - */ - if (showSplashScreen) - { - welcomeWindow = new WelcomeWindow(); - welcomeWindow.pack(); - welcomeWindow.setVisible(true); - } - else - welcomeWindow = null; - - bundleContext.addBundleListener(this); - } - - /** - * Bundle has been started if welcome window is available and visible - * update it to show the bundle activity. - * @param evt - */ - public synchronized void bundleChanged(BundleEvent evt) - { - if (welcomeWindow != null - && welcomeWindow.isShowing() - && (evt.getType() == BundleEvent.STARTED)) - { - /* - * The IBM JRE on GNU/Linux reports the Bundle-Name as null while - * the SUN JRE reports it as non-null. Just prevent the throwing of - * a NullPointerException because displaying the Bundle-Name isn't - * vital anyway. - */ - Object bundleName = evt.getBundle().getHeaders().get("Bundle-Name"); - - welcomeWindow.setBundle( - (bundleName == null) ? null : bundleName.toString()); - } - } - - /** * Setting context to the activator, as soon as we have one. * * @param context the context to set. @@ -141,31 +66,12 @@ public class BrandingActivator @Override public void start(Object dependentService) { - // UI-Service started. - - /* - * Don't let bundleContext retain a reference to this - * listener because it'll retain a reference to - * welcomeWindow. Besides, we're no longer interested in - * handling events so it doesn't make sense to even retain - * this listener. - */ - bundleContext.removeBundleListener(this); - // register the about dialog menu entry registerMenuEntry((UIService)dependentService); - - if (welcomeWindow != null) - { - synchronized(this) - { - welcomeWindow.close(); - welcomeWindow = null; - } - } } - public void stop(BundleContext arg0) throws Exception + @Override + public void stop(BundleContext context) throws Exception { } @@ -185,7 +91,6 @@ public class BrandingActivator private boolean registerMenuEntryMacOSX(UIService uiService) { - Exception exception = null; try { Class clazz = @@ -195,28 +100,16 @@ public class BrandingActivator Object result = method.invoke(null, (Object[]) null); if (result instanceof Boolean) + { return ((Boolean) result).booleanValue(); + } } - catch (ClassNotFoundException ex) - { - exception = ex; - } - catch (IllegalAccessException ex) - { - exception = ex; - } - catch (InvocationTargetException ex) - { - exception = ex; - } - catch (NoSuchMethodException ex) + catch (Exception ex) { - exception = ex; + logger.error("Failed to register Mac OS X-specific About handling.", + ex); } - if (exception != null) - logger.error( - "Failed to register Mac OS X-specific About handling.", - exception); + return false; } @@ -272,17 +165,6 @@ public class BrandingActivator return bundleContext; } - private static ConfigurationService getConfigurationService() - { - ServiceReference serRef - = bundleContext - .getServiceReference(ConfigurationService.class.getName()); - return - (serRef == null) - ? null - : (ConfigurationService) bundleContext.getService(serRef); - } - /** * Returns the ResourceManagementService. * diff --git a/src/net/java/sip/communicator/plugin/branding/WelcomeWindow.java b/src/net/java/sip/communicator/plugin/branding/WelcomeWindow.java deleted file mode 100644 index 7cc78b8..0000000 --- a/src/net/java/sip/communicator/plugin/branding/WelcomeWindow.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * - * Copyright @ 2015 Atlassian Pty Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package net.java.sip.communicator.plugin.branding; - -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; -import java.io.*; - -import javax.imageio.*; -import javax.swing.*; - -import net.java.sip.communicator.plugin.desktoputil.*; - -import org.jitsi.service.resources.*; - -/** - * The WelcomeWindow is actually the splash screen shown while the - * application is loading. It displays the status of the loading process and - * some general information about the version, licenses and contact details. - * - * @author Yana Stamcheva - */ -public class WelcomeWindow extends JDialog -{ - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private static final String APPLICATION_NAME - = BrandingActivator.getResources() - .getSettingsString("service.gui.APPLICATION_NAME"); - - private static final int DEFAULT_TEXT_INDENT - = BrandingActivator.getResources() - .getSettingsInt("plugin.branding.SPLASH_SCREEN_TEXT_INDENT"); - - private static final int PREFERRED_HEIGHT = 330; - - private static final int PREFERRED_WIDTH = 570; - - private final JLabel bundleLabel = new JLabel(); - - /** - * Constructor. - */ - public WelcomeWindow() - { - JLabel titleLabel = new JLabel(APPLICATION_NAME); - - JLabel versionLabel = new JLabel(" " - + System.getProperty("sip-communicator.version")); - - JTextArea logoArea = new JTextArea( - BrandingActivator.getResources() - .getI18NString("plugin.branding.LOGO_MESSAGE")); - - StyledHTMLEditorPane rightsArea = new StyledHTMLEditorPane(); - - StyledHTMLEditorPane licenseArea = new StyledHTMLEditorPane(); - - JPanel textPanel = new JPanel(); - - Container mainPanel = new WindowBackground(); - - this.setTitle(APPLICATION_NAME); - - this.setModal(false); - this.setUndecorated(true); - - mainPanel.setLayout(new BorderLayout()); - - textPanel.setPreferredSize(new Dimension(470, 280)); - textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS)); - textPanel - .setBorder(BorderFactory.createEmptyBorder(15, 15, 0, 15)); - textPanel.setOpaque(false); - - this.initTitleLabel(titleLabel); - - this.initVersionLabel(versionLabel); - - this.initLogoArea(logoArea); - - this.initRightsArea(rightsArea); - - this.initLicenseArea(licenseArea); - - Component loadingPanel = initLoadingPanel(); - - textPanel.add(titleLabel); - textPanel.add(versionLabel); - textPanel.add(logoArea); - textPanel.add(rightsArea); - textPanel.add(licenseArea); - - mainPanel.add(textPanel, BorderLayout.CENTER); - mainPanel.add(loadingPanel, BorderLayout.SOUTH); - - this.getContentPane().add(mainPanel); - - this.setResizable(false); - - mainPanel.setPreferredSize( - new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT)); - - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - this.setLocation(screenSize.width / 2 - 527 / 2, - screenSize.height / 2 - 305 / 2); - - this.initCloseActions(); - } - - /** - * Initializes the title label. - * - * @param titleLabel the title label - */ - private void initTitleLabel(JLabel titleLabel) - { - titleLabel.setFont( - titleLabel.getFont().deriveFont(Font.BOLD, 28)); - titleLabel.setForeground(Constants.TITLE_COLOR); - titleLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - } - - /** - * Initializes the version label. - * - * @param versionLabel the version label - */ - private void initVersionLabel(JLabel versionLabel) - { - versionLabel.setFont( - versionLabel.getFont().deriveFont(Font.BOLD, 18)); - versionLabel.setForeground(Constants.TITLE_COLOR); - versionLabel.setAlignmentX(Component.RIGHT_ALIGNMENT); - } - - /** - * Initializes the logo area. - * - * @param logoArea the logo area - */ - private void initLogoArea(JTextArea logoArea) - { - int logoAreaFontSize = BrandingActivator.getResources(). - getSettingsInt("plugin.branding.ABOUT_LOGO_FONT_SIZE"); - - logoArea.setFont( - logoArea.getFont().deriveFont(Font.BOLD, logoAreaFontSize)); - logoArea.setForeground(Constants.TITLE_COLOR); - logoArea.setOpaque(false); - logoArea.setLineWrap(true); - logoArea.setWrapStyleWord(true); - logoArea.setEditable(false); - logoArea.setPreferredSize(new Dimension(100, 20)); - logoArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - logoArea.setBorder(BorderFactory - .createEmptyBorder(20, DEFAULT_TEXT_INDENT, 0, 0)); - } - - /** - * Initializes the copyright area. - * - * @param rightsArea the copyright area. - */ - private void initRightsArea(StyledHTMLEditorPane rightsArea) - { - rightsArea.setContentType("text/html"); - rightsArea.appendToEnd( - BrandingActivator.getResources().getI18NString( - "plugin.branding.WELCOME_MESSAGE", - new String[]{ - Constants.TEXT_COLOR, - APPLICATION_NAME, - BrandingActivator.getResources() - .getSettingsString("service.gui.APPLICATION_WEB_SITE") - })); - - rightsArea.setPreferredSize(new Dimension(50, 50)); - rightsArea - .setBorder(BorderFactory - .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); - rightsArea.setOpaque(false); - rightsArea.setEditable(false); - rightsArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - } - - /** - * Initializes the license area. - * - * @param licenseArea the license area. - */ - private void initLicenseArea(StyledHTMLEditorPane licenseArea) - { - licenseArea.setContentType("text/html"); - licenseArea.appendToEnd( - BrandingActivator.getResources().getI18NString( - "plugin.branding.LICENSE", - new String[] - { - Constants.TEXT_COLOR - })); - - licenseArea.setPreferredSize(new Dimension(50, 20)); - licenseArea.setBorder(BorderFactory - .createEmptyBorder(0, DEFAULT_TEXT_INDENT, 0, 0)); - licenseArea.setOpaque(false); - licenseArea.setEditable(false); - licenseArea.setAlignmentX(Component.RIGHT_ALIGNMENT); - } - - private JPanel initLoadingPanel() - { - ResourceManagementService resources = BrandingActivator.getResources(); - JLabel loadingLabel - = new JLabel( - resources.getI18NString("plugin.branding.LOADING") + ": "); - JPanel loadingPanel = new JPanel(new BorderLayout()); - - this.bundleLabel.setFont(loadingLabel.getFont().deriveFont(Font.PLAIN)); - - loadingPanel.setOpaque(false); - loadingPanel.add(loadingLabel, BorderLayout.WEST); - loadingPanel.add(bundleLabel, BorderLayout.CENTER); - - int loadingPanelBorder - = resources - .getSettingsInt("plugin.branding.LOADING_BUNDLE_PANEL_BORDER"); - - loadingPanel.setBorder( - BorderFactory.createEmptyBorder(loadingPanelBorder, - loadingPanelBorder, - loadingPanelBorder, - loadingPanelBorder)); - - int loadingPanelHeight - = resources - .getSettingsInt("plugin.branding.LOADING_BUNDLE_PANEL_HEIGHT"); - - loadingPanel.setPreferredSize( - new Dimension(PREFERRED_WIDTH, loadingPanelHeight)); - - return loadingPanel; - } - - /** - * Initializes close actions on mouse click and esc key. - */ - private void initCloseActions() - { - // Close the splash screen on simple click or Esc. - this.getGlassPane().addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - WelcomeWindow.this.close(); - } - }); - - this.getGlassPane().setVisible(true); - - ActionMap amap = this.getRootPane().getActionMap(); - - amap.put("close", new CloseAction()); - - InputMap imap = this.getRootPane().getInputMap( - JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); - - imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "close"); - } - - /** - * Disposes this window. - */ - protected void close() - { - this.dispose(); - } - - /** - * Sets the name of the currently loading bundle. - * - * @param bundleName the name of the bundle to display - */ - public void setBundle(String bundleName) - { - bundleLabel.setText(bundleName); - - bundleLabel.revalidate(); - bundleLabel.getParent().repaint(); - } - - /** - * The action invoked when user presses Escape key. - */ - private class CloseAction extends UIAction - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - public void actionPerformed(ActionEvent e) - { - WelcomeWindow.this.close(); - } - } - - /** - * Constructs the window background in order to have a background image. - */ - private static class WindowBackground - extends JPanel - { - /** - * Serial version UID. - */ - private static final long serialVersionUID = 0L; - - private BufferedImage cache; - - private int cacheHeight; - - private int cacheWidth; - - private final Image image; - - public WindowBackground() - { - setOpaque(true); - - Image image = null; - try - { - image = - ImageIO.read(BrandingActivator.getResources().getImageURL( - "plugin.branding.SPLASH_SCREEN_BACKGROUND")); - } - catch (IOException e) - { - e.printStackTrace(); - } - this.image = image; - - if (image != null) - { - setPreferredSize(new Dimension(image.getWidth(this), image - .getHeight(this))); - } - } - - @Override - protected void paintComponent(Graphics g) - { - super.paintComponent(g); - - g = g.create(); - try - { - internalPaintComponent(g); - } - finally - { - g.dispose(); - } - } - - private void internalPaintComponent(Graphics g) - { - AntialiasingManager.activateAntialiasing(g); - - Graphics2D g2 = (Graphics2D) g; - - /* - * Drawing an Image with a data layout and color model compatible - * with this JPanel is magnitudes faster so create and use such an - * Image from the original drawn by this instance. - */ - int width = getWidth(); - int height = getHeight(); - boolean imageIsChanging = false; - if ((cache == null) || (cacheWidth != width) - || (cacheHeight != height)) - { - cache = - g2.getDeviceConfiguration().createCompatibleImage(width, - height); - cacheWidth = width; - cacheHeight = height; - - Graphics2D cacheGraphics = cache.createGraphics(); - try - { - super.paintComponent(cacheGraphics); - - AntialiasingManager.activateAntialiasing(cacheGraphics); - - imageIsChanging = - !cacheGraphics.drawImage(image, 0, 0, null); - - cacheGraphics.setColor(new Color(150, 150, 150)); - cacheGraphics.drawRoundRect(0, 0, width - 1, height - 1, 5, - 5); - } - finally - { - cacheGraphics.dispose(); - } - } - - g2.drawImage(cache, 0, 0, null); - - /* - * Once the original Image drawn by this instance has been fully - * loaded, we're free to use its "compatible" caching representation - * for the purposes of optimized execution speed. - */ - if (imageIsChanging) - { - cache = null; - } - } - } -} -- cgit v1.1 From 4c8ec00a2ae5233bf99c03808e7784c6246b3246 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 18:53:40 +0100 Subject: Let the config service override the embedded resources --- .../impl/resources/ResourceManagementActivator.java | 20 ++++++++++++++++++++ .../resources/ResourceManagementServiceImpl.java | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/net/java/sip/communicator/impl/resources/ResourceManagementActivator.java b/src/net/java/sip/communicator/impl/resources/ResourceManagementActivator.java index 6c76906..1e7e7e4 100644 --- a/src/net/java/sip/communicator/impl/resources/ResourceManagementActivator.java +++ b/src/net/java/sip/communicator/impl/resources/ResourceManagementActivator.java @@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.resources; import net.java.sip.communicator.util.*; +import org.jitsi.service.configuration.*; import org.jitsi.service.resources.*; import org.osgi.framework.*; @@ -31,6 +32,7 @@ public class ResourceManagementActivator extends SimpleServiceActivator { static BundleContext bundleContext; + private static ConfigurationService configService; /** * Creates new instance of ResourceManagementActivator @@ -68,4 +70,22 @@ public class ResourceManagementActivator { return new ResourceManagementServiceImpl(); } + + /** + * Returns the ConfigurationService obtained from the bundle + * context. + * @return the ConfigurationService obtained from the bundle + * context + */ + public static ConfigurationService getConfigService() + { + if(configService == null) + { + configService + = ServiceUtils.getService( + bundleContext, + ConfigurationService.class); + } + return configService; + } } diff --git a/src/net/java/sip/communicator/impl/resources/ResourceManagementServiceImpl.java b/src/net/java/sip/communicator/impl/resources/ResourceManagementServiceImpl.java index d116fea..1cc2dcf 100644 --- a/src/net/java/sip/communicator/impl/resources/ResourceManagementServiceImpl.java +++ b/src/net/java/sip/communicator/impl/resources/ResourceManagementServiceImpl.java @@ -344,4 +344,24 @@ public class ResourceManagementServiceImpl { return SkinJarBuilder.createBundleFromZip(zipFile, getImagePack()); } + + /** + * Gets the specified setting from the config service if present, otherwise + * from the embedded resources (resources/config/defaults.properties). + * + * @param key The setting to lookup. + * @return The setting for the key or {@code null} if not found. + */ + @Override + public String getSettingsString(String key) + { + Object configValue = ResourceManagementActivator + .getConfigService().getProperty(key); + if (configValue == null) + { + configValue = super.getSettingsString(key); + } + + return configValue == null ? null : configValue.toString(); + } } -- cgit v1.1 From 95f56b342208fd3b2df2796247344d29b4d3abc7 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 18:56:13 +0100 Subject: General config: correctly show which key is used to send messages --- src/net/java/sip/communicator/util/ConfigurationUtils.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/net/java/sip/communicator/util/ConfigurationUtils.java b/src/net/java/sip/communicator/util/ConfigurationUtils.java index db9fa3b..d24426d 100644 --- a/src/net/java/sip/communicator/util/ConfigurationUtils.java +++ b/src/net/java/sip/communicator/util/ConfigurationUtils.java @@ -438,17 +438,9 @@ public class ConfigurationUtils autoPopupNewMessage = true; // Load the "sendMessageCommand" property. - String messageCommandProperty - = "service.gui.SEND_MESSAGE_COMMAND"; - String messageCommand = configService.getString(messageCommandProperty); - - if(messageCommand == null) - messageCommand - = UtilActivator.getResources() - .getSettingsString(messageCommandProperty); - - if(messageCommand == null || messageCommand.length() == 0) - sendMessageCommand = messageCommand; + String messageCommandProperty = "service.gui.SEND_MESSAGE_COMMAND"; + sendMessageCommand = UtilActivator.getResources() + .getSettingsString(messageCommandProperty); // Load the showCallPanel property. String callPanelShown = configService.getString( -- cgit v1.1 From 225628c541c41b865049a0a1b1ec2ee08fe710d4 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 19:53:00 +0100 Subject: Update zrtp4j Closes #303 jitsi/zrtp4j@beb6723b2e13e27710e38ea9b64f2da8d9a395a3 Local build --- .classpath | 2 +- build.xml | 43 +-------------------- .../zrtp4j-light-4.1.0-jitsi-1-SNAPSHOT.jar | Bin 0 -> 214756 bytes lib/installer-exclude/zrtp4j-light.jar | Bin 189342 -> 0 bytes nbproject/project.xml | 2 +- 5 files changed, 4 insertions(+), 43 deletions(-) create mode 100644 lib/installer-exclude/zrtp4j-light-4.1.0-jitsi-1-SNAPSHOT.jar delete mode 100644 lib/installer-exclude/zrtp4j-light.jar diff --git a/.classpath b/.classpath index 303f939..0e8169c 100755 --- a/.classpath +++ b/.classpath @@ -72,7 +72,7 @@ - + diff --git a/build.xml b/build.xml index c273fb8..b7e8efb 100644 --- a/build.xml +++ b/build.xml @@ -950,7 +950,7 @@ bundle-update,bundle-plugin-update, bundle-plugin-simpleaccreg,bundle-plugin-generalconfig, bundle-plugin-googletalkaccregwizz,bundle-argdelegation-service, - bundle-argdelegation,bundle-zrtp4j,bundle-json, + bundle-argdelegation,bundle-json, bundle-filehistory,bundle-metahistory,bundle-metahistory-slick, bundle-plugin-ippiaccregwizz, bundle-plugin-otr,bundle-plugin-iptelaccregwizz, @@ -1005,6 +1005,7 @@ +
    @@ -2145,46 +2146,6 @@ javax.swing.event, javax.swing.border"/> - - - - - - - - - - - - - - - - src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light-4.1.0-jitsi-1-SNAPSHOT.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 7d7da7a39356890a663eea993e4fcaefc8a28066 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sat, 14 Jan 2017 22:36:00 +0100 Subject: Fix last message edit impersonation Closes #299 --- .../sip/communicator/impl/gui/main/chat/ChatConversationPanel.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java index 127e28b..0283e25 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatConversationPanel.java @@ -790,8 +790,6 @@ public class ChatConversationPanel */ public void correctMessage(final ChatMessage chatMessage) { - lastMessageUID = chatMessage.getMessageUID(); - if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(new Runnable() @@ -805,6 +803,11 @@ public class ChatConversationPanel } String correctedUID = chatMessage.getCorrectedMessageUID(); + if (correctedUID != null && correctedUID.equals(lastMessageUID)) + { + lastMessageUID = chatMessage.getMessageUID(); + } + Element root = document.getDefaultRootElement(); Element correctedMsgElement = document.getElement(root, -- cgit v1.1 From 79a3a28b3421f06960871db0c4fb6927b9c39575 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 Jan 2017 01:53:25 +0100 Subject: BLF: Enable plugin and add workaround for Asterisk --- lib/felix.client.run.properties | 3 +- .../sip/OperationSetTelephonyBLFSipImpl.java | 72 +++++++++++++++++----- .../sip/ProtocolProviderServiceSipImpl.java | 12 ++-- .../plugin/busylampfield/BLFActivator.java | 10 +-- .../service/protocol/OperationSetTelephonyBLF.java | 18 +++++- 5 files changed, 86 insertions(+), 29 deletions(-) diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index ad9a08a..d5d8889 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -230,7 +230,8 @@ felix.auto.start.67= \ reference:file:sc-bundles/phonenumbercontactsource.jar \ reference:file:sc-bundles/demuxcontactsource.jar \ reference:file:sc-bundles/usersearch.jar \ - reference:file:sc-bundles/propertieseditor.jar + reference:file:sc-bundles/propertieseditor.jar \ + reference:file:sc-bundles/plugin-blf.jar # Level 68 is for profiler4j. Either don't use it or change the build.xml file # accordingly. diff --git a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyBLFSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyBLFSipImpl.java index 644c85a..a9aefbe 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyBLFSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyBLFSipImpl.java @@ -72,6 +72,10 @@ public class OperationSetTelephonyBLFSipImpl * Account property suffix to set/provision monitored line group. */ public static final String BLF_LINE_GROUP_ACC_PROP_PREFIX = "Group"; + /** + * Account property suffix to set/provision monitored line pickup template. + */ + public static final String BLF_LINE_PICKUP_ACC_PROP_PREFIX = "Pickup"; /** * The name of the event package supported by @@ -195,7 +199,7 @@ public class OperationSetTelephonyBLFSipImpl String[] lineValues = lines.get(ix); if(lineValues == null) { - lineValues = new String[3]; + lineValues = new String[4]; lines.put(ix, lineValues); } @@ -211,13 +215,17 @@ public class OperationSetTelephonyBLFSipImpl { lineValues[2] = entryValue; } + else if(pName.contains(BLF_LINE_PICKUP_ACC_PROP_PREFIX)) + { + lineValues[3] = entryValue; + } } for(Map.Entry en : lines.entrySet()) { String[] vals = en.getValue(); - this.lines.add(new Line(vals[0], vals[1], vals[2], this.provider)); + this.lines.add(new Line(vals[0], vals[1], vals[2], vals[3], this.provider)); } } @@ -263,16 +271,25 @@ public class OperationSetTelephonyBLFSipImpl if(details == null) return; - if(StringUtils.isNullOrEmpty(details.callID) - || StringUtils.isNullOrEmpty(details.localTag) - || StringUtils.isNullOrEmpty(details.remoteTag)) - return; - // replaces Address targetAddress = null; try { - targetAddress = provider.parseAddressString(line.getAddress()); + String address = line.getAddress(); + if(asteriskMode(details)) + { + // broken mode for Asterisk, doesn't provide us with + // the proper call-id, etc. attributes. + // send an unspecified pickup-call if a template is set + if (StringUtils.isNullOrEmpty(line.getPickupTemplate(), true)) + { + return; + } + + address = line.getPickupTemplate().replace("\\1", address); + } + + targetAddress = provider.parseAddressString(address); } catch (ParseException ex) { @@ -281,6 +298,16 @@ public class OperationSetTelephonyBLFSipImpl OperationFailedException.ILLEGAL_ARGUMENT, ex, logger); } + OperationSetBasicTelephonySipImpl telOpSet + = (OperationSetBasicTelephonySipImpl)provider + .getOperationSet(OperationSetBasicTelephony.class); + + if (asteriskMode(details)) + { + telOpSet.createOutgoingCall(targetAddress, null, null); + return; + } + Replaces replacesHeader = null; SipURI sipURI = (SipURI) targetAddress.getURI(); @@ -315,12 +342,14 @@ public class OperationSetTelephonyBLFSipImpl OperationFailedException.INTERNAL_ERROR, ex, logger); } - OperationSetBasicTelephonySipImpl telOpSet - = (OperationSetBasicTelephonySipImpl)provider - .getOperationSet(OperationSetBasicTelephony.class); - - CallSipImpl call - = telOpSet.createOutgoingCall(targetAddress, null, null); + telOpSet.createOutgoingCall(targetAddress, null, null); + } + + private boolean asteriskMode(LineDetails details) + { + return StringUtils.isNullOrEmpty(details.callID) + || StringUtils.isNullOrEmpty(details.localTag) + || StringUtils.isNullOrEmpty(details.remoteTag); } /** @@ -549,6 +578,8 @@ public class OperationSetTelephonyBLFSipImpl Node dialogNode = dialogList.item(i); Element dialogElem = (Element)dialogNode; + details.id = dialogElem.getAttribute("id"); + details.direction = dialogElem.getAttribute("direction"); details.callID = dialogElem.getAttribute("call-id"); details.localTag = dialogElem.getAttribute("local-tag"); details.remoteTag = dialogElem.getAttribute("remote-tag"); @@ -698,12 +729,25 @@ public class OperationSetTelephonyBLFSipImpl */ private class LineDetails { + /** * The current status of the line, the last event fired for it. */ int lastStatusEvent = BLFStatusEvent.STATUS_OFFLINE; /** + * id of the dialog. Mandatory. + */ + String id = null; + + /** + * either initiator or recipient, and indicates whether the observed + * user was the initiator of the dialog, or the recipient of the INVITE + * that created it. + */ + String direction; + + /** * call-id of the dialog if any, used for remote pickup. */ String callID = null; diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index 009af86..a2a98b8 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -1589,16 +1589,16 @@ public class ProtocolProviderServiceSipImpl Set instances = new HashSet(); BundleContext context = SipActivator.getBundleContext(); - ServiceReference[] references = context.getServiceReferences( - ProtocolProviderService.class.getName(), - null - ); - for(ServiceReference reference : references) + Collection> references = + context.getServiceReferences(ProtocolProviderService.class, + null); + for(ServiceReference ref : references) { - Object service = context.getService(reference); + ProtocolProviderService service = context.getService(ref); if(service instanceof ProtocolProviderServiceSipImpl) instances.add((ProtocolProviderServiceSipImpl) service); } + return instances; } catch(InvalidSyntaxException ex) diff --git a/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java b/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java index 036442b..94ea374 100644 --- a/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java +++ b/src/net/java/sip/communicator/plugin/busylampfield/BLFActivator.java @@ -181,15 +181,11 @@ public class BLFActivator } else { - BLFContactSourceService css - = new BLFContactSourceService( + BLFContactSourceService css = new BLFContactSourceService( groupName, currentBLFGroups.size() + 1); - serviceReg = (ServiceRegistration) - bundleContext.registerService( - ContactSourceService.class.getName(), - css, - null); + serviceReg = bundleContext.registerService( + ContactSourceService.class, css, null); currentBLFGroups.put(groupName, serviceReg); css.addLine(line); diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetTelephonyBLF.java b/src/net/java/sip/communicator/service/protocol/OperationSetTelephonyBLF.java index 028c2ae..f6a50dc 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetTelephonyBLF.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetTelephonyBLF.java @@ -80,6 +80,11 @@ public interface OperationSetTelephonyBLF private String group; /** + * Asterisk pickup prefix. + */ + private String pickupTemplate; + + /** * The parent provider. */ private ProtocolProviderService provider; @@ -90,14 +95,16 @@ public interface OperationSetTelephonyBLF * @param address the address of the line. * @param name the display name if any * @param group the group name if any + * @param pickup the pickup dial template * @param provider the parent provider. */ - public Line(String address, String name, String group, + public Line(String address, String name, String group, String pickup, ProtocolProviderService provider) { this.address = address; this.name = name; this.group = group; + this.pickupTemplate = pickup; this.provider = provider; } @@ -129,6 +136,15 @@ public interface OperationSetTelephonyBLF } /** + * The pickup template. + * @return the pickup template. + */ + public String getPickupTemplate() + { + return pickupTemplate; + } + + /** * The provider. * @return the provider. */ -- cgit v1.1 From 3f28fcef07c39ab735917199b1883b4166566546 Mon Sep 17 00:00:00 2001 From: damencho Date: Wed, 18 Jan 2017 14:06:16 -0600 Subject: Adds a property to enable rtpTranslator for conferences. Account property that enables rtpTranslator instead of mixing in conferences. --- .../sip/communicator/service/protocol/Call.java | 12 +++++ .../service/protocol/ProtocolProviderFactory.java | 9 ++++ .../service/protocol/media/MediaAwareCall.java | 2 +- .../protocol/media/MediaAwareCallConference.java | 52 ++++++++++++++++++++-- 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/net/java/sip/communicator/service/protocol/Call.java b/src/net/java/sip/communicator/service/protocol/Call.java index d342373..a952cfd 100644 --- a/src/net/java/sip/communicator/service/protocol/Call.java +++ b/src/net/java/sip/communicator/service/protocol/Call.java @@ -111,6 +111,13 @@ public abstract class Call private boolean isAutoAnswer = false; /** + * The indicator which determines whether any telephony conference + * represented by this instance is mixing or relaying. + * By default what can be mixed is mixed (audio) and rest is relayed. + */ + protected final boolean useTranslator; + + /** * Creates a new Call instance. * * @param sourceProvider the proto provider that created us. @@ -133,6 +140,11 @@ public abstract class Call = accountID.getAccountPropertyBoolean( ProtocolProviderFactory.DEFAULT_SIPZRTP_ATTRIBUTE, true); + + useTranslator + = accountID.getAccountPropertyBoolean( + ProtocolProviderFactory.USE_TRANSLATOR_IN_CONFERENCE, + false); } /** diff --git a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java index 2efdc29..561a092 100644 --- a/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java +++ b/src/net/java/sip/communicator/service/protocol/ProtocolProviderFactory.java @@ -376,6 +376,15 @@ public abstract class ProtocolProviderFactory = "USE_JITSI_VIDEO_BRIDGE"; /** + * The name of the boolean account property which indicates whether Jitsi + * will use translator for media, instead of mixing, for conference + * calls. + * By default if supported mixing is used (audio mixed, video relayed). + */ + public static final String USE_TRANSLATOR_IN_CONFERENCE + = "USE_TRANSLATOR_IN_CONFERENCE"; + + /** * The property name prefix for all stun server properties. We generally use * this prefix in conjunction with an index which is how we store multiple * servers. diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java index f9b6c2f..2bf802b 100644 --- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java +++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java @@ -906,7 +906,7 @@ public abstract class MediaAwareCall< @Override protected CallConference createConference() { - return new MediaAwareCallConference(); + return new MediaAwareCallConference(false, this.useTranslator); } /** diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java index da34f2c..81e917c 100644 --- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java +++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallConference.java @@ -93,6 +93,21 @@ public class MediaAwareCallConference private RTPTranslator videoRTPTranslator; /** + * The RTPTranslator which forwards autio RTP and RTCP traffic + * between the CallPeers of the Calls participating in + * this telephony conference when the local peer is acting as a conference + * focus. + */ + private RTPTranslator audioRTPTranslator; + + /** + * The indicator which determines whether the telephony conference + * represented by this instance is mixing or relaying. + * By default what can be mixed is mixed (audio) and rest is relayed. + */ + private boolean translator = false; + + /** * Initializes a new MediaAwareCallConference instance. */ public MediaAwareCallConference() @@ -111,8 +126,25 @@ public class MediaAwareCallConference */ public MediaAwareCallConference(boolean jitsiVideobridge) { + this(jitsiVideobridge, false); + } + + /** + * Initializes a new MediaAwareCallConference instance which is to + * optionally utilize the Jitsi Videobridge server-side telephony + * conferencing technology. + * + * @param jitsiVideobridge true if the telephony conference + * represented by the new instance is to utilize the Jitsi Videobridge + * server-side telephony conferencing technology; otherwise, false + */ + public MediaAwareCallConference(boolean jitsiVideobridge, + boolean translator) + { super(jitsiVideobridge); + this.translator = translator; + int mediaTypeCount = MediaType.values().length; devices = new MediaDevice[mediaTypeCount]; @@ -269,6 +301,7 @@ public class MediaAwareCallConference * necessary. */ if ((!OSUtils.IS_ANDROID || isConferenceFocus()) + && !this.translator /* * We can use the AudioMixer only if the device is * able to capture (because the AudioMixer will push @@ -325,8 +358,6 @@ public class MediaAwareCallConference */ public RTPTranslator getRTPTranslator(MediaType mediaType) { - RTPTranslator rtpTranslator = null; - /* * XXX A mixer is created for audio even when the local peer is not a * conference focus in order to enable additional functionality. @@ -348,9 +379,22 @@ public class MediaAwareCallConference .getMediaService() .createRTPTranslator(); } - rtpTranslator = videoRTPTranslator; + return videoRTPTranslator; } - return rtpTranslator; + + if (this.translator) + { + if(audioRTPTranslator == null) + { + audioRTPTranslator + = ProtocolMediaActivator + .getMediaService() + .createRTPTranslator(); + } + return audioRTPTranslator; + } + + return null; } /** -- cgit v1.1 From 999dd2a04be03a6250e9dbb8a01e883c57e6f95a Mon Sep 17 00:00:00 2001 From: damencho Date: Wed, 18 Jan 2017 14:07:16 -0600 Subject: Bumps ice4j version in maven dependencies. --- m2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m2/pom.xml b/m2/pom.xml index 25d5efa..b74b656 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -57,7 +57,7 @@ ${project.groupId} ice4j - 1.1-20160706.192041-13 + 2.0-20170111.193659-7 -- cgit v1.1 From 38e1ebc48aa042bfcffa2c4763b9fdb1a6b1b754 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Sun, 15 Jan 2017 18:52:30 +0100 Subject: Don't split resource strings, remove unused resources --- resources/languages/resources.properties | 115 +++------------------ .../impl/certificate/CertificateServiceImpl.java | 9 +- .../AbstractDeviceConfigurationListener.java | 3 +- .../neomedia/AudioDeviceConfigurationListener.java | 18 ++-- .../impl/neomedia/MediaConfigurationImpl.java | 3 +- .../codec/video/h264/ConfigurationPanel.java | 3 +- .../plugin/jabberaccregwizz/AccountPanel.java | 11 +- .../keybindingchooser/chooser/BindingChooser.java | 44 +------- .../communicator/plugin/otr/ScOtrEngineImpl.java | 20 ++-- .../plugin/update/UpdateServiceImpl.java | 32 +++--- 10 files changed, 56 insertions(+), 202 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 89de334..4897b99 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -43,7 +43,6 @@ service.gui.ACCOUNT_ME=Me service.gui.ACCOUNT_REGISTRATION_WIZARD=Account Registration Wizard service.gui.ACCOUNTS=Accounts service.gui.ADD=&Add -service.gui.ADD_ACCOUNT=Add account service.gui.ADD_CONTACT=&Add contact service.gui.ADD_AUTHORIZED_CONTACT=Add {0} to your contact list service.gui.ADD_CONTACT_TO_CONTACTLIST=Add the contact to your contact list @@ -53,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Add contact Error service.gui.ADD_CONTACT_EXIST_ERROR=The contact {0} already exists in your contact list. service.gui.ADD_CONTACT_NETWORK_ERROR=Server did not respond to our request adding contact with id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Failed to add contact with id: {0}. Operation not supported. -service.gui.ADD_CONTACT_IDENTIFIER=In the field below enter the identifier of the contact you would like to add. -service.gui.ADD_CONTACT_WIZARD=Add contact wizard service.gui.ADD_CONTACT_NOT_CONNECTED=You need to be connected in in order to add a contact. Please sign in to the selected provider and try again. service.gui.ADD_GROUP_LOCAL_ERROR=Failed to add group with name: {0}. The problem occurred during a local IO operation. service.gui.ADD_GROUP_EXIST_ERROR=The group {0} already exists in your contact list. Please choose another name. service.gui.ADD_GROUP_NET_ERROR=Failed to add group with name: {0}. The problem occurred due to a network failure. Please check your network connection and try again. service.gui.ADD_GROUP_ERROR=Failed to add group with name: {0}. service.gui.ADD_GROUP_EMPTY_NAME=The group name must not be empty. -service.gui.ADD_GROUP=Create group -service.gui.ADD_SUBCONTACT=&Add subcontact service.gui.ADDRESS=Address service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Advanced -service.gui.ALL=&All service.gui.ALL_CONTACTS=&All contacts service.gui.ALTERNATE_ADDRESS=Alternate address service.gui.APPLY=&Apply @@ -76,7 +70,6 @@ service.gui.AT=at service.gui.AUTHORIZE=&Authorize service.gui.AUTHORIZATION_ACCEPTED={0} has accepted your authorization request. service.gui.AUTHENTICATION_FAILED=Authentication failed for {0}. The password you entered is not valid. -service.gui.AUTHENTICATION_REQUESTED=Authentication requested service.gui.AUTHENTICATION_REQUESTED_SERVER=The {0} server has requested your authentication. service.gui.AUTHENTICATION_REJECTED={0} has rejected your authorization request. service.gui.AUTHENTICATION_WINDOW_TITLE={0} authentication @@ -118,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=In the field below, you can enter your new nic service.gui.CHANGE_NICKNAME_ERROR=Error changing nickname service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nickname already exists service.gui.CHANGE_VIDEO_QUALITY=Change remote video quality -service.gui.CHAT_CONFERENCE_LABEL=Conferences service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}''s conference service.gui.CHAT_ROOM_ALREADY_JOINED=The {0} chat room is already joined. service.gui.CHAT_ROOM_CONFIGURATION={0} chat room configuration @@ -132,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=has left {0} service.gui.CHAT_ROOM_USER_KICKED=has been kicked from {0} service.gui.CHAT_ROOM_USER_QUIT=has quit {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Message sending is forbidden (voice revoked) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Saves the chat room for future use -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Removes the selected room from the list of saved rooms service.gui.CHAT_ROOM_NAME=Chat room name service.gui.CLEAR_CUSTOM_MESSAGES=Clear custom messages service.gui.ROOM_NAME=Chat Room -service.gui.AUTOJOIN=Autojoin service.gui.CHANGE_PASSWORD=Change password service.gui.CHAT_ROOM_NAME_INFO=In the field below enter the name of the chat room that you would like to create. service.gui.CHAT_ROOM_NOT_EXIST=The {0} room was not found in the {1} server. Please verify if the name you typed is correct. service.gui.CHAT_ROOM_NOT_CONNECTED=You need to be logged in in order to join the {0} chat room. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=You need to be logged in in order to leave a chat room. -service.gui.CHAT_ROOM_NOT_JOINED=You need to be joined to the chat room in order to do further operations with it. service.gui.CHAT_ROOM_OPTIONS=Chat room options service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=The {0} chat room requires registration to be joined. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=The {0} chat room has requested a password. @@ -168,18 +156,15 @@ service.gui.CONNECTING=Connecting... service.gui.CONNECTING_STATUS=Connecting service.gui.CONNECTING_EARLY_MEDIA_STATUS=Connecting* service.gui.CONNECTION=Connection -service.gui.CONNECTION_FAILED_MSG=Connection failed for the following account: User name: {0}, Server name: {1}. Please check your network connection or contact your network administrator for more information. service.gui.CONNECTION_EXPIRED_MSG=You are currently disconnected from the {0} server. service.gui.CONTACT_NAME=ID or Number service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com service.gui.CONTACT_NAME_INFO=Add either an instant messaging address (such as jane.doe@example.com) or a VoIP number -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=The chosen {0} contact doesn''t support telephony. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=The chosen {0} contact doesn''t support chat conferencing. service.gui.CONTACT_PAUSED_TYPING={0} paused typing the message service.gui.CONTACT_TYPING={0} is typing a message service.gui.CONTACT_TYPING_SEND_FAILED=uh-oh...we couldn''t tell {0} that you were writing service.gui.CONTACT_INFO=&Contact info -service.gui.CONTACTLIST=Contactlist service.gui.CONTACTS=Contacts service.gui.COPY=&Copy service.gui.COPY_LINK=Copy &link @@ -189,17 +174,14 @@ service.gui.CREATE_CHAT_ROOM=&Create chat room... service.gui.CREATE_CHAT_ROOM_ERROR=Failed to create {0} chat room. service.gui.CREATE_CHAT_ROOM_WIZARD=Create chat room wizard service.gui.CREATE_CONFERENCE_CALL=&Create a conference call... -service.gui.CREATE_CONFERENCE_CHAT=&Create a conference chat... service.gui.CREATE_GROUP=&Create group... service.gui.CREATE_GROUP_NAME=In the field below enter the name of the group you would like to create. -service.gui.CREATE_FIRST_GROUP_WIZARD=Your contact list doesn't contain any groups. Please create a group first (File/Create group). service.gui.CREATE_VIDEO_BRIDGE=Create a &video bridge... service.gui.CREATE_VIDEO_BRIDGE_MENU=Create a &video bridge service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Create / Join video conference service.gui.CREATE_VIDEO_CONFERENCE=Create a new video conference for this chat room service.gui.CONTACT_INFO_NOT_SUPPORTED=This contact doesn't support web contact info service.gui.CUT=C&ut -service.gui.DATE=Date service.gui.DELETE=Delete service.gui.DENY=&Deny service.gui.DESKTOP_SHARING_WARNING=Are you sure you want to start screen sharing?
    Clicking OK will let people on this call see your screen. @@ -212,7 +194,6 @@ service.gui.DISCONNECTED_STATUS=Disconnected service.gui.DND_STATUS=Do not disturb service.gui.DO_NOT_ASK_AGAIN=Don't ask again service.gui.DO_NOT_SHOW_AGAIN=Don't show this message again -service.gui.DOWNLOAD_NOW=&Download now service.gui.DRAG_FOR_SHARING=Drag here anything you want to share... service.gui.DURATION=duration service.gui.DESTROY_CHATROOM=Destroy chat room @@ -233,7 +214,6 @@ service.gui.ERROR_RECEIVED_FROM=Error received from {0} service.gui.ESTIMATED_TIME=Estimated time: service.gui.EVENTS=Events service.gui.EXIT=E&xit -service.gui.EXTENDED_CRITERIA=Extended criteria service.gui.GENERAL=General service.gui.GENERAL_ERROR=General error service.gui.GROUP_NAME=Group name @@ -275,7 +255,6 @@ service.gui.FONT_ITALIC=Italic service.gui.FONT_SIZE=Size service.gui.FONT_STYLE=Style service.gui.FONT_UNDERLINE=Underline -service.gui.FROM={0} from {1} service.gui.GRANT_OWNERSHIP=Grant ownership... service.gui.GRANT_ADMIN=Grant administrator... service.gui.GRANT_MODERATOR=Grant moderator @@ -302,7 +281,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Are you sure you want to permanently remo service.gui.HISTORY_REMOVE_ERROR=Error removing locally stored messages. service.gui.HOME=Home service.gui.HOME_PAGE=Home page -service.gui.HOUR=Hour service.gui.ICE=ICE service.gui.IDENTIFIER=Identifier service.gui.IGNORE=&Ignore @@ -330,7 +308,6 @@ service.gui.JOIN=&Join service.gui.JOIN_AS=J&oin as service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Join an existing video conference service.gui.JOIN_VIDEO=Join video -service.gui.CLOSE_CHAT_ROOM_DIALOG=C&lose service.gui.JOB_TITLE=Job title service.gui.JOIN_CHAT_ROOM=&Join chat room... service.gui.JOIN_CHAT_ROOM_TITLE=Join chat room @@ -343,7 +320,6 @@ service.gui.KICK_FAILED=Kick failed service.gui.KICK_FAILED_GENERAL_ERROR=Failed to kick {0}. A general server error occurred. service.gui.KICK_FAILED_NOT_ALLOWED=Failed to kick {0}. The owner and the administrator of the room could not be kicked. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Failed to kick {0}. You don''t have enough privileges to do that. -service.gui.LAST=Last service.gui.LAST_NAME=Last name service.gui.LEAVE=&Leave service.gui.LIMIT_REACHED_FOR_IP=You have too many existing registrations from the local IP address and the {0} server doesn''t allow to open any more of them. @@ -363,7 +339,6 @@ service.gui.MESSAGE=Message service.gui.MISSED_CALLS_TOOL_TIP=Missed calls from: service.gui.MISSED_CALLS_MORE_TOOL_TIP= and {0} more service.gui.MODERATOR=moderator -service.gui.MORE=See more service.gui.MORE_LABEL=More service.gui.MOVE=Move service.gui.MOVE_SUBCONTACT=M&ove contact @@ -372,7 +347,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=The contact you have chosen is the same as \n service.gui.MOVE_SUBCONTACT_QUESTION=Are you sure you want to move {0} to {1}? service.gui.MOVE_TO_GROUP=&Move to group service.gui.MOVE_CONTACT=Move Contact -service.gui.MOVE_CONTACT_ERROR=&Contact cannot be moved service.gui.MSG_DELIVERY_FAILURE=The above message could not be delivered service.gui.MSG_DELIVERY_NOT_SUPPORTED=The protocol you are using doesn''t \ support offline messages. You could try to reach {0} through another \ @@ -388,7 +362,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=You should be connected to be able to se service.gui.MULTIPLE_LOGINS=You have logged in more than once with the same account. The following account: User name: {0}, Server name: {1} is currently disconnected. service.gui.MY_CHAT_ROOMS=Add chat room service.gui.MY_CHAT_ROOMS_TITLE=Add chat room -service.gui.MUTE=Mute service.gui.MUTUALLY_ON_HOLD_STATUS=Mutually On Hold service.gui.NAME=Name service.gui.NETWORK=Network @@ -420,7 +393,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=NotInContactList service.gui.SD_QUALITY=Standard quality service.gui.OFFLINE=Offline service.gui.OK=&OK -service.gui.OLDER_CALLS=Older calls service.gui.ONLINE=Online service.gui.OPEN=Open service.gui.OPEN_FILE_FROM_IMAGE=Double click to open file. @@ -432,7 +404,6 @@ service.gui.OPEN_ON_ACTIVITY=Open on activity service.gui.OPEN_ON_MESSAGE=Open on message only service.gui.OPEN_ON_IMPORTANT_MESSAGE=Open on important messages only service.gui.OR=or -service.gui.OR_ENTER_PHONE_NUMBER=Or enter phone number here... service.gui.ORGANIZATION=Organization service.gui.OTHER=Other service.gui.chat.role.OWNER=Owner @@ -458,7 +429,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' for suggestions service.gui.PRESS_FOR_CALL_INFO=Press for call info service.gui.PRESS_TO_OPEN_CRM=Press to open CRM application service.gui.PREVIOUS=Previous -service.gui.PREVIOUS_TOOLTIP=Browse older conversations service.gui.PRINT=&Print service.gui.PROACTIVE_NOTIFICATION=is writing a message service.gui.PROBLEMS_ENCOUNTERED=Problems encountered @@ -474,7 +444,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=You have have been disconnecting and rec service.gui.RE_REQUEST_AUTHORIZATION=Re-request authorization service.gui.REFERRED_STATUS=Referred service.gui.REJECT=&Reject -service.gui.REMIND_ME_LATER=Remind me later service.gui.REMEMBER_PASSWORD=Remember password service.gui.REMOVE=&Remove service.gui.REMOVE_ACCOUNT=&Remove account @@ -500,9 +469,7 @@ service.gui.REVOKE_ADMIN=Revoke admin service.gui.REVOKE_MODERATOR=Revoke moderator service.gui.REVOKE_MEMBERSHIP=Revoke membership service.gui.REVOKE_VOICE=Revoke voice -service.gui.ROOT_GROUP=Root group service.gui.SAVE=&Save -service.gui.SAVE_AS_DEFAULT=Save as default service.gui.SEARCH=&Search service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Click the below button to show all chat rooms existing in the selected server. Then select the one you would like to join and click the join button. service.gui.SEARCH_STRING_CONTACT_SOURCE=Searched contact @@ -512,19 +479,13 @@ service.gui.SELECT_ACCOUNT_INFO=Which account do you want to use to communicate service.gui.SELECT_COLOR=Select color service.gui.SELECT_GROUP=Select group service.gui.SELECT_GROUP_INFO=Which group do you want to display this contact under? (Optional) -service.gui.SELECT_GROUP_WIZARD_MSG=The list below contains all groups in your Contact List. Select the one, where you would like to add the new contact. service.gui.SELECT_NO_GROUP=No group -service.gui.SELECT_GROUP_WIZARD=Specify group service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=The list below contains all accounts that support the multi user chat feature. Select the one you would like to use to create your chat room. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=The list below contains all registered accounts. Select the one you would like to use to communicate with the new contact. -service.gui.SELECT_PROVIDERS_WIZARD=Select account service.gui.SELECT_VIDEO_CONFERENCE=Select video conference service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Select chat room from the list and press OK to add it. service.gui.SEND=&Send service.gui.SEND_FILE=Send &file -service.gui.SELECT_CONTACT_SUPPORTING_INFO=There is no info for this contact. service.gui.SEND_MESSAGE=&Send a message -service.gui.SEND_AS_SMS=Send as SMS service.gui.SEND_PRIVATE_MESSAGE=Send private message service.gui.SEND_SMS=S&end SMS service.gui.SEND_SMS_DETAILS=Remember that you need to enter the number in international \ @@ -564,7 +525,6 @@ service.gui.STREET=Street service.gui.SUBJECT=Subject service.gui.SUMMARY=Summary service.gui.TELEPHONY=Telephony -service.gui.TODAY=Today service.gui.TOOLS=&Tools service.gui.TRANSFER=Trans&fer service.gui.TO=&To: @@ -574,7 +534,6 @@ service.gui.TRANSFER_CALL_TO=Transfer to: service.gui.TRANSPARENCY_NOT_ENABLED=Transparency is not supported by your current configuration. service.gui.TYPE_YOUR_REQUEST=Type your request here service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=We were not able to change video quality for this call. -service.gui.UNMUTE=Unmute service.gui.USER_IDENTIFIER=User identifier: service.gui.USER_EXISTS_ERROR=This user already exists on the selected network. Please choose another user or network. service.gui.USERNAME_NULL=Please fill your username and password. @@ -587,7 +546,6 @@ service.gui.USE_PROVISIONING=Use online provisioning service.gui.VALUE=Value service.gui.VIDEO_CALL=&Video call service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&View service.gui.VIEW_HISTORY=View &history service.gui.VIEW_SMILEYS=View &smileys @@ -607,9 +565,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Adjust volume service.gui.WAITING_AUTHORIZATION=Waiting for authorization service.gui.WARNING=Warning service.gui.YES=Yes -service.gui.YESTERDAY=Yesterday -service.gui.EXISTING_ACCOUNT_ERROR=The account you entered is already installed. -service.gui.NEW_MAIL=You have one new Mail!
    From: {0} {1}
    Subject: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=You have received a new mail message in your {0} inbox:
    service.gui.NEW_GMAIL_MANY_HEADER=You have received {2} new mail messages in your {0} inbox:
    service.gui.NEW_GMAIL_FOOTER=one more unread conversation in your inbox.
    @@ -636,7 +591,6 @@ service.gui.SECURITY_ERROR=Security error service.gui.SPEED=Speed: service.gui.SILENT_MEMBER=silent member service.gui.NON_SECURE_CONNECTION=No secure connection can be made for account {0}. If you want to connect to non-secure server, please check \"Allow non-secure connections\" in your account configuration -service.gui.UPDATE=Update service.gui.MOBILE_PHONE=Mobile service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Work @@ -673,12 +627,10 @@ service.gui.callinfo.CALL_INFORMATION=Call information service.gui.callinfo.CALL_IDENTITY=Identity service.gui.callinfo.PEER_COUNT=Participant count service.gui.callinfo.IS_CONFERENCE_FOCUS=Conference focus -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Encryption enabled service.gui.callinfo.CALL_TRANSPORT=Signalling call transport service.gui.callinfo.CALL_DURATION=Call duration service.gui.callinfo.TLS_PROTOCOL=TLS protocol service.gui.callinfo.TLS_CIPHER_SUITE=TLS cipher suite -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=TLS server certificate chain service.gui.callinfo.TLS_CERTIFICATE_CONTENT=The content of the TLS server \ certificate is displayed below. service.gui.callinfo.VIEW_CERTIFICATE=View certificate @@ -699,10 +651,14 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Key exchange protocol service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE candidate extended type service.gui.callinfo.ICE_STATE=ICE Processing State + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Gather candidates service.gui.callinfo.ICE_STATE.RUNNING=Connectivity checks service.gui.callinfo.ICE_STATE.COMPLETED=Completed service.gui.callinfo.ICE_STATE.FAILED=Failed +service.gui.callinfo.ICE_STATE.TERMINATED=Terminated + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Local host IP / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Local reflexive IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Local relayed IP / Port @@ -734,12 +690,6 @@ The certificate is not trusted, which means that the server''s \ identity cannot
    be automatically verified. \ Do you want to continue connecting?

    \ For more information, click "Show Certificate". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} can''t verify the identity \ -of the connecting client.

    \ -The certificate is not trusted, which means that the client''s \ -identity cannot
    be automatically verified. \ -Do you want to accept the connection?

    \ -For more information, click "Show Certificate". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} can''t verify the identity \ of the peer {1}.

    \ The certificate is not trusted, which means that the peer''s \ @@ -749,6 +699,8 @@ For more information, click "Show Certificate". service.gui.CONTINUE_ANYWAY=Continue anyway service.gui.CERT_INFO_CHAIN=Certificate Chain: service.gui.CERT_INFO_ISSUED_TO=Issued To + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Common Name: service.gui.CERT_INFO_O=Organization: service.gui.CERT_INFO_C=Country Name: @@ -767,12 +719,10 @@ service.gui.CERT_INFO_SIGN_ALG=Signature Algorithm: service.gui.CERT_INFO_PUB_KEY_INFO=Public Key Info service.gui.CERT_INFO_ALG=Algorithm: service.gui.CERT_INFO_PUB_KEY=Public Key: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Exponent: service.gui.CERT_INFO_KEY_SIZE=Key Size: service.gui.CERT_INFO_SIGN=Signature: -service.gui.CONTINUE=Continue service.gui.SHOW_CERT=Show Certificate service.gui.HIDE_CERT=Hide Certificate @@ -795,12 +745,9 @@ service.gui.security.SECURE_AUDIO=Secure audio service.gui.security.AUDIO_NOT_SECURED=Audio not secure service.gui.security.SECURE_VIDEO=Secure video service.gui.security.VIDEO_NOT_SECURED=Video not secure -service.gui.security.NO_VIDEO=No video -service.gui.security.CIPHER=Cipher: {0} service.gui.security.CALL_SECURED_TOOLTIP=Call secured. For more information click here. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Call not secure. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Press here to compare security secret with your partner. -service.gui.security.COMPARE_WITH_PARTNER=Compare with partner and click the padlock to confirm. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Compare with partner: service.gui.security.STRING_COMPARED=String compared! @@ -825,11 +772,9 @@ service.gui.avatar.imagepicker.CLICK=Click and Smile service.gui.avatar.imagepicker.IMAGE_FILES=Image files service.gui.avatar.imagepicker.IMAGE_PICKER=Picture service.gui.avatar.imagepicker.IMAGE_SIZE=Image size -service.gui.avatar.imagepicker.INITIALIZING=Initializing service.gui.avatar.imagepicker.RESET=Reset service.gui.avatar.imagepicker.SET=Set service.gui.avatar.imagepicker.TAKE_PHOTO=Take a photo -service.gui.avatar.imagepicker.WEBCAM_ERROR=Webcam error service.gui.security.encryption.required=Encryption required! @@ -844,11 +789,6 @@ service.systray.CLI_NOTE=If your choice does not work, you can start {0} with th This forces the mode to "Disabled" and shows the GUI. \ Changing the tray implementation requires a restart. -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ - impl.protocol.sip.XCAP_ERROR_TITLE=Error in SIP contact list storage impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Resource cannot be read {0}. For {1} impl.protocol.sip.XCAP_ERROR_UNAUTHORIZED=Wrong username or password using xcap. For {0}. @@ -877,9 +817,7 @@ impl.ldap.QUERY_CUSTOM=Custom query impl.ldap.QUERY_CUSTOM_HINT=Use {0} as a placeholder for the search term. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Automatically add wildcards to the query term impl.ldap.QUERY_PHOTO_INLINE=Fetch photo along with other attributes -impl.ldap.NEW=New impl.ldap.EDIT=edit -impl.ldap.REMOVE=Remove impl.ldap.ENABLED=Enabled impl.ldap.SERVER_NAME=Server name impl.ldap.SERVER_NAME_EXAMPLE=My LDAP server @@ -925,7 +863,7 @@ plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK=Enable Microsoft Outlook search plugin.addrbook.DESCRIPTION=If enabled everything you type in the search field \ of the contact list will be also searched in your system address book and all \ matching contacts from your address book will appear in your contact list. - plugin.addrbook.DEFAULT_IM_APP=Make Jitsi the default Instant Messaging Provider (Outlook integration) +plugin.addrbook.DEFAULT_IM_APP=Make Jitsi the default Instant Messaging Provider (Outlook integration) plugin.addrbook.PREFIX=Specific phone number prefix plugin.addrbook.PREFIX_EXAMPLE=Ex.: 00 plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE=Error accessing your Microsoft Outlook contacts. @@ -934,9 +872,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Make Outlook default mail clien # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google Contacts -impl.googlecontacts.NEW=New impl.googlecontacts.EDIT=edit -impl.googlecontacts.REMOVE=Remove impl.googlecontacts.ENABLED=Enabled impl.googlecontacts.ACCOUNT_NAME=Account name impl.googlecontacts.SAVE=Save @@ -979,11 +915,8 @@ plugin.accountinfo.ORGANIZATION=Organization Name: plugin.accountinfo.JOB_TITLE=Job Title: plugin.accountinfo.ABOUT_ME=About Me: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=User Pictures plugin.accountinfo.GLOBAL_ICON=Use global icon plugin.accountinfo.LOCAL_ICON=Use this icon: -plugin.accountinfo.CHANGE=Change -plugin.accountinfo.ONLY_MESSAGE=Only messages # connection info plugin.connectioninfo.TITLE=Connection Info @@ -1003,7 +936,6 @@ plugin.aimaccregwizz.USERNAME=AIM Screenname: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Screen Name and Password plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Register new account plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=In case you don't have an AIM account, click on this button to create a new one. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Override server default options # branding plugin.branding.ABOUT_WINDOW_TITLE=About {0} @@ -1025,9 +957,6 @@ plugin.generalconfig.SHOW_HISTORY=Show plugin.generalconfig.HISTORY_SIZE=recent messages in new chats plugin.generalconfig.SEND_MESSAGES_WITH=Send messages with: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Bring chat window to front -plugin.generalconfig.ERROR_PERMISSION=You don't have enough privileges to remove autostart -plugin.generalconfig.TRANSPARENCY=Transparency -plugin.generalconfig.ENABLE_TRANSPARENCY=Enable transparency plugin.generalconfig.DEFAULT_LANGUAGE=Interface Language plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Your changes will take effect on next restart. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% translated @@ -1117,13 +1046,10 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Comment plugin.jabberaccregwizz.RESOURCE=Resource plugin.jabberaccregwizz.AUTORESOURCE=Auto generate resource plugin.jabberaccregwizz.PRIORITY=Priority -plugin.jabberaccregwizz.XMPP_ERROR=XMPP Error plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Unknown XMPP error ({0}). Verify that the server name is correct. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Your passwords did not match. plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Override server default options -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Advanced options plugin.jabberaccregwizz.USE_ICE=Use ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Use Google's Jingle/ICE (experimental) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Auto discover STUN/TURN servers plugin.jabberaccregwizz.SUPPORT_TURN=Support TURN plugin.jabberaccregwizz.TURN_USERNAME=TURN username @@ -1151,11 +1077,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Disable message carbons plugin.jabberaccregwizz.DTMF_AUTO=Auto: Choose automatically between RTP and Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Server options plugin.jabberaccregwizz.CHANGE_PASSWORD=Change account password -plugin.jabberaccregwizz.NEW_PASSWORD=New password -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirm new password plugin.jabberaccregwizz.PORT_FIELD_INVALID=Please fill a valid port number in order to continue. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=The account has to be signed in before changing a password. -plugin.jabberaccregwizz.PASSWORD_EMPTY=The password is empty. plugin.jabberaccregwizz.TLS_REQUIRED=The connection does not use TLS, will not attempt a password change. plugin.jabberaccregwizz.PASSWORD_CHANGED=The password has been successfully changed plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Your XMPP server does not support password changes. @@ -1169,15 +1092,6 @@ plugin.jabberaccregwizz.RESET=Reset plugin.jabberaccregwizz.RESET_DESCRIPTION=Reset to the global settings plugin.jabberaccregwizz.DISABLE_JINGLE=Disable Jingle (audio and video calls with XMPP). -# mailbox -plugin.mailbox.OUTGOING=Outgoing Message: -plugin.mailbox.INCOMING=Incoming Messages: -plugin.mailbox.WAIT_TIME=Delay Until Call Sent to Voicemail -plugin.mailbox.MAX_MESSAGE_TIME=Maximum Incoming Message Duration -plugin.mailbox.CONFIRM=Confirm -plugin.mailbox.DEFAULTS=Defaults -plugin.mailbox.MAILBOX=Mailbox - # plugin manager plugin.pluginmanager.INSTALL=Install plugin.pluginmanager.UNINSTALL=Uninstall @@ -1206,7 +1120,6 @@ plugin.sipaccregwizz.SERVER_PORT=Server port plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxy port plugin.sipaccregwizz.PREFERRED_TRANSPORT=Preferred transport -plugin.sipaccregwizz.ADVANCED_OPTIONS=Advanced options plugin.sipaccregwizz.PROXY_OPTIONS=Proxy options plugin.sipaccregwizz.PROXY_AUTO=Configure proxy automatically plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Bypass proxy security check for HA scenarios (use only if needed) @@ -1227,8 +1140,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Choose automatically between RTP and Inband plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Override server default options plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Enable support to encrypt calls plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indicate support of ZRTP in signalling protocol plugin.sipaccregwizz.AUTH_NAME=Authorization name @@ -1249,10 +1160,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Voicemail check URI plugin.sipaccregwizz.NOT_SAME_PASSWORD=Your passwords did not match. plugin.sipaccregwizz.NO_CERTIFICATE= (use regular authentication) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP indication +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Off (indicate RTP/AVP only) plugin.sipaccregwizz.SAVP_OPTION_1=Mandatory (offer and accept only RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Optional (offer RTP/SAVP first, then RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Enable S-Descriptor (also known as SDES or SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Choose enabled encryption protocols and their priority (top protocol first): plugin.sipaccregwizz.CIPHER_SUITES=Enabled cipher suites: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} will automatically try to secure all \ @@ -1342,6 +1253,8 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Existing ippi account plugin.ippiaccregwizz.CREATE_ACCOUNT=Create a free ippi account # key binding chooser +plugin.keybindings.WAITING=Press shortcut... +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Close Chat Window plugin.keybindings.CHAT_COPY=Copy plugin.keybindings.CHAT_CUT=Cut @@ -1364,10 +1277,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Name plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primary shortcut plugin.keybindings.globalchooser.SHORTCUT_SECOND=Second shortcut plugin.keybindings.globalchooser.PRESS_BTN=Press to set shortcut -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Waiting plugin.keybindings.globalchooser.PUSH_TO_TALK=Push to talk plugin.keybindings.globalchooser.ENABLE_SPECIAL=Enable special key detection plugin.keybindings.PLUGIN_NAME=Keybindings +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Main plugin.keybindings.GLOBAL=Global shortcuts @@ -1395,6 +1308,7 @@ plugin.notificationconfig.tableheader.SOUND=Play a sound through notification de plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Play a sound through playback device plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Play a sound through PC speaker device plugin.notificationconfig.tableheader.DESCRIPTION=Description of event +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Incoming Call plugin.notificationconfig.event.SecurityMessage=Security Message plugin.notificationconfig.event.IncomingFile=Incoming File @@ -1501,6 +1415,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Periodic Intra Refresh impl.neomedia.configform.H264.defaultProfile=Default profile to encode into: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Baseline impl.neomedia.configform.H264.defaultProfile.high=High impl.neomedia.configform.H264.defaultProfile.main=Main @@ -1531,7 +1446,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Current password: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Enter new password: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Re-enter password: plugin.securityconfig.masterpassword.MP_TITLE=Master Password -plugin.securityconfig.masterpassword.MP_NOT_SET=(not set) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=You did not enter the correct current Master Password. Please try again. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=The Master Password is not correct! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Password Change Failed @@ -1702,7 +1616,6 @@ plugin.provisioning.RESTART_WARNING=Note that your changes will only take effect plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Copy UUID to clipboard plugin.provisioning.CLIPBOARD_FAILED=Failed to copy UUID to clipboard -plugin.provisioning.EXIT_ON_FAIL=Exit the application if the provisioning fails plugin.provisioning.CREDENTIALS=Last stored provisioning credentials plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Are you sure you want to remove provisioning password? plugin.provisioning.PROV_FAILED=Provisioning failed @@ -1784,8 +1697,6 @@ inform them about the issue. \ #plugin spellcheck plugin.spellcheck.TITLE=Spelling and Grammar plugin.spellcheck.MENU=Show Spelling and Grammar -plugin.spellcheck.LANG=Language -plugin.spellcheck.EDIT_PERSONAL_DICT=Edit plugin.spellcheck.ENABLE_SPELL_CHECK=Enable spell check plugin.spellcheck.dialog.FIND=Find Next plugin.spellcheck.dialog.REPLACE=Replace diff --git a/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java b/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java index 9956785..bb888ad 100644 --- a/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java +++ b/src/net/java/sip/communicator/impl/certificate/CertificateServiceImpl.java @@ -737,8 +737,7 @@ public class CertificateServiceImpl propNames.add(propName); message = - R.getI18NString("service.gui." - + "CERT_DIALOG_DESCRIPTION_TXT_NOHOST", + R.getI18NString("service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST", new String[] { appName } @@ -762,8 +761,7 @@ public class CertificateServiceImpl { message = R.getI18NString( - "service.gui." - + "CERT_DIALOG_DESCRIPTION_TXT", + "service.gui.CERT_DIALOG_DESCRIPTION_TXT", new String[] { appName, identitiesToTest.toString() @@ -774,8 +772,7 @@ public class CertificateServiceImpl { message = R.getI18NString( - "service.gui." - + "CERT_DIALOG_PEER_DESCRIPTION_TXT", + "service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT", new String[] { appName, identitiesToTest.toString() diff --git a/src/net/java/sip/communicator/impl/neomedia/AbstractDeviceConfigurationListener.java b/src/net/java/sip/communicator/impl/neomedia/AbstractDeviceConfigurationListener.java index a1814e8..3c84aa2 100644 --- a/src/net/java/sip/communicator/impl/neomedia/AbstractDeviceConfigurationListener.java +++ b/src/net/java/sip/communicator/impl/neomedia/AbstractDeviceConfigurationListener.java @@ -187,8 +187,7 @@ public abstract class AbstractDeviceConfigurationListener body + "\r\n\r\n" + NeomediaActivator.getResources().getI18NString( - "impl.media.configform" - + ".AUDIO_DEVICE_CONFIG_MANAGMENT_CLICK"), + "impl.media.configform.AUDIO_DEVICE_CONFIG_MANAGMENT_CLICK"), null, extras); } diff --git a/src/net/java/sip/communicator/impl/neomedia/AudioDeviceConfigurationListener.java b/src/net/java/sip/communicator/impl/neomedia/AudioDeviceConfigurationListener.java index 75f1fc3..fe06f15 100644 --- a/src/net/java/sip/communicator/impl/neomedia/AudioDeviceConfigurationListener.java +++ b/src/net/java/sip/communicator/impl/neomedia/AudioDeviceConfigurationListener.java @@ -159,10 +159,8 @@ public class AudioDeviceConfigurationListener capturePropertyChangeEvent.getOldValue())) { body.append("\r\n") - .append( - r.getI18NString( - "impl.media.configform" - + ".AUDIO_DEVICE_SELECTED_AUDIO_IN")) + .append(r.getI18NString( + "impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_IN")) .append("\r\n\t") .append(cdi.getName()); selectedHasChanged = true; @@ -179,10 +177,8 @@ public class AudioDeviceConfigurationListener playbackPropertyChangeEvent.getOldValue())) { body.append("\r\n") - .append( - r.getI18NString( - "impl.media.configform" - + ".AUDIO_DEVICE_SELECTED_AUDIO_OUT")) + .append(r.getI18NString( + "impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_OUT")) .append("\r\n\t") .append(cdi.getName()); selectedHasChanged = true; @@ -199,10 +195,8 @@ public class AudioDeviceConfigurationListener notifyPropertyChangeEvent.getOldValue())) { body.append("\r\n") - .append( - r.getI18NString( - "impl.media.configform" - + ".AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS")) + .append(r.getI18NString( + "impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS")) .append("\r\n\t") .append(cdi.getName()); selectedHasChanged = true; diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaConfigurationImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaConfigurationImpl.java index d561c92..00e8aac 100644 --- a/src/net/java/sip/communicator/impl/neomedia/MediaConfigurationImpl.java +++ b/src/net/java/sip/communicator/impl/neomedia/MediaConfigurationImpl.java @@ -1773,8 +1773,7 @@ public class MediaConfigurationImpl { String noAvailableAudioDevice = NeomediaActivator.getResources().getI18NString( - "impl.media.configform" - + ".NO_AVAILABLE_AUDIO_DEVICE"); + "impl.media.configform.NO_AVAILABLE_AUDIO_DEVICE"); preview = new TransparentPanel(new GridBagLayout()); preview.add(new JLabel(noAvailableAudioDevice)); diff --git a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/ConfigurationPanel.java b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/ConfigurationPanel.java index 1381d21..a3ea318 100644 --- a/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/ConfigurationPanel.java +++ b/src/net/java/sip/communicator/impl/neomedia/codec/video/h264/ConfigurationPanel.java @@ -150,8 +150,7 @@ public class ConfigurationPanel JCheckBox defaultIntraRefreshCheckBox = new SIPCommCheckBox( r.getI18NString( - "impl.neomedia.configform.H264" - + ".defaultIntraRefresh")); + "impl.neomedia.configform.H264.defaultIntraRefresh")); cnstrnts.gridwidth = GridBagConstraints.REMAINDER; cnstrnts.gridx = 0; cnstrnts.gridy = 3; diff --git a/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java b/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java index 0467033..c046348 100644 --- a/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java +++ b/src/net/java/sip/communicator/plugin/jabberaccregwizz/AccountPanel.java @@ -140,7 +140,7 @@ public class AccountPanel userIDPassPanel.setBorder( BorderFactory.createTitledBorder( Resources.getString( - "plugin.sipaccregwizz.USERNAME_AND_PASSWORD"))); + "plugin.jabberaccregwizz.USERNAME_AND_PASSWORD"))); JPanel southPanel = new TransparentPanel(new BorderLayout()); southPanel.add(rememberPassBox, BorderLayout.WEST); @@ -564,8 +564,7 @@ public class AccountPanel OperationSetChangePassword.class).supportsPasswordChange()) { changePasswordMessagePane.setText(Resources.getString( - "plugin.jabberaccregwizz." - + "SERVER_NOT_SUPPORT_PASSWORD_CHANGE")); + "plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE")); } else { @@ -683,8 +682,7 @@ public class AccountPanel getAccountID().getAccountAddress(), ex); displayPopupError(Resources.getString( - "plugin.jabberaccregwizz." - + "PASSWORD_NOT_STORED")); + "plugin.jabberaccregwizz.PASSWORD_NOT_STORED")); } } //now update the password field in AccountPanel, @@ -705,8 +703,7 @@ public class AccountPanel } catch (OperationFailedException ex) { displayPopupError(Resources.getString( - "plugin.jabberaccregwizz." - + "SERVER_NOT_SUPPORT_PASSWORD_CHANGE")); + "plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE")); } } } diff --git a/src/net/java/sip/communicator/plugin/keybindingchooser/chooser/BindingChooser.java b/src/net/java/sip/communicator/plugin/keybindingchooser/chooser/BindingChooser.java index bd8ff0d..12ba3e2 100644 --- a/src/net/java/sip/communicator/plugin/keybindingchooser/chooser/BindingChooser.java +++ b/src/net/java/sip/communicator/plugin/keybindingchooser/chooser/BindingChooser.java @@ -24,6 +24,7 @@ import java.util.*; import javax.swing.*; import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.plugin.keybindingchooser.KeybindingChooserActivator; import net.java.sip.communicator.service.keybindings.*; /** @@ -51,36 +52,12 @@ public class BindingChooser // can be selected private BindingEntry selectedEntry = null; // None selected when null - private String selectedText = "Press shortcut..."; - /** * Keybinding set. */ private KeybindingSet set = null; /** - * Displays a dialog allowing the user to redefine the keystroke component - * of key bindings. The top has light blue labels describing the fields and - * the bottom provides an 'OK' and 'Cancel' option. This uses the default - * color scheme and indent style. If no entries are selected then the enter - * key is equivalent to pressing 'OK' and escape is the same as 'Cancel'. - * - * @param parent frame to which to apply modal property and center within - * (centers within screen if null) - * @param bindings initial mapping of keystrokes to their actions - * @return redefined mapping of keystrokes to their actions, null if cancel - * is pressed - */ - public static LinkedHashMap showDialog(Component parent, - Map bindings) - { - BindingChooser display = new BindingChooser(); - display.putAllBindings(bindings); - return showDialog(parent, display, "Key Bindings", true, display - .makeAdaptor()); - } - - /** * Adds a collection of new key binding mappings to the end of the listing. * If any shortcuts are already contained then the previous entries are * replaced (not triggering the onUpdate method). Disabled shortcuts trigger @@ -269,22 +246,6 @@ public class BindingChooser } /** - * Sets the message of the selected shortcut field when awaiting user input. - * By default this is "Press shortcut...". - * - * @param message prompt for user input - */ - public void setSelectedText(String message) - { - if (this.selectedEntry != null) - { - this.selectedEntry.getField(BindingEntry.Field.SHORTCUT).setText( - message); - } - this.selectedText = message; - } - - /** * Returns if a binding is currently awaiting input or not. * * @return true if a binding is awaiting input, false otherwise @@ -344,7 +305,8 @@ public class BindingChooser onUpdate(getBindingIndex(this.selectedEntry), this.selectedEntry, false); this.selectedEntry.getField(BindingEntry.Field.SHORTCUT).setText( - " " + this.selectedText); + KeybindingChooserActivator.getResources().getI18NString( + "plugin.keybindings.WAITING")); } } diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java index c330879..8e4a235 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java @@ -654,15 +654,14 @@ public class ScOtrEngineImpl String unverifiedSessionWarning = OtrActivator.resourceService.getI18NString( - "plugin.otr.activator" - + ".unverifiedsessionwarning", - new String[] - { - contact.getDisplayName() + resourceName, - this.getClass().getName(), - "AUTHENTIFICATION", - sessionGuid.toString() - }); + "plugin.otr.activator.unverifiedsessionwarning", + new String[] + { + contact.getDisplayName() + resourceName, + this.getClass().getName(), + "AUTHENTIFICATION", + sessionGuid.toString() + }); OtrActivator.uiService.getChat(contact).addMessage( contact.getDisplayName(), new Date(), Chat.SYSTEM_MESSAGE, @@ -727,8 +726,7 @@ public class ScOtrEngineImpl OtrActivator.scOtrKeyManager.isVerified( contact, remoteFingerprint) ? "plugin.otr.activator.sessionstared" - : "plugin.otr.activator" - + ".unverifiedsessionstared", + : "plugin.otr.activator.unverifiedsessionstared", new String[] {contact.getDisplayName() + resourceName}); diff --git a/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java b/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java index 53dde17..d0c908e 100644 --- a/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java +++ b/src/net/java/sip/communicator/plugin/update/UpdateServiceImpl.java @@ -545,24 +545,22 @@ public class UpdateServiceImpl if(notifyAboutNewestVersion) { SwingUtilities.invokeLater( - new Runnable() + new Runnable() + { + public void run() { - public void run() - { - UIService ui = UpdateActivator.getUIService(); - ResourceManagementService r - = Resources.getResources(); - - ui.getPopupDialog().showMessagePopupDialog( - r.getI18NString( - "plugin.updatechecker." - + "DIALOG_NOUPDATE"), - r.getI18NString( - "plugin.updatechecker." - + "DIALOG_NOUPDATE_TITLE"), - PopupDialog.INFORMATION_MESSAGE); - } - }); + UIService ui = UpdateActivator.getUIService(); + ResourceManagementService r + = Resources.getResources(); + + ui.getPopupDialog().showMessagePopupDialog( + r.getI18NString( + "plugin.updatechecker.DIALOG_NOUPDATE"), + r.getI18NString( + "plugin.updatechecker.DIALOG_NOUPDATE_TITLE"), + PopupDialog.INFORMATION_MESSAGE); + } + }); } } else -- cgit v1.1 From 134da567cd83c6be630d7a37f64249005d7c2925 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 18 Jan 2017 21:59:38 +0100 Subject: Fix tray icon to open window on double click on Windows --- .../osdependent/systemtray/awt/AWTTrayIcon.java | 27 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java index 0aef71b..2fa0318 100644 --- a/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java +++ b/src/net/java/sip/communicator/impl/osdependent/systemtray/awt/AWTTrayIcon.java @@ -63,9 +63,17 @@ public class AWTTrayIcon } } - public void setDefaultAction(Object menuItem) + public void setDefaultAction(final Object menuItem) { - ActionListener[] listeners; + // clear all previous listeners + ActionListener[] previous = impl.getActionListeners(); + for (ActionListener l : previous) + { + impl.removeActionListener(l); + } + + // get the new handlers + final ActionListener[] listeners; if (menuItem instanceof JMenuItem) { listeners = ((JMenuItem) menuItem).getActionListeners(); @@ -79,10 +87,19 @@ public class AWTTrayIcon return; } - for (ActionListener l : listeners) + // create a custom handler to fake that the source is the menu item + impl.addActionListener(new ActionListener() { - impl.addActionListener(l); - } + @Override + public void actionPerformed(ActionEvent e) + { + for (ActionListener l : listeners) + { + l.actionPerformed(new ActionEvent(menuItem, + e.getID(), e.getActionCommand())); + } + } + }); } public void addBalloonActionListener(ActionListener listener) -- cgit v1.1 From b828fa1150b2972a352ca4f46acdcdca3eb266ba Mon Sep 17 00:00:00 2001 From: Thomas M Date: Wed, 18 Jan 2017 23:43:25 +0100 Subject: VoiceCall Target resource (#37) * VoiceCall Target resource in chat/toolBars/ added. * Unneeded change forgotten to remove --- .../impl/gui/main/chat/toolBars/MainToolBar.java | 13 +++++++++---- .../jabber/OperationSetBasicTelephonyJabberImpl.java | 5 ++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java index 6905df9..7080d13 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/toolBars/MainToolBar.java @@ -715,14 +715,19 @@ public class MainToolBar m.put(opSetClass, ct.getProtocolProvider()); UIContactDetailImpl d = new UIContactDetailImpl( - ct.getName(), + ct.getName() + (ct.getResourceName() == null + ? "" + : "/" + ct.getResourceName()), ct.getDisplayName(), null, - null, + (ct.getResourceName() == null + ? Arrays.asList(GuiActivator.getResources().getI18NString("service.gui.VIA") + ": " + + ct.getProtocolProvider().getAccountID().getAccountAddress()) + : null), null, m, null, - ct.getName()); + ct); PresenceStatus status = ct.getStatus(); byte[] statusIconBytes = status.getStatusIcon(); @@ -736,7 +741,7 @@ public class MainToolBar res.add(d); } - + Point location = new Point(callButton.getX(), callButton.getY() + callButton.getHeight()); diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java index 6853ae7..78027c0 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java @@ -280,7 +280,10 @@ public class OperationSetBasicTelephonyJabberImpl Iterable sessionInitiateExtensions) throws OperationFailedException { - return createOutgoingCall(call, calleeAddress, null, null); + if (calleeAddress.contains("/")) + return createOutgoingCall(call, calleeAddress, calleeAddress, null); + else + return createOutgoingCall(call, calleeAddress, null, null); } /** -- cgit v1.1 From 9a2676b0d3c9b8c217d0cd9a78d88c9afc9d1b58 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:51:17 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1505 of 1505 strings translated (0 fuzzy). --- resources/languages/resources_de.properties | 235 +++++++--------------------- 1 file changed, 56 insertions(+), 179 deletions(-) diff --git a/resources/languages/resources_de.properties b/resources/languages/resources_de.properties index 362936e..afdc21b 100644 --- a/resources/languages/resources_de.properties +++ b/resources/languages/resources_de.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Ich service.gui.ACCOUNT_REGISTRATION_WIZARD=Kontoassistent service.gui.ACCOUNTS=Konten service.gui.ADD=&Hinzufügen -service.gui.ADD_ACCOUNT=Konto hinzufügen service.gui.ADD_CONTACT=&Kontakt hinzufügen service.gui.ADD_AUTHORIZED_CONTACT={0} zu den Kontakten hinzufügen service.gui.ADD_CONTACT_TO_CONTACTLIST=Kontakt zur Kontaktliste hinzufügen @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Fehler: Kontakt kann nicht hinzugefügt werd service.gui.ADD_CONTACT_EXIST_ERROR=Der Kontakt {0} existiert bereits. service.gui.ADD_CONTACT_NETWORK_ERROR=Der Server reagierte nicht auf die Anfrage den Kontakt {0} hinzuzufügen. service.gui.ADD_CONTACT_NOT_SUPPORTED=Kontakt {0} konnte nicht hinzugefügt werden. Vorgang wird nicht unterstützt. -service.gui.ADD_CONTACT_IDENTIFIER=Bitte geben Sie im folgenden Feld den Benutzernamen des hinzuzufügenden Kontakts ein. -service.gui.ADD_CONTACT_WIZARD=Kontakt hinzufügen service.gui.ADD_CONTACT_NOT_CONNECTED=Sie müssen angemeldet sein, um einen Kontakt hinzufügen zu können. Bitte melden Sie sich beim gewählten Anbieter an und versuchen Sie es erneut. service.gui.ADD_GROUP_LOCAL_ERROR=Die Gruppe {0} kann nicht hinzugefügt werden. Das Problem ist bei einer lokalen Lese-/Schreiboperation aufgetreten. service.gui.ADD_GROUP_EXIST_ERROR=Die Gruppe {0} existiert bereits in Ihrer Kontaktliste. Bitte wählen Sie einen anderen Namen. service.gui.ADD_GROUP_NET_ERROR=Die Gruppe {0} kann nicht hinzugefügt werden. Überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut. service.gui.ADD_GROUP_ERROR=Die Gruppe {0} kann nicht hinzugefügt werden. service.gui.ADD_GROUP_EMPTY_NAME=Der Gruppenname muss angegeben werden. -service.gui.ADD_GROUP=Gruppe erstellen -service.gui.ADD_SUBCONTACT=&Unterkontakt hinzufügen service.gui.ADDRESS=Adresse service.gui.ADMINISTRATOR=Administrator service.gui.ADVANCED=Erweitert -service.gui.ALL=&Alle service.gui.ALL_CONTACTS=&Alle Kontakte service.gui.ALTERNATE_ADDRESS=Alternative Adresse service.gui.APPLY=&Anwenden @@ -65,7 +70,6 @@ service.gui.AT=Wann service.gui.AUTHORIZE=&Autorisieren service.gui.AUTHORIZATION_ACCEPTED={0} hat die Autorisierungsanfrage akzeptiert. service.gui.AUTHENTICATION_FAILED=Anmeldung für {0} fehlgeschlagen. Die eingegebenen Anmeldedaten sind falsch. -service.gui.AUTHENTICATION_REQUESTED=Anmeldung erforderlich service.gui.AUTHENTICATION_REQUESTED_SERVER=Der {0} Server benötigt Ihre Zugangsdaten. service.gui.AUTHENTICATION_REJECTED={0} hat die Autorisierungsanfrage zurückgewiesen. service.gui.AUTHENTICATION_WINDOW_TITLE={0} Authentifizierung @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Im nachstehenden Feld können Sie Ihren neuen service.gui.CHANGE_NICKNAME_ERROR=Fehler beim Ändern des Nicknamens service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nickname existiert bereits service.gui.CHANGE_VIDEO_QUALITY=Videoqualität ändern -service.gui.CHAT_CONFERENCE_LABEL=Konferenzen service.gui.CHAT_CONFERENCE_ITEM_LABEL=Konferenz von {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Sie sind bereits Mitglied des Chatraums {0}. service.gui.CHAT_ROOM_CONFIGURATION={0} Chatraum konfigurieren @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=hat den Chatraum verlassen {0} service.gui.CHAT_ROOM_USER_KICKED=ist von {0} hinausgeschmissen worden service.gui.CHAT_ROOM_USER_QUIT=hat {0} beendet service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Nachrichtenversand ist verboten (Stimme gesperrt) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Speichert den Chatraum für künftige Verwendungen -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Entfernt den markierten Chatraum von der Liste der gespeicherten Chaträume service.gui.CHAT_ROOM_NAME=Name des Chatraums service.gui.CLEAR_CUSTOM_MESSAGES=Benutzerdefinierte Nachrichten löschen service.gui.ROOM_NAME=Chatraum -service.gui.AUTOJOIN=Automatisches beitreten service.gui.CHANGE_PASSWORD=Passwort ändern service.gui.CHAT_ROOM_NAME_INFO=Geben Sie im folgenden Feld den Namen des Chatraums ein, den Sie erstellen wollen. service.gui.CHAT_ROOM_NOT_EXIST=Der Chatraum {0} ist dem Server {1} unbekannt. Bitte überprüfen Sie den Namen des Chatraums. service.gui.CHAT_ROOM_NOT_CONNECTED=Sie müssen angemeldet sein, um dem Chatraum {0} beitreten zu können. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Sie müssen verbunden sein, um einen Chatraum zu verlassen. -service.gui.CHAT_ROOM_NOT_JOINED=Sie müssen dem Chatraum beigetreten sein, bevor Sie weitere Aktionen ausführen können. service.gui.CHAT_ROOM_OPTIONS=Chatraum-Einstellungen service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Der Chatraum {0} erfordert eine Registrierung um beizutreten. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Der Chatraum {0} benötigt ein Passwort. @@ -157,16 +156,15 @@ service.gui.CONNECTING=Verbinde... service.gui.CONNECTING_STATUS=Verbinde service.gui.CONNECTING_EARLY_MEDIA_STATUS=Verbinde* service.gui.CONNECTION=Verbindung -service.gui.CONNECTION_FAILED_MSG=Die Verbindung für {0} ({1}) ist fehlgeschlagen. Bitte überprüfen Sie Ihre Netzwerkverbindung oder kontaktieren Sie Ihren Netzwerkadministrator für weitere Informationen. service.gui.CONNECTION_EXPIRED_MSG=Sie sind nicht mit Server {0} verbunden. service.gui.CONTACT_NAME=ID oder Nummer -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Der gewählte {0} Kontakt unterstützt keine Telefonie. +service.gui.CONTACT_NAME_PROMPT=irene.muster@example.com +service.gui.CONTACT_NAME_INFO=Adresse für Chat-Dienst (z.B. lisa.mueller@example.com) oder VoIP-Nummer hinzufügen service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Der ausgewählte Kontakt {0} unterstützt die Gruppenkonferenz nicht. service.gui.CONTACT_PAUSED_TYPING={0} unterbricht das Schreiben service.gui.CONTACT_TYPING={0} schreibt eine Nachricht service.gui.CONTACT_TYPING_SEND_FAILED=Ups... wir konnten {0} die Schreibbenachrichtigung nicht senden service.gui.CONTACT_INFO=&Kontaktinformation -service.gui.CONTACTLIST=Kontaktliste service.gui.CONTACTS=Kontakte service.gui.COPY=&Kopieren service.gui.COPY_LINK=&Link kopieren @@ -176,28 +174,26 @@ service.gui.CREATE_CHAT_ROOM=&Chatraum erstellen... service.gui.CREATE_CHAT_ROOM_ERROR=Der Chatraum mit dem Namen {0} konnte nicht erstellt werden. service.gui.CREATE_CHAT_ROOM_WIZARD=Assistent zum Erstellen eines Chatraums service.gui.CREATE_CONFERENCE_CALL=&Konferenz erstellen... -service.gui.CREATE_CONFERENCE_CHAT=&Chatraum erstellen... service.gui.CREATE_GROUP=&Gruppe erstellen... service.gui.CREATE_GROUP_NAME=Bitte geben Sie im folgenden Feld den Namen der zu erstellenden Gruppe ein. -service.gui.CREATE_FIRST_GROUP_WIZARD=Ihre Kontaktliste enthält keine Gruppe. Bitte legen Sie zuerst eine Gruppe an (Datei/Gruppe erstellen). service.gui.CREATE_VIDEO_BRIDGE=&Videobrücke erstellen... service.gui.CREATE_VIDEO_BRIDGE_MENU=&Videobrücke erstellen service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Videokonferenz erstellen/beitreten service.gui.CREATE_VIDEO_CONFERENCE=Videokonferenz erstellen service.gui.CONTACT_INFO_NOT_SUPPORTED=Dieser Kontakt unterstützt keine Web-Informationen service.gui.CUT=&Ausschneiden -service.gui.DATE=Datum service.gui.DELETE=Löschen service.gui.DENY=&Ablehnen service.gui.DESKTOP_SHARING_WARNING=Soll die Bildschirmfreigabe wirklich eingeschaltet werden?
    Die Freigabe zeigt den Bildschirm allen Teilnehmern dieses Anrufs. service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Ihr Bildschirm ist freigegeben service.gui.DIALPAD=Wähltastatur service.gui.DISPLAY_NAME=Anzeigename +service.gui.DISPLAY_NAME_PROMPT=Lisa Mueller +service.gui.DISPLAY_NAME_INFO=Name für diesen Kontakt. Ohne Angaben wird die Chat-Adresse oder VoIP-Nummer verwendet. (Optional) service.gui.DISCONNECTED_STATUS=Getrennt service.gui.DND_STATUS=Bitte nicht stören service.gui.DO_NOT_ASK_AGAIN=Nicht mehr fragen service.gui.DO_NOT_SHOW_AGAIN=Diese Nachricht nicht mehr anzeigen -service.gui.DOWNLOAD_NOW=Jetzt herunterla&den service.gui.DRAG_FOR_SHARING=Ziehe hier etwas hinein, das den anderen geschickt werden soll... service.gui.DURATION=Dauer service.gui.DESTROY_CHATROOM=Chatraum auflösen @@ -218,7 +214,6 @@ service.gui.ERROR_RECEIVED_FROM=Fehler von {0} empfangen service.gui.ESTIMATED_TIME=Geschätzte Zeit: service.gui.EVENTS=Ereignisse service.gui.EXIT=&Verlassen -service.gui.EXTENDED_CRITERIA=Erweiterte Kriterien service.gui.GENERAL=Allgemein service.gui.GENERAL_ERROR=Allgemeiner Fehler service.gui.GROUP_NAME=Gruppenname @@ -260,7 +255,6 @@ service.gui.FONT_ITALIC=Kursiv service.gui.FONT_SIZE=Größe service.gui.FONT_STYLE=Stil service.gui.FONT_UNDERLINE=Unterstrichen -service.gui.FROM={0} von {1} service.gui.GRANT_OWNERSHIP=Erlaube Eigentümer... service.gui.GRANT_ADMIN=Erlaube Administrator... service.gui.GRANT_MODERATOR=Erlaube Moderator @@ -286,7 +280,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Sind Sie sicher, dass Sie alle lokal gesp service.gui.HISTORY_REMOVE_ERROR=Fehler beim Löschen der lokal gespeicherten Nachrichten. service.gui.HOME=Privat service.gui.HOME_PAGE=Homepage -service.gui.HOUR=Stunde service.gui.ICE=ICE service.gui.IDENTIFIER=Identifikation service.gui.IGNORE=&Ignorieren @@ -310,13 +303,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Kontakte zur Videobrücke einladen service.gui.INVITE_REASON=Grund der Einladung service.gui.IS_CALLING={0} ruft an... service.gui.IS_NOW={0} ist nun {1} -service.gui.JITSI_WARNING=SIP Communicator wurde in Jitsi umbenannt
    . Wenn die Installation aktuell gehalten werden soll, laden Sie Jitsi bitte jetzt herunter.

    Das Jitsi Entwickler-Team entschuldigt sich für die entstehenden Umstände. -service.gui.JITSI_WARNING_TITLE=SIP Communicator wird zu Jitsi service.gui.JOIN=&Teilnehmen service.gui.JOIN_AS=T&eilnehmen als service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Videokonferenz beitreten service.gui.JOIN_VIDEO=Mit Video beitreten -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Schließen service.gui.JOB_TITLE=Beruf service.gui.JOIN_CHAT_ROOM=Chatraum bei&treten... service.gui.JOIN_CHAT_ROOM_TITLE=Chatraum beitreten @@ -329,7 +319,6 @@ service.gui.KICK_FAILED=Rauswurf fehlgeschlagen service.gui.KICK_FAILED_GENERAL_ERROR=Rauswurf von {0} fehlgeschlagen. Der Server meldete einen allgemeinen Fehler. service.gui.KICK_FAILED_NOT_ALLOWED=Teilnehmer {0} kann nicht rausgeworfen werden. Der Eigentümer und der Administrator des Raums können nicht rausgeworfen werden. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Rauswurf von {0} gescheitert. Sie haben nicht die erforderlichen Rechte. -service.gui.LAST=Letzter service.gui.LAST_NAME=Nachname service.gui.LEAVE=&Verlassen service.gui.LIMIT_REACHED_FOR_IP=Sie haben schon zu viele Verbindungen von Ihrer IP-Adresse und der Server {0} erlaubt keine weiteren. @@ -349,7 +338,6 @@ service.gui.MESSAGE=Nachricht service.gui.MISSED_CALLS_TOOL_TIP=Verpasste Anrufe von: service.gui.MISSED_CALLS_MORE_TOOL_TIP= und {0} mehr service.gui.MODERATOR=Moderator -service.gui.MORE=Mehr service.gui.MORE_LABEL=Mehr service.gui.MOVE=Verschieben service.gui.MOVE_SUBCONTACT=Kontakt &verschieben @@ -358,7 +346,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Der Zielkontakt ist derselbe wie der Ausgangs service.gui.MOVE_SUBCONTACT_QUESTION=Sind Sie sicher, dass Sie {0} nach {1} verschieben wollen? service.gui.MOVE_TO_GROUP=&Verschiebe in Gruppe service.gui.MOVE_CONTACT=Verschiebe Kontakt -service.gui.MOVE_CONTACT_ERROR=&Kontakt kann nicht verschoben werden service.gui.MSG_DELIVERY_FAILURE=Diese Nachricht konnte nicht zugestellt werden service.gui.MSG_DELIVERY_NOT_SUPPORTED=Das verwendete Protokoll kann Nachrichten nur zustellen, wenn Benutzer angemeldet sind. Warten Sie bis {0} wieder angemeldet ist, oder verwenden Sie ein anderes Protokoll. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Ein internes Problem ist aufgetreten. Dies ist wahrscheinlich ein Programmfehler. Bitte melden Sie ihn unter https://jitsi.org/Development/BugsAndIssues. @@ -372,7 +359,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Damit Sie Nachrichten senden können, m service.gui.MULTIPLE_LOGINS=Sie haben mehrere Verbindungen zum selben Konto. Das Konto {0} auf Server {1} ist derzeit nicht verbunden. service.gui.MY_CHAT_ROOMS=Chatraum hinzufügen service.gui.MY_CHAT_ROOMS_TITLE=Chatraum hinzufügen -service.gui.MUTE=Ton aus service.gui.MUTUALLY_ON_HOLD_STATUS=Gegenseitig gehalten service.gui.NAME=Name service.gui.NETWORK=Netzwerk @@ -404,7 +390,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Nicht in Kontaktliste service.gui.SD_QUALITY=Standardqualität service.gui.OFFLINE=Offline service.gui.OK=&OK -service.gui.OLDER_CALLS=Ältere Anrufe service.gui.ONLINE=Online service.gui.OPEN=Öffnen service.gui.OPEN_FILE_FROM_IMAGE=Doppelklicken, um die Datei zu öffnen. @@ -416,7 +401,6 @@ service.gui.OPEN_ON_ACTIVITY=Bei Aktivität service.gui.OPEN_ON_MESSAGE=Bei neuen Nachrichten service.gui.OPEN_ON_IMPORTANT_MESSAGE=Bei wichtigen Nachrichten service.gui.OR=oder -service.gui.OR_ENTER_PHONE_NUMBER=Oder geben Sie eine Telefonnummer hier ein... service.gui.ORGANIZATION=Firma service.gui.OTHER=Andere service.gui.chat.role.OWNER=Besitzer @@ -442,7 +426,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS=''Enter'' für Vorschläge service.gui.PRESS_FOR_CALL_INFO=Anrufdetails service.gui.PRESS_TO_OPEN_CRM=Klicken um die CRM Applikation zu öffnen service.gui.PREVIOUS=Zurück -service.gui.PREVIOUS_TOOLTIP=Suche ältere Gespräche service.gui.PRINT=&Drucken service.gui.PROACTIVE_NOTIFICATION=schreibt eine Mitteilung service.gui.PROBLEMS_ENCOUNTERED=Aufgetretene Probleme @@ -458,7 +441,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Sie haben die Verbindung zu oft vom Serv service.gui.RE_REQUEST_AUTHORIZATION=Autorisierung erneut anfragen service.gui.REFERRED_STATUS=Weitergeleitet service.gui.REJECT=&Zurückweisen -service.gui.REMIND_ME_LATER=Später erinnern service.gui.REMEMBER_PASSWORD=Passwort speichern service.gui.REMOVE=&Entfernen service.gui.REMOVE_ACCOUNT=&Konto entfernen @@ -484,29 +466,23 @@ service.gui.REVOKE_ADMIN=Admin widerrufen service.gui.REVOKE_MODERATOR=Moderator widerrufen service.gui.REVOKE_MEMBERSHIP=Mitgliedschaft widerrufen service.gui.REVOKE_VOICE=Sprecherlaubnis widerrufen -service.gui.ROOT_GROUP=Hauptgruppe service.gui.SAVE=&Speichern -service.gui.SAVE_AS_DEFAULT=Als Standard speichern service.gui.SEARCH=&Suchen service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Betätigen Sie die nachfolgende Schaltfläche um alle Chaträume auf dem ausgewählten Server anzuzeigen. Wählen Sie den Chatraum dem Sie beitreten wollen aus und betätigen Sie "Beitreten". service.gui.SEARCH_STRING_CONTACT_SOURCE=Gesuchter Kontakt service.gui.SECURITY=Sicherheit service.gui.SELECT_ACCOUNT=Konto auswählen +service.gui.SELECT_ACCOUNT_INFO=Welches Konto soll für diesen Kontakt verwendet werden? service.gui.SELECT_COLOR=Farbe auswählen service.gui.SELECT_GROUP=Gruppe auswählen -service.gui.SELECT_GROUP_WIZARD_MSG=Die unten angeführte Liste enthält alle Gruppen Ihrer Kontaktliste. Wählen Sie diejenige aus, zu der Sie den neuen Kontakt hinzufügen wollen. +service.gui.SELECT_GROUP_INFO=Zu welcher Gruppe soll dieser Kontakt hinzugefügt werden? (Optional) service.gui.SELECT_NO_GROUP=Keine Gruppe -service.gui.SELECT_GROUP_WIZARD=Gruppe auswählen service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Die unten angeführte Liste zeigt alle Konten, die Gruppenchats unterstützen. Wählen Sie eines aus und erstellen Sie einen Chatraum. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Die folgende Liste enthält alle Ihre registrierten Benutzerkonten. Bitte wählen Sie das Benutzerkonto aus, das sie für den neuen Kontakt verwenden möchten. -service.gui.SELECT_PROVIDERS_WIZARD=Konto auswählen service.gui.SELECT_VIDEO_CONFERENCE=Videokonferenz auswählen service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Wählen Sie einen Chatraum aus der Liste aus und betätigen Sie OK um ihn hinzuzufügen. service.gui.SEND=&Senden service.gui.SEND_FILE=Datei s&enden -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Für diesen Kontakt sind keine Informationen verfügbar. service.gui.SEND_MESSAGE=Eine Nachricht &Senden -service.gui.SEND_AS_SMS=Als SMS Versenden service.gui.SEND_PRIVATE_MESSAGE=Private Nachricht senden service.gui.SEND_SMS=SMS vers&enden service.gui.SEND_SMS_DETAILS=Die Telefonnummer muss einschließlich der internationalen Vorwahl eingegeben werden, z. B. mit der +49 für eine deutsche Nummer. Beispiel: +491771234567 @@ -545,7 +521,6 @@ service.gui.STREET=Strasse service.gui.SUBJECT=Thema service.gui.SUMMARY=Zusammenfassung service.gui.TELEPHONY=Telefonie -service.gui.TODAY=Heute service.gui.TOOLS=&Werkzeuge service.gui.TRANSFER=Übertr&agung service.gui.TO=&An: @@ -555,7 +530,6 @@ service.gui.TRANSFER_CALL_TO=Weiterleiten an: service.gui.TRANSPARENCY_NOT_ENABLED=Transparenz ist in Ihrer derzeitigen Konfiguration nicht unterstützt. service.gui.TYPE_YOUR_REQUEST=Formulieren Sie Ihre Anfrage hier service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Die Videoqualität konnte nicht geändert werden. -service.gui.UNMUTE=Ton ein service.gui.USER_IDENTIFIER=Benutzerkennung: service.gui.USER_EXISTS_ERROR=Dieser Benutzer existiert bereits in dem gewählten Netzwerk. Bitte wählen Sie einen anderen Benutzer oder ein anderes Netzwerk/Protokoll. service.gui.USERNAME_NULL=Bitte geben Sie Ihren Benutzernamen und Ihr Passwort ein. @@ -568,7 +542,6 @@ service.gui.USE_PROVISIONING=Provisionierung verwenden service.gui.VALUE=Wert service.gui.VIDEO_CALL=&Videoanruf service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Ansicht service.gui.VIEW_HISTORY=&Verlauf anzeigen service.gui.VIEW_SMILEYS=&Smileys anzeigen @@ -588,9 +561,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Lautstärke anpassen service.gui.WAITING_AUTHORIZATION=Autorisierung ausstehend service.gui.WARNING=Warnung service.gui.YES=Ja -service.gui.YESTERDAY=Gestern -service.gui.EXISTING_ACCOUNT_ERROR=Das von Ihnen eingegebene Konto ist bereits installiert. -service.gui.NEW_MAIL=Sie haben eine neue E-Mail!
    Von: {0} {1}
    Betreff: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Sie haben eine neue E-Mail in ihrem {0} Posteingang:
    service.gui.NEW_GMAIL_MANY_HEADER=Sie haben {2} neue E-Mails in ihrem {0} Posteingang:
    service.gui.NEW_GMAIL_FOOTER=Eine weitere ungelesene Konversation in ihrem Posteingang.
    @@ -617,7 +587,6 @@ service.gui.SECURITY_ERROR=Sicherheitsfehler service.gui.SPEED=Geschwindigkeit: service.gui.SILENT_MEMBER=Stilles Mitglied service.gui.NON_SECURE_CONNECTION=Mit dem Konto {0} kann keine sichere Verbindung hergestellt werden. Um eine Verbindung zu unsicheren Servern herzustellen, muss die Option "Unsichere Verbindung erlauben" in den Kontoeinstellungen aktiviert werden. -service.gui.UPDATE=Aktualisieren service.gui.MOBILE_PHONE=Handy service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Geschäftlich @@ -652,12 +621,10 @@ service.gui.callinfo.CALL_INFORMATION=Anrufinformationen service.gui.callinfo.CALL_IDENTITY=Identität service.gui.callinfo.PEER_COUNT=Anzahl Teilnehmer service.gui.callinfo.IS_CONFERENCE_FOCUS=Konferenz-Organisator -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Verschlüsselung aktiv service.gui.callinfo.CALL_TRANSPORT=Signalisierungskanal-Transport service.gui.callinfo.CALL_DURATION=Anrufdauer service.gui.callinfo.TLS_PROTOCOL=TLS Protokoll service.gui.callinfo.TLS_CIPHER_SUITE=TLS Chiffrensammlung -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=TLS Zertifikatskette service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Das TLS Zertifikat des Servers wird unten angezeigt. service.gui.callinfo.VIEW_CERTIFICATE=Zertifikat anzeigen service.gui.callinfo.CODEC=Codec / Frequenz @@ -677,10 +644,14 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Schlüsselaustauschprotokoll service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Erweiterter ICE Kandidatentyp service.gui.callinfo.ICE_STATE=ICE Verarbeitungsstatus + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Kandidaten ermitteln service.gui.callinfo.ICE_STATE.RUNNING=Verbindungstests service.gui.callinfo.ICE_STATE.COMPLETED=Fertig service.gui.callinfo.ICE_STATE.FAILED=Fehlgeschlagen +service.gui.callinfo.ICE_STATE.TERMINATED=Beendet + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Lokale IP / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Lokale reflexive IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Lokale weitergegebene IP / Port @@ -701,11 +672,12 @@ service.gui.ALWAYS_TRUST=Diesem Zertifikat immer vertrauen service.gui.CERT_DIALOG_TITLE=Zertifikat überprüfen service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} kann die Identität des Servers bei der Verbindung zu {1} nicht verifizieren.

    Das Zertifikat ist nicht vertrauenswürdig, daher kann die Identität des Servers
    nicht automatisch geprüft werden. Wollen Sie die Verbindung trotzdem aufbauen?

    Um mehr Information zu erhalten, klicken Sie auf "Zertifikat anzeigen". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} kann die Identität des Servers nicht überprüfen.

    Das Zertifikat ist nicht vertrauenswürdig, daher kann die Identität des Servers
    nicht automatisch geprüft werden. Wollen Sie die Verbindung trotzdem aufbauen?

    Um mehr Information zu erhalten, klicken Sie auf "Zertifikat anzeigen". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} kann die Identität des Clients nicht überprüfen.

    Das Zertifikat ist nicht vertrauenswürdig, daher kann die Identität des Clients
    nicht automatisch geprüft werden. Wollen Sie die Verbindung trotzdem aufbauen?

    Um mehr Information zu erhalten, klicken Sie "Zertifikat anzeigen". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} kann die Identität des Clients {1} nicht überprüfen.

    Das Zertifikat ist nicht vertrauenswürdig, daher kann die Identität des Clients
    nicht automatisch geprüft werden. Wollen Sie die Verbindung trotzdem aufbauen?

    Um mehr Information zu erhalten, klicken Sie auf "Zertifikat anzeigen". service.gui.CONTINUE_ANYWAY=Trotzdem verbinden service.gui.CERT_INFO_CHAIN=Zertifikatskette: service.gui.CERT_INFO_ISSUED_TO=Ausgestellt für + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Allgemeiner Name (CN): service.gui.CERT_INFO_O=Organisation (O): service.gui.CERT_INFO_C=Land (C): @@ -724,12 +696,10 @@ service.gui.CERT_INFO_SIGN_ALG=Signaturalgorithmus: service.gui.CERT_INFO_PUB_KEY_INFO=Informationen zum öffentlichen Schlüssel service.gui.CERT_INFO_ALG=Algorithmus: service.gui.CERT_INFO_PUB_KEY=Öffentlicher Schlüssel: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} Bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} Bits service.gui.CERT_INFO_EXP=Exponent: service.gui.CERT_INFO_KEY_SIZE=Schlüssellänge: service.gui.CERT_INFO_SIGN=Signatur: -service.gui.CONTINUE=Weiter service.gui.SHOW_CERT=Zertifikat anzeigen service.gui.HIDE_CERT=Zertifikat ausblenden @@ -752,12 +722,9 @@ service.gui.security.SECURE_AUDIO=Verschlüsseltes Audio service.gui.security.AUDIO_NOT_SECURED=Audio nicht verschlüsselt service.gui.security.SECURE_VIDEO=Verschlüsseltes Video service.gui.security.VIDEO_NOT_SECURED=Video nicht verschlüsselt -service.gui.security.NO_VIDEO=Kein Video -service.gui.security.CIPHER=Algorithmus: {0} service.gui.security.CALL_SECURED_TOOLTIP=Anruf verschlüsselt. Klicken für weitere Informationen. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Anruf nicht verschlüsselt service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Klicken um SAS mit dem Gesprächspartner zu vergleichen. -service.gui.security.COMPARE_WITH_PARTNER=Vergleiche mit Gesprächspartner und klicke auf das Vorhängeschloß, um zu bestätigen. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Mit Gesprächspartner vergleichen: service.gui.security.STRING_COMPARED=SAS bestätigt @@ -775,20 +742,20 @@ service.gui.avatar.imagepicker.CLICK=Klicken und lächeln service.gui.avatar.imagepicker.IMAGE_FILES=Bilddateien service.gui.avatar.imagepicker.IMAGE_PICKER=Avatar bearbeiten service.gui.avatar.imagepicker.IMAGE_SIZE=Bildgröße -service.gui.avatar.imagepicker.INITIALIZING=Initialisierung... service.gui.avatar.imagepicker.RESET=Zurücksetzen service.gui.avatar.imagepicker.SET=Auswählen service.gui.avatar.imagepicker.TAKE_PHOTO=Foto aufnehmen -service.gui.avatar.imagepicker.WEBCAM_ERROR=Kamerafehler service.gui.security.encryption.required=Verschlüsselung benötigt service.protocol.ICE_FAILED=Verbindung konnte nicht aufgebaut (ICE fehlgeschlagen, kein Relay gefunden) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ +service.systray.MODE=Tray-Symbol Modus +service.systray.mode.NATIVE=Standard +service.systray.mode.DISABLED=Deaktiviert +service.systray.mode.APPINDICATOR=AppIndicator (Unity, KDE, nicht Standard-Gnome 3; kann unter Debian abstürzen) +service.systray.mode.APPINDICATOR_STATIC=AppIndicator statisch (keine Untermenus für Konten) +service.systray.CLI_NOTE=Wenn die Auswahl nicht funktioniert, kann {0} mit der "--notray" option gestartet werden. Dies erzwingt den Modus "Deaktiviert" und zeigt das GUI. Die Änderung des Tray-Symbol Modus erfordert einen neustart. impl.protocol.sip.XCAP_ERROR_TITLE=Fehler in den servergespeicherten SIP Kontakten impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Ressource {0} kann nicht gelesen werden. Konto: {1} @@ -818,9 +785,7 @@ impl.ldap.QUERY_CUSTOM=Benutzerdefinierte Abfrage impl.ldap.QUERY_CUSTOM_HINT={0} dient als Platzhalter für den Suchbegriff. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Automatisch Platzhalter/Wildcard zum Suchbegriff hinzufügen impl.ldap.QUERY_PHOTO_INLINE=Fotos gemeinsam mit den anderen Attributen abfragen -impl.ldap.NEW=Neu impl.ldap.EDIT=Bearbeiten -impl.ldap.REMOVE=&Entfernen impl.ldap.ENABLED=Aktiv impl.ldap.SERVER_NAME=Name impl.ldap.SERVER_NAME_EXAMPLE=Mein LDAP-Server @@ -853,6 +818,12 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Telefon-Präfix impl.ldap.PHONE_PREFIX_EXAMPLE=Bsp.: 00 +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS=''{0}'' ist keine gültige SIP-Adresse. + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS=''{0}'' ist keine gültige XMPP JID. + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Adressbuch plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Suche im Mac OS X-Adressbuch aktivieren @@ -867,9 +838,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Outlook als Standard-E-Mail-Anw # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google-Kontakte -impl.googlecontacts.NEW=Neu impl.googlecontacts.EDIT=Bearbeiten -impl.googlecontacts.REMOVE=&Entfernen impl.googlecontacts.ENABLED=Aktiv impl.googlecontacts.ACCOUNT_NAME=Konto impl.googlecontacts.SAVE=&Speichern @@ -878,6 +847,10 @@ impl.googlecontacts.USERNAME=Benutzername impl.googlecontacts.PASSWORD=Passwort impl.googlecontacts.PREFIX=Telefon-Präfix impl.googlecontacts.WRONG_CREDENTIALS=Falsche Anmeldedaten für Google-Konto {0} +impl.googlecontacts.OAUTH_DIALOG_TITLE=Google Contacts Authorisierung +impl.googlecontacts.INSTRUCTIONS=

    Klicken Sie auf den Link um dem Google Contacts Plugin Zugriff auf das Konto zu erlauben.

    Wenn Sie dem Link folgen, wird eine Website im Browser geöffnet. Melden Sie sich mit Ihrem Google-Konto an und gestatten den Zugriff. Nach der Genehmigung wird eine code angezeigt. Kopieren Sie diesen Code in das Textfeld und klicken Sie auf 'Speichern'

    Dies muss nur einmal durchgeführt werden. Der Code wird für künftige Zugriffe gespeichert.

    +impl.googlecontacts.CODE=Code: +impl.googlecontacts.HYPERLINK_TEXT=Hier klicken um Zugriff auf {0} zu genehmigen # account info plugin.accountinfo.TITLE=Kontoinformationen @@ -908,11 +881,8 @@ plugin.accountinfo.ORGANIZATION=Firma: plugin.accountinfo.JOB_TITLE=Beruf: plugin.accountinfo.ABOUT_ME=Über mich: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Benutzerfotos plugin.accountinfo.GLOBAL_ICON=Globalen Avatar verwenden plugin.accountinfo.LOCAL_ICON=Diesen Avatar verwenden: -plugin.accountinfo.CHANGE=Ändern -plugin.accountinfo.ONLY_MESSAGE=Nur Nachrichten # connection info plugin.connectioninfo.TITLE=Verbindungsinformationen @@ -932,52 +902,15 @@ plugin.aimaccregwizz.USERNAME=AIM-Name: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Benutzername und Passwort plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Neues Benutzerkonto anlegen plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Wenn Sie kein AIM-Konto haben, klicken Sie hier, um ein neues Konto zu erstellen. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Standardmäßige Servereinstellungen überschreiben # branding plugin.branding.ABOUT_WINDOW_TITLE=Über {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Instant Messaging -plugin.branding.LOADING=Lade plugin.branding.ABOUT_MENU_ENTRY=&Über Jitsi -plugin.branding.WELCOME_MESSAGE=
    {1} ist derzeit unter aktiver Entwicklung. Die Version, welche Sie derzeit verwenden, ist NUR EXPERIMENTELL und KÖNNTE möglicherweise NICHT wie erwartet funktionieren. Bei {2} finden Sie mehr Informationen.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Alle Rechte vorbehalten. https://jitsi.org
    -plugin.branding.LICENSE=
    Jitsi steht unter der Lizenz der LGPL (http://www.gnu.org).
    +plugin.branding.COPYRIGHT_LICENSE=
    Copyright 2003-{1} {3}, alle Rechte vorbehalten.

    {4} steht unter der {6}.
    plugin.busylampfield.PICKUP=Anruf holen -# Dict protocol -service.protocol.DICTIONARIES=Wörterbücher -plugin.dictaccregwizz.ANY_DICTIONARY=Alle Wörterbücher -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Alle Wörterbücher von {0} -plugin.dictaccregwizz.FIRST_MATCH=Erster Treffer -plugin.dictaccregwizz.NO_MATCH=Keine Treffer -plugin.dictaccregwizz.MATCH_RESULT=Keine Definitionen für "{0}" gefunden. Möglicherweise meinten Sie:\n -plugin.dictaccregwizz.INVALID_DATABASE=Das aktuelle Wörterbuch "{0}" existiert nicht mehr auf dem Server. -plugin.dictaccregwizz.INVALID_STRATEGY=Die aktuelle Strategie ist auf dem Server nicht verfügbar. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Das Dict-Service-Protokoll -plugin.dictaccregwizz.HOST=Servername -plugin.dictaccregwizz.SERVER_INFO=Serverinformationen -plugin.dictaccregwizz.STRATEGY_SELECTION=Strategieauswahl -plugin.dictaccregwizz.STRATEGY_LIST=Liste der Strategien: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Suche Strategien -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Wenn keine Übersetzung gefunden wurde, bestimmt die Strategie, wie ähnliche Wörter zu finden sind. Zum Beispiel: die "Präfix-Strategie" sucht Wörter, die den gleichen Anfang (Präfix) wie das zu übersetzende Wort haben. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict-Kontoinformationen -plugin.dictaccregwizz.FIRST_ACCOUNT=Diese Seite erstellt ihr erstes Wörterbuchkonto auf dict.org.\n\nSie können weitere Wöterbuchserver mit "Konto hinzufügen" angeben. Geben sie den Namen des Wöterbuchservers im Feld "Host" an. -plugin.dictaccregwizz.THREAD_CONNECT=Verbindungsaufbau zum Server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Verbindungsaufbau fehlgeschlagen. Dies ist kein Dict-Server oder der Server ist nicht erreichbar. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Rufe Strategien ab -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Keine Strategien auf dem Server gefunden -plugin.dictaccregwizz.POPULATE_LIST=Liste wird geladen -plugin.dictaccregwizz.CLOSING_CONNECTION=Schließe Verbindung - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Um den Facebook-Chat nutzen zu können, müssen Sie einen Benutzernamen
    auf Facebook unter "Kontoeinstellungen" erstellen.


    Achtung: Nachdem Sie einen Benutzernamen erstellt haben, müssen Sie sich von Facebook abmelden.
    Es kann einige Minuten dauern, bis Sie den Benutzernamen hier verwenden können!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Facebook-Chat-Protokoll -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=E-Mail: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Benutzername und Passwort - # generalconfig plugin.generalconfig.AUTO_START={0} beim Systemstart automatisch starten plugin.generalconfig.CHATALERTS_ON_MESSAGE=Zeige Benachrichtigungen in Taskleiste/Dock @@ -987,9 +920,6 @@ plugin.generalconfig.SHOW_HISTORY=Zeige plugin.generalconfig.HISTORY_SIZE=vorherige Nachrichten in neuen Chats plugin.generalconfig.SEND_MESSAGES_WITH=Sende Nachrichten mit: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Chat-Fenster in den Vordergrund holen -plugin.generalconfig.ERROR_PERMISSION=Sie haben nicht die Berechtigung, den Autostart auszuschalten -plugin.generalconfig.TRANSPARENCY=Transparenz -plugin.generalconfig.ENABLE_TRANSPARENCY=Transparenz aktivieren plugin.generalconfig.DEFAULT_LANGUAGE=Sprache plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Die Änderungen werden erst beim nächsten Start aktiv. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% übersetzt @@ -1005,6 +935,8 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Vor dem Wählen Sonderzeichen plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Buchstaben in Telefonnummern in Ziffern umwandeln plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=Bsp. +1-800-ANRUFE -> +1-800-267833 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=Alle Ressourcen verwenden um die Funktionalität eines Kontakts zu ermitteln plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Abtastrate: plugin.generalconfig.OPUS_BITRATE=Durchschnittliche Übertragungsrate (kbps): @@ -1018,6 +950,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Paketverlust immer annehmen: plugin.generalconfig.SILK_SAT=Sprachaktivitätsschwelle (0 bis 1): plugin.generalconfig.SILK_ADVERTISE_FEC=FEC-Unterstützung in SDP angeben: plugin.generalconfig.RESTORE=Voreinstellungen wiederherstellen +plugin.generalconfig.MINIMIZE_NOT_HIDE=Hauptfenster minimieren statt zu schliessen oder verstecken # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish @@ -1076,13 +1009,10 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Kommentar plugin.jabberaccregwizz.RESOURCE=Ressource plugin.jabberaccregwizz.AUTORESOURCE=Erzeuge Ressource automatisch plugin.jabberaccregwizz.PRIORITY=Priorität -plugin.jabberaccregwizz.XMPP_ERROR=XMPP-Fehler plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Unbekannter XMPP-Fehler ({0}). Überprüfen Sie, ob der Name des Servers richtig ist. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Die Passwörter stimmen nicht überein. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Standardmäßige Servereinstellungen überschreiben -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Erweiterte Einstellungen +plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Standardmässige Servereinstellungen überschreiben plugin.jabberaccregwizz.USE_ICE=ICE verwenden -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Google's Jingle/ICE Variante verwenden (experimentell) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=STUN/TURN-Server automatisch konfigurieren plugin.jabberaccregwizz.SUPPORT_TURN=TURN aktivieren plugin.jabberaccregwizz.TURN_USERNAME=TURN-Benutzername @@ -1110,11 +1040,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Nachrichtenkopien deaktivieren plugin.jabberaccregwizz.DTMF_AUTO=Automatische Auswahl zwischen RTP und Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Server-Optionen plugin.jabberaccregwizz.CHANGE_PASSWORD=Kontopasswort ändern -plugin.jabberaccregwizz.NEW_PASSWORD=Neues Passwort -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Neues Passwort bestätigen plugin.jabberaccregwizz.PORT_FIELD_INVALID=Bitte eine gültige Portnummer eingeben um fortzufahren. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Das Konto muss angemeldet sein um das Passwort zu ändern. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Das Passwort ist leer. plugin.jabberaccregwizz.TLS_REQUIRED=Die Verbindung verwendet kein SSL/TLS, eine Passwortänderung wird daher nicht unterstützt. plugin.jabberaccregwizz.PASSWORD_CHANGED=Das Passwort wurde erfolgreich geändert plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Der XMPP-Server unterstützt keine Passwortänderungen. @@ -1128,21 +1055,6 @@ plugin.jabberaccregwizz.RESET=Zurücksetzen plugin.jabberaccregwizz.RESET_DESCRIPTION=Auf globale Einstellungen zurücksetzen plugin.jabberaccregwizz.DISABLE_JINGLE=Jingle deaktivieren (Audio- und Videoanrufe mit XMPP) -# mailbox -plugin.mailbox.OUTGOING=Ausgehende Meldung: -plugin.mailbox.INCOMING=Eingehende Meldung: -plugin.mailbox.WAIT_TIME=Warten, bis Anruf an den Anrufbeantworter weitergeleitet wurde -plugin.mailbox.MAX_MESSAGE_TIME=Maximale Dauer eingehender Meldungen -plugin.mailbox.CONFIRM=Bestätigen -plugin.mailbox.DEFAULTS=Voreinstellungen -plugin.mailbox.MAILBOX=Anrufbeantworter - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN/Live Messenger -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Das MSN/Live Messenger-Protokoll. -plugin.msnaccregwizz.USERNAME=E-Mail: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Kontoinformationen - # plugin manager plugin.pluginmanager.INSTALL=Installieren plugin.pluginmanager.UNINSTALL=Deinstallieren @@ -1171,9 +1083,9 @@ plugin.sipaccregwizz.SERVER_PORT=Server-Port plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxy-Port plugin.sipaccregwizz.PREFERRED_TRANSPORT=Bevorzugter Transport -plugin.sipaccregwizz.ADVANCED_OPTIONS=Erweiterte Optionen plugin.sipaccregwizz.PROXY_OPTIONS=Proxy-Server-Optionen plugin.sipaccregwizz.PROXY_AUTO=Proxy-Server automatisch konfigurieren +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Proxy-Sicherheitsprüfung deaktivieren (nur für Hochverfügbarkeitsszenarien) plugin.sipaccregwizz.ENABLE_PRESENCE=Anwesenheitsfunktion aktivieren (SIMPLE) plugin.sipaccregwizz.FORCE_P2P_PRESENCE=Anwesenheitsmodus "Peer-To-Peer" erzwingen plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=Abfrageintervall für Offline-Kontakte (in Sekunden) @@ -1191,8 +1103,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Automatische Auswahl zwischen RTP und Inband (kei plugin.sipaccregwizz.DTMF_RTP=RTP (RFC2833 / RFC4733) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Servervoreinstellungen überschreiben plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Verschlüsselte Anrufe zulassen plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Unterstützung von ZRTP in der Protokollsignalisierung anzeigen plugin.sipaccregwizz.AUTH_NAME=Name für die Anmeldung @@ -1213,10 +1123,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Anrufbeantworter Abruf-URI plugin.sipaccregwizz.NOT_SAME_PASSWORD=Die Passwörter stimmen nicht überein. plugin.sipaccregwizz.NO_CERTIFICATE= (reguläre Anmeldung verwenden) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP Transport-Attribut +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Aus (nur RTP/AVP wird angeboten) plugin.sipaccregwizz.SAVP_OPTION_1=Zwingend (nur RTP/SAVP anbieten und annehmen) plugin.sipaccregwizz.SAVP_OPTION_2=Optional (RTP/SAVP zuerst anbieten, dann RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=S-Descriptor Verschlüsselung aktivieren (auch bekannt als SDES oder SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Aktivierte Verschlüsselungsprotokolle und Priorität: plugin.sipaccregwizz.CIPHER_SUITES=Aktivierte Verschlüsselungs-Suiten plugin.sipaccregwizz.SECURITY_WARNING=
    {0} versucht automatisch alle Anrufe mit ZRTP zu verschlüsseln. Beide Gesprächsteilnehmer hören und sehen eine Benachrichtigung sobald eine sichere Verbindung hergestellt wurde. Die erweiterten Einstellungen auf dieser Seite sollten ohne Expertenwissen nicht geändert werden.
    @@ -1230,15 +1140,6 @@ plugin.skinmanager.DEFAULT_SKIN=Standard Skin plugin.skinmanager.ADD_NEW_SKIN=Neuen Skin hinzufügen... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Der Standard-Skin der Anwendung. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=SSH ist ein Protokoll für die verschlüsselte Verbindung zu anderen Computern. -plugin.sshaccregwizz.USERNAME=Benutzerkennung: -plugin.sshaccregwizz.IDENTITY_FILE=Identitätsdatei: -plugin.sshaccregwizz.KNOWN_HOSTS=Bekannte Server: -plugin.sshaccregwizz.OPTIONAL=Optional -plugin.sshaccregwizz.ACCOUNT_DETAILS=Kontodetails - # status update plugin.autoaway.AUTO_STATUS=Automatisch abwesend plugin.autoaway.ENABLE_CHANGE_STATUS=Status automatisch auf "abwesend" setzen @@ -1286,22 +1187,6 @@ plugin.whiteboard.DESELECT=Auswahl aufheben plugin.whiteboard.DELETE=Löschen plugin.whiteboard.PROPERTIES=Einstellungen -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Das Yahoo!-Protokoll. -plugin.yahooaccregwizz.USERNAME=Benutzername: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Kontoinformationen - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Das Zeroconf-Protokoll (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Vorname: -plugin.zeroaccregwizz.LAST_NAME=Nachname: -plugin.zeroaccregwizz.EMAIL=E-Mail: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Bonjour-Kontakte merken? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Kontoinformationen -plugin.zeroaccregwizz.USERID=Benutzerkennung - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Das Google Talk-Protokoll @@ -1315,19 +1200,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, das Portal für IP-Teleko plugin.iptelaccregwizz.USERNAME=Benutzername plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Bei iptel.org anmelden -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP und Chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Benutzername plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Passwort wiederholen plugin.sip2sipaccregwizz.EMAIL=E-Mail Adresse -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Um Hilfe für diesen Dienst zu erhalten, besuchen Sie bitte die Seite
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Die E-Mail Adresse wird verwendet, um Nachrichten des Anrufbeantworters und Benachrichtigungen über verpasste Anrufe zu erhalten sowie um ein vergessenes Passwort zurückzusetzen -plugin.sip2sipaccregwizz.INFO_NOTE=Um Hilfe für diesen Dienst zu erhalten, besuchen Sie bitte die Seitehttp://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Bestehendes sip2sip.info-Konto -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Kostenloses sip2sip.info-Konto erstellen - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Sofortnachrichten plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Um Hilfe für diesen Dienst zu erhalten, besuchen Sie bitte die Seite
    http://ippi.fr @@ -1336,6 +1213,8 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Existierendes ippi-Konto plugin.ippiaccregwizz.CREATE_ACCOUNT=Kostenloses ippi-Konto erstellen # key binding chooser +plugin.keybindings.WAITING=Kurzbefehl hinzufügen... +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Gesprächsfenster schließen plugin.keybindings.CHAT_COPY=Kopieren plugin.keybindings.CHAT_CUT=Ausschneiden @@ -1358,10 +1237,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Aktion plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primäre Tastenkombination plugin.keybindings.globalchooser.SHORTCUT_SECOND=Sekundäre Tastenkombination plugin.keybindings.globalchooser.PRESS_BTN=Taste drücken um Verknüpfung zu setzen -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Warte plugin.keybindings.globalchooser.PUSH_TO_TALK=Sprechtaste plugin.keybindings.globalchooser.ENABLE_SPECIAL=Erkennung von Spezialtasten aktivieren plugin.keybindings.PLUGIN_NAME=Tastenkombinationen +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Hauptfenster plugin.keybindings.GLOBAL=Systemweit @@ -1389,6 +1268,7 @@ plugin.notificationconfig.tableheader.SOUND=Ton über Benachrichtigungsgerät ab plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Ton über Wiedergabegerät abspielen plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Ton über PC-Lautsprecher abspielen plugin.notificationconfig.tableheader.DESCRIPTION=Beschreibung der Benachrichtigung +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Eingehender Anruf plugin.notificationconfig.event.SecurityMessage=Sicherheitsmitteilung plugin.notificationconfig.event.IncomingFile=Eingehende Datei @@ -1490,6 +1370,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Zyklische Intra-Aktualisierung impl.neomedia.configform.H264.defaultProfile=Standard-Kodierungsprofil +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Baseline impl.neomedia.configform.H264.defaultProfile.high=High impl.neomedia.configform.H264.defaultProfile.main=Main @@ -1520,7 +1401,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Aktuelles Passwort: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Neues Passwort: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Passwort bestätigen: plugin.securityconfig.masterpassword.MP_TITLE=Master-Passwort -plugin.securityconfig.masterpassword.MP_NOT_SET=(keines) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Falsches aktuelles Passwort, bitte wiederholen. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Das Master-Passwort ist falsch. plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Die Änderung des Passworts ist fehlgeschlagen @@ -1536,7 +1416,7 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Passwort plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(unbekannt) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nicht entschlüsselbar) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Gespeicherte Passwörter -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=&Entfernen +plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Entfernen plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Alle entfernen plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Sind Sie sicher, dass alle Passwörter entfernt werden sollen? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Alle Passwörter entfernen @@ -1632,7 +1512,7 @@ plugin.globalproxy.PROXY_PORT=Proxy-Portnummer plugin.globalproxy.PROXY_USERNAME=Proxy-Benutzername plugin.globalproxy.PROXY_PASSWORD=Proxy-Passwort plugin.globalproxy.DESCRIPTION={0} verwendet von nun an diese Proxy-Konfiguration für alle Protokolle.\nDie Unterstützung für Proxy-Server befindet sich noch im Experimentierstadium und unterstützt noch nicht alle Protokolle. Die folgende Tabelle gibt weitere Hinweise: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    +plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    XMPP + + + +
    ICQ/AIM + + + +
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=DNS ebenfalls tunneln plugin.globalproxy.FWD_DNS_NOTE=Hilfreich bei der Verwendung von Tor. Vermeidet die Offenlegung von DNS-Daten indem der gesamte DNS-Datenverkehr über den Tor-Proxy umgeleitet wird. Wird erst nach einem Neustart aktiv. @@ -1670,7 +1550,6 @@ plugin.provisioning.RESTART_WARNING=Die Änderungen werden erst beim nächsten S plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=UUID in die Zwischenablage kopieren plugin.provisioning.CLIPBOARD_FAILED=UUID konnte nicht in die Zwischenablage kopiert werden -plugin.provisioning.EXIT_ON_FAIL=Programm beenden wenn die Provisionierung fehlschlägt plugin.provisioning.CREDENTIALS=Zuletzt gespeicherte Anmeldedaten plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Soll das gespeicherte Provisionierungspasswort wirklich entfernt werden? plugin.provisioning.PROV_FAILED=Provisionierung fehlgeschlagen @@ -1737,8 +1616,6 @@ util.dns.DNSSEC_WARNING=
    {0} hat versucht den Server {1 #plugin spellcheck plugin.spellcheck.TITLE=Rechtschreibung und Grammatik plugin.spellcheck.MENU=Rechtschreibung und Grammatik prüfen -plugin.spellcheck.LANG=Sprache -plugin.spellcheck.EDIT_PERSONAL_DICT=Bearbeiten plugin.spellcheck.ENABLE_SPELL_CHECK=Rechtschreibprüfung aktivieren plugin.spellcheck.dialog.FIND=Nächster Fehler plugin.spellcheck.dialog.REPLACE=Ersetzen -- cgit v1.1 From 5db8e4256770deda67c98a503ecc1bf0b595c273 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:51:27 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 988 of 1505 strings translated (36 fuzzy). --- resources/languages/resources_pt_BR.properties | 774 +++++++++++++++++++++++-- 1 file changed, 713 insertions(+), 61 deletions(-) diff --git a/resources/languages/resources_pt_BR.properties b/resources/languages/resources_pt_BR.properties index 1769ea8..f8e335b 100644 --- a/resources/languages/resources_pt_BR.properties +++ b/resources/languages/resources_pt_BR.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -29,42 +40,36 @@ service.gui.ABOUT=&Sobre service.gui.ACCEPT=&Aceitar service.gui.ACCOUNT=Conta service.gui.ACCOUNT_ME=Eu -service.gui.ACCOUNT_REGISTRATION_WIZARD=Utilitário para registro de contas +service.gui.ACCOUNT_REGISTRATION_WIZARD=Assistente para registro de contas service.gui.ACCOUNTS=Contas service.gui.ADD=&Adicionar -service.gui.ADD_ACCOUNT=Adicionar conta service.gui.ADD_CONTACT=&Adicionar contato service.gui.ADD_AUTHORIZED_CONTACT=Adicionar {0} à sua lista de contatos -service.gui.ADD_CONTACT_TO_CONTACTLIST=Adicionar contato à sua lista de contatos -service.gui.ADD_CONTACT_TO=&Adicionar contato +service.gui.ADD_CONTACT_TO_CONTACTLIST=Adicionar o contato à sua lista de contatos +service.gui.ADD_CONTACT_TO=&Adicionar contato para service.gui.ADD_CONTACT_ERROR=Falha ao adicionar o contato com a id: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Erro ao adicionar contato service.gui.ADD_CONTACT_EXIST_ERROR=O contato {0}, já está na sua lista de contatos. service.gui.ADD_CONTACT_NETWORK_ERROR=O servidor não respondeu a sua requisição para adicionar o contato com a id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Falha ao adicionar contato com a id: {0}. Operação não suportada. -service.gui.ADD_CONTACT_IDENTIFIER=Insira no campo abaixo a identificação do contato que você deseja adicionar. -service.gui.ADD_CONTACT_WIZARD=Utilitário para adicionar contato service.gui.ADD_CONTACT_NOT_CONNECTED=É preciso estar conectado para que seja possível adicionar um contato. Por favor, conecte-se ao serviço selecionado e tente novamente. service.gui.ADD_GROUP_LOCAL_ERROR=Falha ao adicionar grupo com o nome: {0}. O problema ocorreu durante uma operação de E/S local. service.gui.ADD_GROUP_EXIST_ERROR=O grupo {0} já existe na sua lista de contatos. Por favor escolha outro nome. service.gui.ADD_GROUP_NET_ERROR=Falha ao adicionar grupo com o nome: {0}. O problema ocorreu devido a uma falha na rede. Por favor, verifique sua conexão com a rede e tente novamente. service.gui.ADD_GROUP_ERROR=Falha ao adicionar grupo com o nome: {0}. service.gui.ADD_GROUP_EMPTY_NAME=O nome do grupo não pode ser deixado em branco. -service.gui.ADD_GROUP=Criar grupo -service.gui.ADD_SUBCONTACT=&Adicionar subcontato service.gui.ADDRESS=Endereço service.gui.ADMINISTRATOR=administrador service.gui.ADVANCED=&Avançado -service.gui.ALL=&Tudo service.gui.ALL_CONTACTS=&Todos os contatos service.gui.ALTERNATE_ADDRESS=Endereço alternativo service.gui.APPLY=&Aplicar service.gui.ARE_CALLING={0} estão chamando... service.gui.ARE_NOW=Você agora é {0} +service.gui.AT=em service.gui.AUTHORIZE=&Autorizar service.gui.AUTHORIZATION_ACCEPTED={0} aceitou o seu pedido de autorização. service.gui.AUTHENTICATION_FAILED=A autenticação para {0} falhou. A senha inserida é inválida. -service.gui.AUTHENTICATION_REQUESTED=Autenticação requisitada service.gui.AUTHENTICATION_REQUESTED_SERVER=O servidor {0}, requisitou sua autenticação. service.gui.AUTHENTICATION_REJECTED={0} rejeitou seu pedido de autorização. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autenticação @@ -106,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Você pode inserir seu novo apelido no campo a service.gui.CHANGE_NICKNAME_ERROR=Erro ao mudar o apelido service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Este apelido já existe service.gui.CHANGE_VIDEO_QUALITY=Mudar a qualidade do vídeo remoto -service.gui.CHAT_CONFERENCE_LABEL=Conferências service.gui.CHAT_CONFERENCE_ITEM_LABEL=Conferência de {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Você já está na sala de conversação {0}. service.gui.CHAT_ROOM_CONFIGURATION=Configuração da sala de conversação {0} @@ -120,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=saiu de {0} service.gui.CHAT_ROOM_USER_KICKED=foi expulso de {0} service.gui.CHAT_ROOM_USER_QUIT=saiu de {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Envio de mensagem proibido (fala revogada) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Salva a sala de conversação para uso futuro -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Remove a sala selecionada da lista de salas salvas service.gui.CHAT_ROOM_NAME=Nome da sala de conversação service.gui.CLEAR_CUSTOM_MESSAGES=Limpar mensagens personalizadas service.gui.ROOM_NAME=Sala de conversação -service.gui.AUTOJOIN=Entrar automaticamente service.gui.CHANGE_PASSWORD=Alterar a senha service.gui.CHAT_ROOM_NAME_INFO=Coloque o nome da nova sala de conversação no campo abaixo. service.gui.CHAT_ROOM_NOT_EXIST=A sala {0} não foi encontrada no servidor {1}. Por favor verifique se o nome digitado está correto. service.gui.CHAT_ROOM_NOT_CONNECTED=Você precisa estar logado para entrar na sala de conversação {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Você precisa estar conectado para poder deixar a sala de conversação. -service.gui.CHAT_ROOM_NOT_JOINED=Você precisa entrar na sala de conversação para poder fazer alterações. service.gui.CHAT_ROOM_OPTIONS=Opções de sala de conversação service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=A sala de conversação {0}, requer um registro para poder entrar. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=A sala de conversação {0} requisitou uma senha. @@ -150,22 +150,20 @@ service.gui.CLEAR=Limpar service.gui.CLOSE=F&echar service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Você recebeu uma nova mensagem a menos de 2 segundos. Você tem certeza que deseja fechar esta janela? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Você tem transferências de arquivo ativas. Tem certeza que deseja cancelar elas? -service.gui.CONFIRM=Confirmar service.gui.CONNECTED_STATUS=Conectado service.gui.CONNECTING=Conectando... service.gui.CONNECTING_STATUS=Conectando service.gui.CONNECTING_EARLY_MEDIA_STATUS=Conectando* service.gui.CONNECTION=Conexão -service.gui.CONNECTION_FAILED_MSG=A conexão falhou para as seguintes contas: Nome de usuário: {0}, Nome do servidor: {1}. Por favor, verifique suas conexões de rede ou fale com o administrador para mais informações. service.gui.CONNECTION_EXPIRED_MSG=Você está desconectado do servidor {0}, neste momento. service.gui.CONTACT_NAME=ID ou número -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=O contato escolhido [(0)] não suporta telefonia. +service.gui.CONTACT_NAME_PROMPT=joao.silva@exemplo.com +service.gui.CONTACT_NAME_INFO=Adicione um endereço de mensageiro instantâneo (como joao.ninguem@exemplo.com) ou número VoIP service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=O usuário escolhido [{0}] não tem suporte para conversas em conferência. service.gui.CONTACT_PAUSED_TYPING={0} parou de digitar a mensagem service.gui.CONTACT_TYPING={0} está digitando uma mensagem -service.gui.CONTACT_TYPING_SEND_FAILED=O-ou... Não foi possível informar à {0} que você estava digitando -service.gui.CONTACT_INFO=Informação do &contato -service.gui.CONTACTLIST=Lista de contatos +service.gui.CONTACT_TYPING_SEND_FAILED=Ooops!... Não foi possível informar {0} que você estava digitando +service.gui.CONTACT_INFO=Informações do &contato service.gui.CONTACTS=Contatos service.gui.COPY=&Copiar service.gui.COPY_LINK=Copiar &endereço @@ -175,34 +173,34 @@ service.gui.CREATE_CHAT_ROOM=&Criar sala de conversação... service.gui.CREATE_CHAT_ROOM_ERROR=Falha ao criar a sala de conversação {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Utilitário de sala de conversação service.gui.CREATE_CONFERENCE_CALL=&Criar uma chamada em conferência... -service.gui.CREATE_CONFERENCE_CHAT=&Criar uma conversa em conferência... service.gui.CREATE_GROUP=&Criar grupo... service.gui.CREATE_GROUP_NAME=No campo abaixo coloque o nome do grupo que deseja criar. -service.gui.CREATE_FIRST_GROUP_WIZARD=Sua lista de contatos não contém nenhum grupo. Por favor crie um grupo primeiro (Arquivo/Criar grupo). service.gui.CREATE_VIDEO_BRIDGE=Criar uma ponte de &vídeo... service.gui.CREATE_VIDEO_BRIDGE_MENU=Criar uma ponte de &vídeo -service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Criar ou entrar em uma conferência com vídeo +service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Criar/entrar videoconferência service.gui.CREATE_VIDEO_CONFERENCE=Criar uma nova conferência de vídeo para esta sala de conversação service.gui.CONTACT_INFO_NOT_SUPPORTED=Este contato não suporta informações de contato da web service.gui.CUT=&Recortar -service.gui.DATE=Data service.gui.DELETE=Excluir service.gui.DENY=&Negar service.gui.DESKTOP_SHARING_WARNING=Você tem certeza que deseja iniciar o compartilhamento de área de trabalho?
    Clicar em OK permitirá que os participantes desta chamada vejam sua área de trabalho. service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Você está compartilhando sua tela service.gui.DIALPAD=Discador service.gui.DISPLAY_NAME=Exibir nome +service.gui.DISPLAY_NAME_PROMPT=João Silva +service.gui.DISPLAY_NAME_INFO=Dê um nome a este contato. Se deixado em branco será usado o endereço de MI ou número VoIP. (Opcional) service.gui.DISCONNECTED_STATUS=Desconectado service.gui.DND_STATUS=Não perturbe service.gui.DO_NOT_ASK_AGAIN=Não perguntar novamente service.gui.DO_NOT_SHOW_AGAIN=Não mostrar esta mensagem novamente -service.gui.DOWNLOAD_NOW=&Transferir agora service.gui.DRAG_FOR_SHARING=Arraste aqui tudo que deseja compartilhar... service.gui.DURATION=duração service.gui.DESTROY_CHATROOM=Destruir sala de conversação service.gui.DESTROY_MESSAGE=Para informar outros participantes, por favor, entre uma razão e uma sala alternativa para entrarem. service.gui.EDIT=&Editar service.gui.EDITED_AT=editado em {0} +service.gui.EMAIL=E-mail +service.gui.EMAILS=E-mails service.gui.EMPTY_HISTORY=&Histórico vazio service.gui.ENABLE_DESKTOP_REMOTE_CONTROL=Ativar controle remoto da área de trabalho service.gui.ENABLE_TYPING_NOTIFICATIONS=Informar aos outros quando estiver escrevendo uma mensagem (envia atividade da conversa) @@ -215,12 +213,12 @@ service.gui.ERROR_RECEIVED_FROM=Erro recebido de {0} service.gui.ESTIMATED_TIME=Tempo estimado: service.gui.EVENTS=Eventos service.gui.EXIT=&Sair -service.gui.EXTENDED_CRITERIA=Critério estendido service.gui.GENERAL=Geral service.gui.GENERAL_ERROR=Erro genérico service.gui.GROUP_NAME=Nome do grupo service.gui.FAILED_STATUS=A chamada falhou service.gui.FAILED_TO_JOIN_CHAT_ROOM=Falha ao entrar na sala de conversação com o nome: {0}. +service.gui.FAX=Fax service.gui.FFC_STATUS=Disponível para conversar service.gui.FILE=&Arquivo service.gui.FILE_WAITING_TO_ACCEPT=Aguardando aceitação de arquivo para {0}. @@ -240,10 +238,13 @@ service.gui.FILE_TRANSFER_PREPARING=Preparando transferência de arquivo com {0} service.gui.FILE_TRANSFER_REQUEST_RECIEVED={0} está compartilhando um arquivo com você. service.gui.FILE_DOES_NOT_EXIST=O arquivo especificado não pode ser encontrado. Foi deletado ou movido. service.gui.FILE_OPEN_FAILED=Falha ao abrir o arquivo. O arquivo pode ter sido excluído ou movido. +service.gui.FILE_OPEN_NOT_SUPPORTED=Desculpe-nos, a operação com arquivo aberto não é suportada na plataforma atual service.gui.FILE_OPEN_NO_PERMISSION=Você não tem permissões suficientes para abrir este arquivo. Por favor, verifique suas permissões de leitura e tente novamente. service.gui.FILE_OPEN_NO_APPLICATION=Não foi possível encontrar um aplicativo associado a este tipo de arquivo. service.gui.FINISH=&Finalizar +service.gui.FOLDER_DOES_NOT_EXIST=A pasta contendo este arquivo não foi encontrada. Ou ela foi apagada ou foi movida. service.gui.FOLDER_OPEN_FAILED=Falha ao abrir o diretório. +service.gui.FOLDER_OPEN_NO_PERMISSION=Você não tem permissões suficientes para abrir este arquivo. Por favor verifique suas permissões de leitura e tente de novo. service.gui.FOLDER_OPEN_NO_APPLICATION=Não foi possível encontrar um aplicativo para abrir este diretório. service.gui.FONT=Fonte service.gui.FONT_BOLD=Negrito @@ -253,132 +254,621 @@ service.gui.FONT_ITALIC=Itálico service.gui.FONT_SIZE=Tamanho service.gui.FONT_STYLE=Estilo service.gui.FONT_UNDERLINE=Sublinhar -service.gui.FROM={0} de {1} +service.gui.GRANT_OWNERSHIP=Conceder a posse... +service.gui.GRANT_ADMIN=Dar permissão de administrador +service.gui.GRANT_MODERATOR=Dar permissão de moderador +service.gui.GRANT_MEMBERSHIP=Conceder ao membro participação +service.gui.GRANT_VOICE=Conceder voz service.gui.GUEST=visitante service.gui.HANG_UP=Desligar service.gui.HD_QUALITY=Vídeo HD service.gui.HELP=Aj&uda service.gui.HIDE=Ocultar service.gui.HIDE_OFFLINE_CONTACTS=Ocultar contatos desconectados +service.gui.HIDE_MAIN_WINDOW=
    Clicando no botão da janela X não irá fechar o aplicativo, mas somente
    escondê-lo. Se você deseja sair do aplicativo, escolha Arquivo/Fechar.
    +service.gui.HISTORY=&Histórico +service.gui.HISTORY_CONTACT=Histórico - {0} service.gui.HISTORY_TOGGLE_PER_CONTACT=Desativar histórico para este contato service.gui.HISTORY_TOGGLE_PER_CHATROOM=Desativar histórico para esta sala de conversação service.gui.HISTORY_TOGGLE_ALL=Desativar histórico para todas as conversas e contatos service.gui.HISTORY_ERASE_PER_CONTACT=Apagar todo o histórico para este contato +service.gui.HISTORY_ERASE_PER_CHATROOM=Apagar todo o histórico desta sala de conversação service.gui.HISTORY_ERASE_ALL=Apagar todo o histórico de conversação em {0} +service.gui.HISTORY_REMOVE_PER_CONTACT_WARNING=Tem a certeza que deseja remover definitivamente todas as mensagens guardadas localmente para {0}? +service.gui.HISTORY_REMOVE_ALL_WARNING=Tem certeza que deseja remover permanentemente todas as mensagens armazenadas localmente? +service.gui.HISTORY_REMOVE_ERROR=Erro ao remover as mensagens armazenadas localmente. +service.gui.HOME=Inicio +service.gui.HOME_PAGE=Página Inicial +service.gui.ICE=ICE +service.gui.IDENTIFIER=Identificador +service.gui.IGNORE=&Ignorar service.gui.INSERT_SMILEY=Inserir emoticon service.gui.INCOMING_CALL=Chamada recebida de: {0} service.gui.INCOMING_SCREEN_SHARE=Compartilhamento de tela recebido de: {0} +service.gui.INCOMING_CALL_STATUS=Recebendo chamada +service.gui.INCOMING_SCREEN_SHARE_STATUS=Compartilhar a tela de entrada +service.gui.INSTANT_MESSAGINGS=IM's +service.gui.IM=IM +service.gui.INITIATING_CALL_STATUS=Chamada inicializada +service.gui.INVITATION=Texto de convite +service.gui.INVITATION_RECEIVED=Convite recebido service.gui.INVITATION_RECEIVED_MSG={0} convidou você para a sala de conversação {1}. Você pode aceitar, rejeitar ou ignorar este convite. service.gui.INVITATION_REJECTED={0} rejeitou o seu convite para entrar na sala de conversação. Razão: {1}. +service.gui.INVITE=&Convidar service.gui.INVITE_CONTACT_MSG=Selecione os contatos que você gostaria de adicionar à esta conversa, e então clique Convidar. +service.gui.INVITE_CONTACT_TO_CHAT=Convidar contato para chat +service.gui.INVITE_CONTACT_TO_CALL=Convidar contactos para chamada +service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Convide contatos para a videoconferência service.gui.INVITE_REASON=Recebendo chamada de {0}... service.gui.IS_CALLING={0} e está ligando... service.gui.IS_NOW={0} é agora {1} -service.gui.JITSI_WARNING=O SIP Communicator recentemente foi renomeado para Jitsi.
    Se você deseja que sua versão permaneça atualizada, por favor baixe o Jitsi agora.

    Nos desculpamos por qualquer inconveniência que isso possa causar.

    Grupo de desenvolvimento do Jitsi +service.gui.JOIN=&Juntar +service.gui.JOIN_AS=J&untar como service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Participar de uma vídeo conferência já existente +service.gui.JOIN_VIDEO=Juntar video +service.gui.JOB_TITLE=Cargo +service.gui.JOIN_CHAT_ROOM=&Entrar na sala de bate-papo... +service.gui.JOIN_CHAT_ROOM_TITLE=Entrar na sala de bate-papo service.gui.JOIN_CHAT_ROOM_NAME=Por favor, digite o nome da sala de conversação que você gostaria de entrar. +service.gui.JOIN_CHAT_ROOM_WIZARD=Assistente para entrar na sala de bate-papo +service.gui.JOIN_AUTOMATICALLY=Entrar automáticamente +service.gui.DONT_JOIN_AUTOMATICALLY=Não entrar automáticamente +service.gui.KICK=&Expulsar +service.gui.KICK_FAILED=Falha na expulsão service.gui.KICK_FAILED_GENERAL_ERROR=Falha ao expulsar {0}. Ocorreu um erro genérico do servidor. +service.gui.KICK_FAILED_NOT_ALLOWED=Falha na expulsão {0}. O proprietário e o administrador da sala não pode ser expulso. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Falha ao expulsar {0}. Você não tem privilégios suficientes para fazer isto. +service.gui.LAST_NAME=Sobrenome +service.gui.LEAVE=&Sair +service.gui.LIMIT_REACHED_FOR_IP=Você tem muitos registos em uso do mesmo endereço IP local, o {0} servidor não permite abrir mais registos. +service.gui.LIST=Lista service.gui.LOADING_ROOMS=Carregando salas... service.gui.LOADING=Carregando... +service.gui.LOCALLY_ON_HOLD_STATUS=Chamada local em espera +service.gui.LOGIN_NETWORK_ERROR=Impossível logar: Usuário: {0}, Nome do Servidor: {1}, devido a uma falha de rede. Verifique a conexão de rede. +service.gui.LOGIN_GENERAL_ERROR=Um erro ocorreu enquanto tentava logar-se com a conta: Nome de usuário: {0}, Nome do servidor: {1}:{2}. +service.gui.LOGIN_INTERNAL_ERROR=Ocorreu um erro quando se tentava logar com a conta: Usuário: {0}, Servidor: {1}. Isto deve-se provavelmente a um erro interno da aplicação. Reporte o problema a nossa equipe de desenvolvimento (dev@jitsi.java.net). +service.gui.LOGIN_INVALID_PROPERTIES_ERROR=Impossível se conectar com a conta: Usuário: {0}, Servidor: {1}, devido a um erro de configuração. Por favor, verifique a configuração de sua conta. +service.gui.LOGOFF_NOT_SUCCEEDED=Um erro ocorreu enquanto tentava se desconectar da conta: Nome do usuário: {0}, Nome do servidor: {1}. service.gui.LOW_QUALITY=Baixa qualidade service.gui.MEMBER=membro +service.gui.MERGE_TO_CALL=Juntar todas as chamadas +service.gui.MESSAGE=Mensagem service.gui.MISSED_CALLS_TOOL_TIP=Chamadas perdidas de: +service.gui.MISSED_CALLS_MORE_TOOL_TIP= e {0} mais service.gui.MODERATOR=moderador +service.gui.MORE_LABEL=Mais +service.gui.MOVE=Mover +service.gui.MOVE_SUBCONTACT=M&over contato +service.gui.MOVE_SUBCONTACT_MSG=Selecione o contato ou o grupo onde você deseja mover o contato selecionado. +service.gui.MOVE_SUBCONTACT_FAILED=O contato escolhido é o mesmo que \n o contato de origem. Por favor, escolha outro contato! service.gui.MOVE_SUBCONTACT_QUESTION=Você tem certeza que deseja mover {0} para {1}? service.gui.MOVE_TO_GROUP=&Mover para o grupo +service.gui.MOVE_CONTACT=Mover Contato +service.gui.MSG_DELIVERY_FAILURE=Não foi possível entregar a mensagem acima +service.gui.MSG_DELIVERY_NOT_SUPPORTED=O protocolo que você está usando não suporta mensagens offline. Você pode tentar alcançar {0} através de outro protocolo ou aguardar até que ele/ela fique disponível. +service.gui.MSG_DELIVERY_INTERNAL_ERROR=Um erro interno ocorreu. Isto é provavelmente um bug. Por favor informe em: https://jitsi.org/Development/BugsAndIssues. +service.gui.MSG_DELIVERY_ERROR=Falhou ao enviar a mensagem. +service.gui.MSG_DELIVERY_UNKNOWN_ERROR=Um erro desconhecido ocorreu durante o envio de sua mensagem. +service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION=Operação não suportada. +service.gui.MSG_NOT_DELIVERED=Ocorreu um problema de rede. Verifique a sua configuração de rede e tente novamente. +service.gui.MSG_NOT_POSSIBLE=Mensagens não são possíveis para este contato (não é suportado pelo protocolo) +service.gui.MSG_RECEIVED={0} escreveu +service.gui.MSG_SEND_CONNECTION_PROBLEM=Você precisa estar conectado para poder enviar mensagens. +service.gui.MULTIPLE_LOGINS=Você se conectou mais de uma vez com a mesma conta. A conta seguinte: Nome do Usuário: {0}, Nome do Servidor: {1} encontra-se desconectada no momento. service.gui.MY_CHAT_ROOMS=Adicionar sala de conversação service.gui.MY_CHAT_ROOMS_TITLE=Adicionar sala de conversação +service.gui.MUTUALLY_ON_HOLD_STATUS=Ambos em espera +service.gui.NAME=Nome +service.gui.NETWORK=Rede +service.gui.NETWORK_FAILURE=Falha de rede +service.gui.NEXT=Pró&ximo service.gui.NEW_ACCOUNT=Adicionar uma &nova conta... +service.gui.NEW_MESSAGE=Nova mensagem +service.gui.NEW_NAME=Novo nome +service.gui.NEW_STATUS_MESSAGE=Nova mensagem de status +service.gui.NEW_STATUS_MESSAGE_SAVE=Salvar como mensagem personalizada +service.gui.NICKNAME=Apelido +service.gui.NO=Não +service.gui.NONE=Nenhum service.gui.NO_CAMERA_AVAILABLE=Nenhuma câmera disponível +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=Compartilhamento de tela não é suportado por este protocolo +service.gui.NO_VIDEO_ENCODINGS=Nehuma codificação de vídeo foi selecionada na configuração. +service.gui.NO_VIDEO_FOR_PROTOCOL=O vídeo não é suportado por este protocolo +service.gui.NO_AVAILABLE_ROOMS=A lista de salas deste servidor não está disponível no momento. +service.gui.NO_CONTACTS_FOUND=Não foram encontrados contatos. Pressione Ctrl+Enter para chamar {0} ou use os botões abaixo. +service.gui.NO_CONTACTS_FOUND_SHORT=Não foram encontrados contatos. +service.gui.NO_MESSAGE=Sem mensagem +service.gui.NO_GROUP_CHAT_ACCOUNT_AVAILABLE=Não foi encontrada nenhuma conta que suporte conversações de múltiplos usuários. Consulte jitsi.org para mais informações sobre quais protocolos suportam conversações de múltiplos usuários. +service.gui.NO_ONLINE_CONFERENCING_ACCOUNT=Nenhuma conta de conferência disponível. Consulte https://jitsi.org para mais informações sobre quais protocolos suportam conferências. +service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=É necessária pelo menos uma conta telefônica online conectada para fazer a chamada. Por favor conecte-se a uma de suas contas telefônicas e tente novamente. +service.gui.NOT_AUTHORIZED=Não autorizado +service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=Você está tentando fechar uma janela de conversação com uma mensagem não enviada. Tem certeza que quer fechar esta janela de conversação? +service.gui.NON_EXISTING_USER_ID=O servidor {0} não reconhece o id de usuário especificado. +service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Não está na lista de contatos +service.gui.SD_QUALITY=Qualidade normal service.gui.OFFLINE=Desconectado +service.gui.OK=&OK service.gui.ONLINE=Disponível +service.gui.OPEN=Abrir +service.gui.OPEN_FILE_FROM_IMAGE=Duplo clique para abrir o arquivo. +service.gui.OPEN_FOLDER=Abrir pasta +service.gui.OPEN_IN_BROWSER=A&brir no navegador service.gui.OPTIONS=Opções +service.gui.OPEN_AUTOMATICALLY=Abrir esta sala automaticamente quando +service.gui.OPEN_ON_ACTIVITY=Aberto em atividade +service.gui.OPEN_ON_MESSAGE=Abrir somente com mensagem +service.gui.OPEN_ON_IMPORTANT_MESSAGE=Abrir apenas com mensagens importantes +service.gui.OR=ou +service.gui.ORGANIZATION=Empresa +service.gui.OTHER=Outro +service.gui.chat.role.OWNER=Proprietário service.gui.chat.role.ADMINISTRATOR=Administrador service.gui.chat.role.MODERATOR=Moderador service.gui.chat.role.MEMBER=Membro +service.gui.chat.role.GUEST=Convidado +service.gui.chat.role.SILENT_MEMBER=Silenciar membro +service.gui.chat.role.OUTCAST=Proibido de entrar +service.gui.OWNER=dono da sala +service.gui.ON_MOBILE_TOOLTIP=(no celular) +service.gui.PASSWORD=Senha +service.gui.PASSWORD_CHANGE_FAILURE=A alteração de senha falhou +service.gui.PASSWORD_CHANGE_SUCCESS=Senha alterada com sucesso +service.gui.PASTE=&Colar +service.gui.PERSONAL=Pessoal +service.gui.PORT=Porta +service.gui.POSTAL_CODE=Código postal +service.gui.PREFERENCES=Preferências +service.gui.PREFIX=Prefixo +service.gui.PRESENCE=Presença +service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' para sugestões service.gui.PRESS_FOR_CALL_INFO=Pressione para obter informações da chamada +service.gui.PRESS_TO_OPEN_CRM=Clique para abrir aplicação de CRM +service.gui.PREVIOUS=Anterior +service.gui.PRINT=Im&primir +service.gui.PROACTIVE_NOTIFICATION=está escrevendo uma mensagem +service.gui.PROBLEMS_ENCOUNTERED=Problemas encontrados +service.gui.PROTOCOL=Protocolo +service.gui.PUT_OFF_HOLD=Cancelar espera +service.gui.PUT_ON_HOLD=Colocar em espera service.gui.QUIT=&Sair +service.gui.READY=Pronto +service.gui.RECENT_MESSAGES=Conversas recentes +service.gui.REASON=Motivo +service.gui.RECEIVED={0} recebido +service.gui.RECONNECTION_LIMIT_EXCEEDED=Você está sendo conectado e desconectado do servidor muito rápido. A conta seguinte: Nome de usuário: {0}, Nome do servidor: {1} foi temporariamente banida e terá de esperar algum tempo antes de tentar conectar novamente. +service.gui.RE_REQUEST_AUTHORIZATION=Pedir autorização novamente +service.gui.REFERRED_STATUS=Mencionado +service.gui.REJECT=&Rejeitar +service.gui.REMEMBER_PASSWORD=Lembrar senha +service.gui.REMOVE=&Remover +service.gui.REMOVE_ACCOUNT=&Remover conta +service.gui.REMOVE_ACCOUNT_MESSAGE=Tem certeza de que deseja remover esta conta? +service.gui.REMOVE_CONTACT=&Remover contato +service.gui.REMOVE_CONTACT_TEXT=
    Tem certeza que pretende remover {0}
    da sua lista de contatos?
    +service.gui.REMOVE_CONTACT_NOT_CONNECTED=Você precisa estar conectado para remover esse contato. Por favor acesse e tente novamente. +service.gui.REMOVE_GROUP=&Remover grupo +service.gui.REMOTELY_ON_HOLD_STATUS=Remotamente em espera +service.gui.RENAME=&Renomear +service.gui.RENAME_CONTACT=Re&nomear contato +service.gui.RENAME_CONTACT_WIZARD=No campo abaixo você pode definir o nome que deseja usar para o contato. +service.gui.RENAME_GROUP=Re&nomear grupo +service.gui.RENAME_GROUP_INFO=No campo abaixo você pode definir o nome que deseja usar para o grupo. +service.gui.RENAME_CLEAR_USER_DEFINED=Restaurar +service.gui.RINGING_STATUS=Chamando +service.gui.REQUEST=&Solicitar +service.gui.REQUEST_AUTHORIZATION=Solicita&r autorização +service.gui.REQUEST_AUTHORIZATION_MSG=Não foi possível adicionar {0} à sua lista de contatos. {0} terá de autorizar o seu pedido para o/a adicionar. Por favor informe seu pedido abaixo. +service.gui.RETRY=Tentar novamente +service.gui.REVOKE_OWNERSHIP=Revogar propriedade +service.gui.REVOKE_ADMIN=Revogar privilégio de administração +service.gui.REVOKE_MODERATOR=Revogar privilégio de moderador +service.gui.REVOKE_MEMBERSHIP=Revogar participação +service.gui.REVOKE_VOICE=Revogar voz +service.gui.SAVE=&Salvar +service.gui.SEARCH=Pe&squisar +service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Clique no botão abaixo para mostrar todas as salas existentes no servidor selecionado. Depois escolha aquela que você deseja participar e clique no botão Entrar. +service.gui.SEARCH_STRING_CONTACT_SOURCE=Contato pesquisado service.gui.SECURITY=Segurança +service.gui.SELECT_ACCOUNT_INFO=Qual conta deseja usar para se comunicar com este contato? +service.gui.SELECT_COLOR=Selecionar cor +service.gui.SELECT_GROUP=Selecionar grupo +service.gui.SELECT_GROUP_INFO=Em qual grupo deseja incluir este contato? (Opcional) +service.gui.SELECT_NO_GROUP=Sem grupo +service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=A lista abaixo contém todas as contas que suportam o recurso de conversas com múltiplos usuários. Selecione aquela que vocês deseja utilizar para criar sua sala. +service.gui.SELECT_VIDEO_CONFERENCE=Selecionar videoconferência +service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Selecione sala da lista e pressione OK para adicioná-la. +service.gui.SEND=&Enviar +service.gui.SEND_FILE=Enviar &arquivo service.gui.SEND_MESSAGE=&Enviar mensagem +service.gui.SEND_PRIVATE_MESSAGE=Enviar mensagem privada +service.gui.SEND_SMS=&Enviar SMS +service.gui.SEND_SMS_DETAILS=Lembre-se que você tem de introduzir o número no formato internacional; iniciar com +55 para BR; por exemplo: +5521977770000 +service.gui.SEND_SMS_NOT_SUPPORTED=O protocolo que você selecionou não suporta mensagens SMS. +service.gui.SMS=SMS +service.gui.SEND_VIA=Enviar via +service.gui.SENT=enviado +service.gui.SERVER_CHAT_ROOMS=Salas do servidor service.gui.SET_GLOBAL_STATUS=Definir estado global +service.gui.SET_STATUS_MESSAGE=Definir mensagem de status +service.gui.SET_SUBJECT=Definir assunto service.gui.SETTINGS=&Opções +service.gui.SHARE_DESKTOP=&Compartilhar a área de trabalho +service.gui.SHARE_DESKTOP_WITH_CONTACT=Compartilhar área de trabalho com contato +service.gui.SHARE_FULL_SCREEN=Compartilhar tela completa +service.gui.SHARE_REGION=Compartilhar região service.gui.SHOW=Mostrar +service.gui.SHOW_CONTACT_LIST_TOOL_TIP=Clique aqui para fechar a visualização do histórico e mostrar a sua lista de contatos. +service.gui.SHOW_MORE=exibir mais... service.gui.SHOW_OFFLINE_CONTACTS=Mostrar contatos desconectados +service.gui.SIGN_IN=Entrar +service.gui.SMS_SUCCESSFULLY_SENT=Mensagem SMS enviada com sucesso! +service.gui.SMS_SEND_CONNECTION_PROBLEM=Você tem que estar conectado antes de poder enviar mensagens SMS. Conecte-se primeiro ao ser provedor de SMS. +service.gui.SPECIFY_REASON=No campo abaixo você pode definir o motivo desta operação. +service.gui.SPECIFY_SERVER=Complete as informações do servidor da sua conta. service.gui.SOUND_OFF=Desativar sons service.gui.SOUND_ON=Ativar sons +service.gui.START_SHARING=Iniciar compartilhamento +service.gui.STATUS=Status +service.gui.STATUS_CHANGED_CHAT_MESSAGE=tornou-se {0} +service.gui.STATUS_CHANGE_GENERAL_ERROR=Falha na mudança de status da conta: Nome de usuário: {0}, Nome do servidor: {1}, devido a um erro geral. +service.gui.STATUS_CHANGE_NETWORK_FAILURE=Falha na mudança de estado da conta: Nome de usuário: {0}, Nome do servidor: {1}, devido a um problema de rede. +service.gui.STATUS_MESSAGE_INFO=Na linha abaixo pode indicar a nova mensagem que pretende usar. +service.gui.STOP_SHARING=Interromper compartilhamento +service.gui.STREET=Rua +service.gui.SUBJECT=Assunto +service.gui.SUMMARY=Resumo +service.gui.TELEPHONY=Telefonia service.gui.TOOLS=&Ferramentas +service.gui.TRANSFER=Trans&ferência +service.gui.TO=&Para: +service.gui.TRANSFER_CALL_MSG=Selecione o nome do contato que você deseja transferir e depois clique em Transferir. +service.gui.TRANSFER_CALL_TITLE=Transferir Chamada +service.gui.TRANSFER_CALL_TO=Transferir para: +service.gui.TRANSPARENCY_NOT_ENABLED=Transparência não é suportada por sua configuração atual. +service.gui.TYPE_YOUR_REQUEST=Escreva o seu pedido aqui +service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Não foi possível alterar a qualidade do vídeo para esta chamada. +service.gui.USER_IDENTIFIER=Identificador de usuário: +service.gui.USER_EXISTS_ERROR=Este usuário existe na rede selecionada. Escolha outro usuário ou outra rede. +service.gui.USERNAME_NULL=Digite o seu nome de usuário e sua senha. +service.gui.WEBPAGE=Abrir a página web +service.gui.ACCOUNT_CREATION_FAILED=Não foi possível criar a sua conta devido ao erro: {0} +service.gui.UNKNOWN=Usuário desconhecido +service.gui.UNKNOWN_STATUS=Estado desconhecido +service.gui.UNREGISTERED_MESSAGE=Não foi possível conectar à conta: Nome de usuário: {0}, Nome do servidor: {1}. Você está offline. +service.gui.USE_PROVISIONING=Use provisionamento online +service.gui.VALUE=Valor +service.gui.VIDEO_CALL=Chamada de &vídeo +service.gui.VIA=via +service.gui.VIEW=&Visualizar +service.gui.VIEW_HISTORY=Exibir &histórico +service.gui.VIEW_SMILEYS=Exibir &smileys service.gui.VIEW_TOOLBAR=Visualizar &barra de ferramentas +service.gui.VIEW_SIMPLE_CHAT_THEME=Ver tema simples de janela de conversação +service.gui.VOICEMAIL_NEW_URGENT_OLD_RECEIVED={0} nova(s) ({1} urgente(s)) e {2} antigas +service.gui.VOICEMAIL_NEW_URGENT_RECEIVED={0} nova ({1} urgente) mensagens +service.gui.VOICEMAIL_NEW_OLD_RECEIVED={0} novas e {1} mensagens antigas +service.gui.VOICEMAIL_NEW_RECEIVED={0} mensagens novas +service.gui.VOICEMAIL_OLD_RECEIVED={0} mensagens antigas +service.gui.VOICEMAIL_NO_MESSAGES=Sem mensagens. +service.gui.VOICEMAIL_TITLE=Mensagens de voz +service.gui.VOICEMAIL_TOOLTIP=Mensagens de voz para: +service.gui.VOICEMAIL_TIP=Clique no botão de chamada para ouvir suas mensagens. +service.gui.VOICEMAIL_TIP_NO_ACCOUNT=Configure o URI para verificar o voicemail no assistente de conta +service.gui.VOLUME_CONTROL_TOOL_TIP=Ajustar o volume +service.gui.WAITING_AUTHORIZATION=Aguardando autorização +service.gui.WARNING=Alerta +service.gui.YES=Sim +service.gui.NEW_GMAIL_HEADER=Você recebeu uma nova mensagem em sua {0} caixa de entrada:
    +service.gui.NEW_GMAIL_MANY_HEADER=Você recebeu {2} novas mensagens em sua {0} caixa de entrada:
    +service.gui.NEW_GMAIL_FOOTER=mais uma conversa não lida em sua caixa de entrada.
    +service.gui.NEW_GMAIL_MANY_FOOTER={1} mais conversas não lidas em sua caixa de entrada.
    +service.gui.ACTIVATE=Ativar +service.gui.DEACTIVATE=Desativar +service.gui.NEW=Novo +service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Mudar para tela cheia +service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Sair da tela cheia +service.gui.HOLD_BUTTON_TOOL_TIP=Alternar espera +service.gui.MUTE_BUTTON_TOOL_TIP=Alternar Mudo ou segure o botão para ajustar som do microfone +service.gui.PARK=Em espera +service.gui.PARKING_SLOT=Fila de espera +service.gui.PARK_BUTTON_TOOL_TIP=Chamada em espera +service.gui.RECORD_BUTTON_TOOL_TIP=Alternar Gravação +service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=Alternar Vídeo service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Mostrar/Esconder vídeo local service.gui.SHOW_HIDE_PEERS_TOOL_TIP=Mostrar/Esconder lista de participantes da chamada +service.gui.TRANSFER_BUTTON_TOOL_TIP=Transferir chamada +service.gui.TRANSFER_TO=Transferir para... service.gui.SECURITY_INFO=Informações de segurança -service.gui.UPDATE=Atualizar - - +service.gui.SECURITY_WARNING=Alerta de segurança +service.gui.SECURITY_ERROR=Erro de segurança +service.gui.SPEED=Velocidade: +service.gui.SILENT_MEMBER=membro silencioso +service.gui.NON_SECURE_CONNECTION=Não é possível estabelecer uma conexão segura para a conta {0}. Se você quer conectar através de um servidor não seguro, por favor marque "Permitir conexões não seguras" na configuração de sua conta +service.gui.MOBILE_PHONE=Celular +service.gui.VIDEO_PHONE=Vídeo +service.gui.WORK_PHONE=Trabalho +service.gui.PHONE=Telefone +service.gui.PHONES=Telefones +service.gui.EDIT_NOT_SUPPORTED=Edição desta conta não é suportada +service.gui.SHOW_PREVIEW=(exibir visualização) +service.gui.SHOW_PREVIEW_WARNING_DESCRIPTION=Pretende continuar com a visualização desta imagem?\n\nTenha em mente que ao ativar a visualização de Imagem/Vídeo pode comprometer o seu anonimato e expor a sua atividade na rede. +service.gui.SHOW_PREVIEW_DIALOG_TITLE=Mostrar previsualização de Imagem/Video + +service.gui.ZID_NAME_SET=Nome do identificador ZRTP: +service.gui.ZID_NAME_NOT_SET=O nome do identificador ZRTP não está definido. +service.gui.ZID_NAME_BUTTON=Clique para definir o nome do identificador ZRTP. +service.gui.ZID_NAME_DIALOG=Alterar nome do identificador ZRTP +service.gui.ZID_NAME_UNEXPECTED=As chaves ZRTP não coincidem.
    Compare e verifique a string de autenticação entre os equipamentos envolvidos!
    Altere as chaves ZRP e armazene-as somente se a string de autenticação coincidir. + +service.gui.JANUARY=Jan +service.gui.FEBRUARY=Fev +service.gui.MARCH=Mar +service.gui.APRIL=Abr +service.gui.MAY=Mai +service.gui.JUNE=Jun +service.gui.JULY=Jul +service.gui.AUGUST=Ago +service.gui.SEPTEMBER=Set +service.gui.OCTOBER=Out +service.gui.NOVEMBER=Nov +service.gui.DECEMBER=Dez service.gui.callinfo.TECHNICAL_CALL_INFO=Informação técnica da chamada service.gui.callinfo.CALL_INFORMATION=Informações da chamada +service.gui.callinfo.CALL_IDENTITY=Identidade +service.gui.callinfo.PEER_COUNT=Contador de participante +service.gui.callinfo.IS_CONFERENCE_FOCUS=Foco na conferência +service.gui.callinfo.CALL_TRANSPORT=Transporte da chamada de sinalização +service.gui.callinfo.CALL_DURATION=Duração da chamada +service.gui.callinfo.TLS_PROTOCOL=Protocolo TLS +service.gui.callinfo.TLS_CIPHER_SUITE=Conjunto de cifras do TLS +service.gui.callinfo.TLS_CERTIFICATE_CONTENT=O conteudo do certificado do servidor TLS é apresentado abaixo. +service.gui.callinfo.VIEW_CERTIFICATE=Visualizar certificado +service.gui.callinfo.CODEC=Codec / Frequencia +service.gui.callinfo.NA=N.A. +service.gui.callinfo.VIDEO_SIZE=Tamanho do vídeo service.gui.callinfo.AUDIO_INFO=Informações do áudio service.gui.callinfo.VIDEO_INFO=Informações do vídeo - +service.gui.callinfo.LOCAL_IP=IP / Porta Local +service.gui.callinfo.REMOTE_IP=Porta / IP remoto +service.gui.callinfo.BANDWITH=Largura de banda +service.gui.callinfo.LOSS_RATE=Taxa de perda +service.gui.callinfo.RTT=RTT +service.gui.callinfo.JITTER=Jitter +service.gui.callinfo.MEDIA_STREAM_TRANSPORT_PROTOCOL=Protocolo de transporte de streaming +service.gui.callinfo.MEDIA_STREAM_RTP=RTP +service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP +service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocolo de troca de chaves +service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Tipo extendido de candidato ICE +service.gui.callinfo.ICE_STATE=Estado de Processamento ICE + +#enum values from IceProcessingState +service.gui.callinfo.ICE_STATE.WAITING=Reunir candidatos +service.gui.callinfo.ICE_STATE.RUNNING=Verificação de conectividade +service.gui.callinfo.ICE_STATE.COMPLETED=Concluído +service.gui.callinfo.ICE_STATE.FAILED=Falhou + +service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Computador local IP / Porta +service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Porta / IP reflexiva local +service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=IP / Porta local retransmitida +service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=IP / Porta do hospedeiro remoto +service.gui.callinfo.ICE_REMOTE_REFLEXIVE_ADDRESS=IP / Porta reflexiva remota +service.gui.callinfo.ICE_REMOTE_RELAYED_ADDRESS=IP / Porta remota retransmitida +service.gui.callinfo.TOTAL_HARVESTING_TIME=Tempo total de captação +service.gui.callinfo.HARVESTING_TIME=Tempo de captação +service.gui.callinfo.HARVESTING_MS_FOR=ms (para +service.gui.callinfo.HARVESTS=captações) +service.gui.callinfo.DECODED_WITH_FEC=Pacotes decodificados com FEC +service.gui.callinfo.DISCARDED_PERCENT=Pacotes atualmente sendo descartados +service.gui.callinfo.DISCARDED_TOTAL=Número de pacotes descartados +service.gui.callinfo.ADAPTIVE_JITTER_BUFFER=Buffer do jitter adaptativo +service.gui.callinfo.JITTER_BUFFER_DELAY=Buffer de jitter + +service.gui.ALWAYS_TRUST=Sempre confiar neste certificado +service.gui.CERT_DIALOG_TITLE=Verificar Certificado +service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} não pode verificar a identidade do servidor durante a conexão a
    {1}.

    O certificado não é confiável, o que significa que a identidade do servidor não pode ser verificada automaticamente.

    Deseja conectar mesmo assim?
    Para mais informações, clique em "Exibir Certificado". +service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} não pode verificar a identidade do certificado do servidor.

    O certificado não é confiável, o que significa que a identidade do servidor não pode
    ser verificada automaticamente. Deseja continuar com a conexão?

    Para mais informações clique em "Exibir Certificado". service.gui.CONTINUE_ANYWAY=Continuar assim mesmo +service.gui.CERT_INFO_CHAIN=Cadeia de certificados: +service.gui.CERT_INFO_ISSUED_TO=Emitido Por + +#service.gui.CERT_INFO_ are combined from Rdn names +service.gui.CERT_INFO_CN=Nome comum (CN): +service.gui.CERT_INFO_O=Organização: +service.gui.CERT_INFO_C=Nome do País: +service.gui.CERT_INFO_ST=Nome do Estado ou Província: +service.gui.CERT_INFO_L=Nome da Localidade: +service.gui.CERT_INFO_ISSUED_BY=Emitido Por +service.gui.CERT_INFO_OU=Unidade Organizacional: +service.gui.CERT_INFO_VALIDITY=Validade +service.gui.CERT_INFO_ISSUED_ON=Data de emissão: +service.gui.CERT_INFO_EXPIRES_ON=Expira Em: +service.gui.CERT_INFO_FINGERPRINTS=Impressões digitais service.gui.CERT_INFO_CERT_DETAILS=Informação do certificado +service.gui.CERT_INFO_SER_NUM=Numero de Série: +service.gui.CERT_INFO_VER=Versão: +service.gui.CERT_INFO_SIGN_ALG=Algoritmo de assinatura: service.gui.CERT_INFO_PUB_KEY_INFO=Informações da chave pública -service.gui.CONTINUE=Continuar +service.gui.CERT_INFO_ALG=Algoritmo: +service.gui.CERT_INFO_PUB_KEY=Chave pública: +service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits +service.gui.CERT_INFO_EXP=Expoente: +service.gui.CERT_INFO_KEY_SIZE=Tamanho da chave: +service.gui.CERT_INFO_SIGN=Assinatura: +service.gui.SHOW_CERT=Mostrar Certificado service.gui.HIDE_CERT=Ocultar certificado service.gui.AUTO_ANSWER=Atendimento automático e transferência de chamadas service.gui.AUTO_ANSWER_LABEL=Resposta automática - -service.gui.security.NO_VIDEO=Sem vídeo +service.gui.AUTO_ANSWER_ALL_CALLS=Todas as chamadas +service.gui.AUTO_ANSWER_ALERT_INFO_FIELDS=Somente chamadas que requeiram. (Aquelas contendo um campo "Informação-Alerta" definido para "Resposta Automática") +service.gui.AUTO_ANSWER_CUSTOM_FIELDS=Chamadas com o seguinta campo e valor +service.gui.AUTO_ANSWER_FIELD=Campo/Cabeçalho: +service.gui.AUTO_ANSWER_VALUE=Valor: +service.gui.AUTO_ANSWER_DESCR_VLUE=deixe vazio para qualquer +service.gui.AUTO_ANSWER_FWD_CALLS=Encaminhar Chamadas +service.gui.AUTO_ANSWER_FWD_CALLS_TO=Redirecionar todas as chamadas para o seguinte número ou URI: +service.gui.AUTO_ANSWER_VIDEO=Vídeo +service.gui.AUTO_ANSWER_VIDEO_CALLS_WITH_VIDEO=Responder chamadas de vídeo com vídeo +service.gui.LOCAL_VIDEO_ERROR_TITLE=Erro no vídeo local +service.gui.LOCAL_VIDEO_ERROR_MESSAGE=Não foi possível ativar/desativar o vídeo local. + +service.gui.security.SECURE_AUDIO=Áudio seguro +service.gui.security.AUDIO_NOT_SECURED=Áudio inseguro +service.gui.security.SECURE_VIDEO=Vídeo seguro +service.gui.security.VIDEO_NOT_SECURED=Vídeo inseguro service.gui.security.CALL_SECURED_TOOLTIP=Chamada segura. Para mais informações clique aqui. +service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Clique aqui para comparar o seu código de segurança com o do outro participante. # keep the following string short - +service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparar com o outro participante: +service.gui.security.STRING_COMPARED=Código comparado! +service.gui.security.SAS_INFO_TOOLTIP=Para que tudo esteja seguro você
    precisa comparar verbalmente o pequeno
    código de autenticação exibido com o código
    do outro participante e clicar no botão confirmar quando o
    código for verificado.

    Se você não confirmar, será solicitada a verificação
    na próxima vez que chamar este participante. +service.gui.security.SECURITY_ALERT=Tentanto uma chamada segura. Desconectará em + +service.gui.avatar.CHOOSE_ICON=Escolha uma imagem +service.gui.avatar.REMOVE_ICON=Remover a imagem actual +service.gui.avatar.CLEAR_RECENT=Limpar imagens recentes +service.gui.avatar.RECENT_ICONS=Imagens recentes: # service.gui.avatar.imagepicker service.gui.avatar.imagepicker.CANCEL=Cancelar +service.gui.avatar.imagepicker.CHOOSE_FILE=Escolher... +service.gui.avatar.imagepicker.CLICK=Clique e Sorria +service.gui.avatar.imagepicker.IMAGE_FILES=Arquivos de imagem +service.gui.avatar.imagepicker.IMAGE_PICKER=Imagem +service.gui.avatar.imagepicker.IMAGE_SIZE=Tamanho da imagem +service.gui.avatar.imagepicker.RESET=Reiniciar +service.gui.avatar.imagepicker.SET=Definir +service.gui.avatar.imagepicker.TAKE_PHOTO=Tirar uma foto +service.gui.security.encryption.required=Encriptação requerida! +service.protocol.ICE_FAILED=Não foi possível estabelecer a conexão (ICE falhou e transmissão não encontrada) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) +service.systray.MODE=Característica de exibição na bandeja do sistema +service.systray.mode.NATIVE=Padrão +service.systray.mode.DISABLED=Desabilitado +service.systray.CLI_NOTE=Se sua escolha não funcionar, você pode iniciar {0} com o argumento "--notray". Isto força o modo para "Desabilitado" e mostra a interface gráfica ao usuário. Alterar a característica de exibição na bandeja do sistema requer reinicialização. +impl.protocol.sip.XCAP_ERROR_TITLE=Erro no arquivo da lista de contatos SIP +impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=O recurso não pode ser lido {0}. Para {1} +impl.protocol.sip.XCAP_ERROR_UNAUTHORIZED=Usuário ou senha errados usando xcap. Para {0}. # systray +impl.systray.SET_STATUS=Definir estado +impl.systray.FAILED_TO_OPEN_ADD_CONTACT_DIALOG=Falhou ao abrir janela "Adicionar Contato". +impl.systray.POPUP_MESSAGE_HANDLER=Mensagens popup +impl.swingnotification.POPUP_MESSAGE_HANDLER={0} popups +impl.growlnotification.POPUP_MESSAGE_HANDLER=Notificações sonoras +impl.galagonotification.POPUP_MESSAGE_HANDLER=Notificações do freedesktop.org no Ambiente de Trabalho # New Account Dialog +impl.gui.main.account.DEFAULT_PAGE_TITLE=Selecionar Rede +impl.gui.main.account.DEFAULT_PAGE_BODY=Você pode usar a lista acima para selecionar a rede que deseja adicionar uma conta. +impl.gui.main.account.DUMMY_PROTOCOL_NAME=selecione a rede +impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=selecione a rede # LDAP +impl.ldap.CONFIG_FORM_TITLE=Configuração do LDAP impl.ldap.GENERAL=Geral +impl.ldap.FIELDS=Campos +impl.ldap.QUERY=Consulta +impl.ldap.QUERY_DEFAULT=Criar automaticamente +impl.ldap.QUERY_CUSTOM=Consulta personalizada +impl.ldap.QUERY_CUSTOM_HINT=Use {0} como um espaço reservado para o termo de busca. +impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Adicionar coringas automaticamente ao argumento de pesquisa +impl.ldap.QUERY_PHOTO_INLINE=Trazer fotos junto com demais atributos +impl.ldap.EDIT=editar +impl.ldap.ENABLED=Habilitado +impl.ldap.SERVER_NAME=Nome do servidor +impl.ldap.SERVER_NAME_EXAMPLE=Meu servidor LDAP +impl.ldap.SERVER_HOSTNAME=Nome da máquina +impl.ldap.SERVER_EXIST=O servidor já existe, escolha um nome diferente +impl.ldap.USE_SSL=Usar SSL +impl.ldap.AUTH_NONE=Nenhum +impl.ldap.AUTH_SIMPLE=Simples +impl.ldap.SCOPE_SUB_TREE=Sub árvore +impl.ldap.SCOPE_ONE=Um +impl.ldap.SAVE=&Salvar impl.ldap.CANCEL=Cancelar +impl.ldap.SERVER_PORT=Porta +impl.ldap.PASSWORD=Senha +impl.ldap.MAILSUFFIX_FIELD_NAME=Campo(s) de sufixo de e-mail +impl.ldap.WORKPHONE_FIELD_NAME=Campo(s) do telefone do trabalho +impl.ldap.MOBILEPHONE_FIELD_NAME=Campo(s) do celular +impl.ldap.HOMEPHONE_FIELD_NAME=Campo(s) do telefone de casa +impl.ldap.MAIL_FIELD_EXAMPLE=e-mail +impl.ldap.MAILSUFFIX_FIELD_EXAMPLE=@domain.org (não se esqueça de adicionar '@') +impl.ldap.WORKPHONE_FIELD_EXAMPLE=telefoneEmpresa +impl.ldap.MOBILEPHONE_FIELD_EXAMPLE=celularEmpresa +impl.ldap.HOMEPHONE_FIELD_EXAMPLE=telefoneCasa +impl.ldap.PHONE_PREFIX=Prefixo do telefone: + +# SIP Protocol + +#Jabber Protocol # Address book plugin +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE=Erro ao acessar seus contatos do Microsoft Outlook. +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT={0} não é possível acessar os contatos do Microsoft Outlook neste momento porque o Outlook não está definido como a aplicação padrão de e-mail. +plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Definir o Outlook como cliente de e-mail padrão # Google Contacts +impl.googlecontacts.CONFIG_FORM_TITLE=Contatos do Google +impl.googlecontacts.EDIT=editar +impl.googlecontacts.ENABLED=Habilitado +impl.googlecontacts.ACCOUNT_NAME=Nome da conta +impl.googlecontacts.SAVE=&Salvar impl.googlecontacts.CANCEL=Cancelar +impl.googlecontacts.USERNAME=Nome da conta +impl.googlecontacts.PASSWORD=Senha +impl.googlecontacts.PREFIX=Prefixo do telefone: # account info plugin.accountinfo.TITLE=Informações da conta +plugin.accountinfo.DISPLAY_NAME=Exibir nome +plugin.accountinfo.FIRST_NAME=Primeiro nome: +plugin.accountinfo.MIDDLE_NAME=Nome do meio: +plugin.accountinfo.LAST_NAME=Último nome: +plugin.accountinfo.NICKNAME=Apelido: +plugin.accountinfo.URL=URL: +plugin.accountinfo.AGE=Idade: +plugin.accountinfo.BDAY=Data de nascimento: +plugin.accountinfo.BDAY_FORMAT=MMM dd, yyyy +plugin.accountinfo.GENDER=Sexo: plugin.accountinfo.CITY=Cidade: +plugin.accountinfo.POST=Código postal +plugin.accountinfo.COUNTRY=País +plugin.accountinfo.EMAIL=E-mail +plugin.accountinfo.PHONE=Telefone +plugin.accountinfo.MOBILE_PHONE=celularEmpresa +plugin.accountinfo.ORGANIZATION=Nome da organização: +plugin.accountinfo.JOB_TITLE=Função: +plugin.accountinfo.ABOUT_ME=Sobre mim: +plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 +plugin.accountinfo.GLOBAL_ICON=Usar icone global +plugin.accountinfo.LOCAL_ICON=Usar este ícone: # connection info plugin.connectioninfo.TITLE=Informações da conexão # contact info +plugin.contactinfo.USER_PICTURES=Imagens do usuário # aimaccregwizz +plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nome do usuário e senha +plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registrar nova conta # branding +plugin.branding.ABOUT_WINDOW_TITLE=Sobre {0} +plugin.branding.LOGO_MESSAGE=VoIP de código aberto && Mensageiro Instantâneo plugin.branding.ABOUT_MENU_ENTRY=&Sobre -# Dict protocol -plugin.dictaccregwizz.SERVER_INFO=Informações do servidor - -# facebookaccregwizz # generalconfig plugin.generalconfig.GROUP_CHAT_MESSAGES=Agrupar conversas em uma janela plugin.generalconfig.LOG_HISTORY=Salvar histórico das conversas +plugin.generalconfig.SHOW_HISTORY=Mostrar plugin.generalconfig.HISTORY_SIZE=mensagens recentes em novas janelas de conversação plugin.generalconfig.SEND_MESSAGES_WITH=Enviar mensagens utilizando: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Trazer a janela de conversação para a frente @@ -389,13 +879,17 @@ plugin.generalconfig.LEAVE_CHATROOM_ON_WINDOW_CLOSE=Deixar salas de conversaçã plugin.generalconfig.SHOW_RECENT_MESSAGES=Mostrar conversas recentes (o histórico precisa estar habilitado) plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Remover caracteres especiais antes de chamar números telefônicos plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Converter letras em número telefônico -plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=ex.: +1-800-CASA -> +1-800-123456 +plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=Exemplo: 0800-MEUNUMERO-> 0800-638686376 # gibberish accregwizz # icqaccregwizz +plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Registrar nova conta # irc accregwizz +plugin.ircaccregwizz.USERNAME=Apelido +plugin.ircaccregwizz.HOST=Nome da máquina +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autenticação # jabber accregwizz plugin.jabberaccregwizz.NO_STUN_ADDRESS=Por favor insira um endereço de servidor STUN válido para poder continuar. @@ -406,23 +900,24 @@ plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Seu servidor XMPP nã plugin.jabberaccregwizz.PASSWORD_NOT_STORED=A senha foi alterada no servidor, mas a configuração local não foi atualizada plugin.jabberaccregwizz.ENCODINGS=Codificadores plugin.jabberaccregwizz.AUDIO=Áudio - -# mailbox - -# msn accregwizz +plugin.jabberaccregwizz.VIDEO=Vídeo +plugin.jabberaccregwizz.RESET=Reiniciar # plugin manager -plugin.pluginmanager.UPDATE=Atualizar +plugin.pluginmanager.UNINSTALL=Desinstalar +plugin.pluginmanager.NEW=Novo # simple accregwizz # sipaccregwizz +plugin.sipaccregwizz.PROXY_PORT=Porta do servidor proxy +plugin.sipaccregwizz.DISPLAY_NAME=Exibir nome +plugin.sipaccregwizz.CLIST_TYPE=Tipo +plugin.sipaccregwizz.XCAP_PASSWORD=Senha +#used from SecurityPanel # skin manager -# ssh accregwizz -plugin.sshaccregwizz.OPTIONAL=Opcional - # status update plugin.autoaway.ENABLE_CHANGE_STATUS=Mudar o estado quando ausente plugin.autoaway.AWAY_MINUTES=Minutos antes de mudar estado para ausente: @@ -431,6 +926,7 @@ plugin.autoaway.AWAY_MINUTES=Minutos antes de mudar estado para ausente: plugin.updatechecker.DIALOG_TITLE=Instalar atualizações plugin.updatechecker.DIALOG_MESSAGE=Uma nova versão do {0} está disponível. plugin.updatechecker.BUTTON_DOWNLOAD=Transferir +plugin.updatechecker.BUTTON_CLOSE=F&echar plugin.updatechecker.UPDATE_MENU_ENTRY=Procurar por atualizações plugin.updatechecker.DIALOG_NOUPDATE=Sua versão está atualizada. plugin.updatechecker.DIALOG_MISSING_UPDATE=O instalador da atualização não foi encontrado. @@ -438,33 +934,44 @@ plugin.updatechecker.DIALOG_MISSING_UPDATE=O instalador da atualização não fo # usersearch # whiteboard - -# yahoo accregwizz - -# zero accregwizz +plugin.whiteboard.OPEN=Abrir +plugin.whiteboard.COLOR=Cor +plugin.whiteboard.DELETE=Excluir # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +plugin.keybindings.CHAT_COPY=&Copiar +plugin.keybindings.CHAT_CUT=&Recortar +plugin.keybindings.CHAT_PASTE=&Colar +plugin.keybindings.MAIN_RENAME=Re&nomear contato +plugin.keybindings.globalchooser.SHORTCUT_NAME=Nome +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Conversação # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=Habilitar plugin.notificationconfig.DISPLAY_POPUP=Mostrar uma mensagem em uma janela flutuante plugin.notificationconfig.POPUP_NOTIF_HANDLER=Tipo de notificação flutuante plugin.notificationconfig.tableheader.SOUND=Tocar um som usando o dispositivo de notificação plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Tocar um som usando o dispositivo de reprodução de áudio +plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Tocar um som usando o dispositivo de reprodução de áudio +#NotificationsTable constants +plugin.notificationconfig.event.IncomingCall=Recebendo chamada +plugin.notificationconfig.event.IncomingFile=Recebendo chamada plugin.notificationconfig.event.HangUp=Desligar # ZRTP Securing # ZRTP Configuration +impl.media.security.zrtp.CONFIG=Configuração do LDAP impl.media.security.zrtp.TITLE=Chamar +impl.media.security.zrtp.PUB_KEYS=Chave pública: impl.media.security.zrtp.DESCRIPTION=O {0} tentará garantir automaticamente a segurança de suas chamadas. Você receberá um notificação audiovisual quando uma chamada segura for estabelecida. O botão abaixo permite alterar de forma avançada como o {0} se comportará durante negociações ZRTP. Nenhuma alteração é necessária para poder fazer chamadas seguras. Você deverá somente alterar essas configurações se você possuir conhecimento de como ZRTP e encriptação em geral funcionam. @@ -481,54 +988,199 @@ impl.media.configform.ECHOCANCEL=Habilitar cancelamento de eco impl.media.configform.ENCODINGS=Codificadores impl.media.configform.UP=&Subir impl.media.configform.VIDEO=Mais configurações +impl.media.configform.VIDEO_MORE_SETTINGS=Mais configurações impl.media.configform.VIDEO_RESOLUTION=Resolução de vídeo impl.neomedia.configform.AUDIO=Áudio +impl.neomedia.configform.VIDEO=Vídeo +#in JNIEncoder +impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTP # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. # Security configuration form title plugin.securityconfig.TITLE=Segurança +plugin.securityconfig.masterpassword.TITLE=Senha +plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Senha atual: +plugin.securityconfig.masterpassword.ENTER_PASSWORD=Informe sua senha: +plugin.securityconfig.masterpassword.REENTER_PASSWORD=Repita sua senha: +plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Mudança de Senha Falhou +plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS=Senha Alterada +plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS_MSG=Senha Master alterada +plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS_MSG=Senha Master alterada +plugin.securityconfig.masterpassword.COL_TYPE=Tipo +plugin.securityconfig.masterpassword.COL_NAME=Nome +plugin.securityconfig.masterpassword.COL_PASSWORD=Senha +plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=Desconhecido +plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(não é possível decifrar) +plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Senhas armazenadas plugin.securityconfig.masterpassword.HIDE_PASSWORDS_BUTTON=Ocultar senhas # otr plugin +plugin.otr.menu.TITLE=Chat seguro +plugin.otr.menu.START_OTR=Iniciar conversa privada +plugin.otr.menu.END_OTR=Encerrar conversa privada +plugin.otr.menu.LOADING_OTR=Iniciar conversa privada +plugin.otr.menu.TIMED_OUT=Iniciar conversa privada +plugin.otr.menu.REFRESH_OTR=Iniciar conversa privada plugin.otr.menu.WHATS_THIS=O que é isso +plugin.otr.menu.CB_AUTO=Iniciar mensagens privadas automaticamente +plugin.otr.menu.CB_AUTO_ALL=Iniciar mensagens privadas automaticamente +plugin.otr.menu.CB_ENABLE=Habilitar mensagens privadas +plugin.otr.menu.CB_REQUIRE=Exigir mensagens privadas +plugin.otr.menu.CB_RESET=Reiniciar plugin.otr.authbuddydialog.CANCEL=Cancelar plugin.otr.authbuddydialog.HELP=Aj&uda +plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS=Autenticação bem sucedida! +plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL=Autenticação falhou! plugin.otr.configform.MY_PRIVATE_KEYS=Minhas Chaves Privadas +plugin.otr.configform.KNOWN_FINGERPRINTS=Impressões Digitais Conhecidas +plugin.otr.configform.CB_AUTO=Iniciar mensagens privadas automaticamente +plugin.otr.configform.CB_ENABLE=Habilitar mensagens privadas +plugin.otr.configform.CB_REQUIRE=Exigir mensagens privadas plugin.otr.configform.GENERATE=Gerar +plugin.otr.configform.FINGERPRINT=Impressão Digital +plugin.otr.configform.VERIFY_FINGERPRINT=Verificar Impressão Digital plugin.otr.configform.COLUMN_NAME_CONTACT=Contato +plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=Verificada +plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=Sim +plugin.otr.configform.COLUMN_VALUE_VERIFIED_FALSE=Não +plugin.otr.activator.sessionstared=Conversa privada com {0} iniciada. +plugin.otr.activator.sessionlost=Conversa privada com {0} iniciada. +plugin.otr.activator.smpaborted={0} interrompeu o processo de autenticação. +plugin.otr.activator.smperror=Ocorreu um erro no processo de autenticação. +plugin.otr.activator.unencryptedmsgreceived=A mensagem foi recebida não criptografada +plugin.otr.activator.unreadablemsgreceived={0} enviou uma mensagem criptografada ilegível. # global proxy plugin +plugin.globalproxy.GLOBAL_PROXY_CONFIG=Proxy Global +plugin.globalproxy.PROXY_TYPE=Tipo de Servidor Proxy +plugin.globalproxy.PROXY_ADDRESS=Servidor Proxy +plugin.globalproxy.PROXY_PORT=Porta do servidor proxy +plugin.globalproxy.PROXY_USERNAME=Usuário do servidor proxy +plugin.globalproxy.PROXY_PASSWORD=Senha do servidor proxy #plugin.globalproxy.PROTOCOL_SUPPORT +plugin.globalproxy.FWD_DNS_ADDR=Endereço do Proxy DNS +plugin.globalproxy.FWD_DNS_PORT=Porta do DNS Proxy # plugin reconnect +plugin.reconnectplugin.NETWORK_DOWN=Conectividade de rede perdida #plugin chat config plugin.chatconfig.TITLE=Conversação +plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Habilitar substituição de smiley +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Habilitar +plugin.chatconfig.replacement.DISABLE_REPLACEMENT=Desabilitar +plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Fontes: +plugin.chatconfig.spellcheck.TITLE=Corretor Ortográfico #provisioning plugin +plugin.provisioning.PROVISIONING=Provisionamento +plugin.provisioning.ENABLE_DISABLE=Habilitar provisionamento +plugin.provisioning.AUTO=Descobrir automaticamente um URI de provisionamento +plugin.provisioning.DHCP=DHCP +plugin.provisioning.DNS=DNS +plugin.provisioning.URI=URI plugin.provisioning.RESTART_WARNING=Note que suas alterações só terão efeito na próxima vez em que você iniciar o {0}! +plugin.provisioning.UUID=UUID +plugin.provisioning.COPYTOCLIPBOARD=Copiar UUID para área de transferência +plugin.provisioning.CLIPBOARD_FAILED=Falhou ao copiar UUID para área de transferência +plugin.provisioning.FORGET_PASSWORD=Esquecer senha # packet logging service +plugin.loggingutils.PACKET_LOGGING_CONFIG=Log +plugin.loggingutils.ENABLE_DISABLE=Habilitar log de pacotes +plugin.loggingutils.PACKET_LOGGING_RTP=RTP +plugin.loggingutils.PACKET_LOGGING_RTP_DESCRIPTION=(guarda 1 pacote de cada 5000) +plugin.loggingutils.PACKET_LOGGING_ICE4J=ice4j.org +plugin.loggingutils.PACKET_LOGGING_FILE_COUNT=Número de arquivos de log +plugin.loggingutils.PACKET_LOGGING_FILE_SIZE=Tamanho máximo do arquivo (em KB) +plugin.loggingutils.ARCHIVE_BUTTON=Arquivar Logs plugin.loggingutils.UPLOAD_LOGS_BUTTON=Enviar relatórios plugin.loggingutils.UPLOAD_BUTTON=Enviar +plugin.loggingutils.ARCHIVE_FILECHOOSE_TITLE=Escolher arquivo +plugin.loggingutils.ARCHIVE_UPREPORT_EMAIL=johnsmith@email.com +plugin.loggingutils.ARCHIVE_MESSAGE_NOTOK=Erro archivando logs \n{0} # dns config plugin +plugin.dnsconfig.TITLE=DNS +plugin.dnsconfig.DNSSEC=DNS Security (DNSSEC) +plugin.dnsconfig.border.TITLE=Resolvedor backup +plugin.dnsconfig.lblBackupResolver.text=Nome da máquina +plugin.dnsconfig.lblBackupPort.text=Porta +plugin.dnsconfig.lblRedemption.text=Voltar para resolvedor primário +plugin.dnsconfig.dnssec.chkEnabled=Habilitar resolvedor DNSSEC +plugin.dnsconfig.dnssec.lblDefault=Comportamento padrão +plugin.dnsconfig.dnssec.chkAbsolute=Tratar todos os nomes de domínio como absolutos +plugin.dnsconfig.dnssec.lblNameservers=Servidores de nome customizados +plugin.dnsconfig.dnssec.DOMAIN_NAME=Domínio +plugin.dnsconfig.dnssec.MODE=Comportamento +plugin.dnsconfig.dnssec.ENABLE_FAILED=Mudança de estado falhou +plugin.dnsconfig.dnssec.ENABLE_FAILED_MSG=Mudança de estado do DNSSEC falhou. +net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Ignorar +net.java.sip.communicator.util.dns.SecureResolveMode.SecureOnly=Obrigatório +net.java.sip.communicator.util.dns.SecureResolveMode.SecureOrUnsigned=Obrigatório para zonas assinadas +util.dns.INSECURE_ANSWER_TITLE=Falha de DNSSEC +util.dns.INSECURE_ANSWER_MESSAGE_NO_REASON=Resposta do DNS para {0} é insegura. +util.dns.DNSSEC_ADVANCED_OPTIONS=Mostrar opções avançadas +util.dns.DNSSEC_ADVANCED_REASON_UNSIGNED={0} pesquisa por {1} não foi assinada. +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Accept=Aceitar mesmo assim +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysAccept=Aceitar sempre +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=&Negar +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysDeny=Negar sempre #plugin spellcheck +plugin.spellcheck.TITLE=Ortografia e Gramática +plugin.spellcheck.MENU=Mostrar Ortografia e Gramática +plugin.spellcheck.ENABLE_SPELL_CHECK=Habilitar corretor ortográfico +plugin.spellcheck.dialog.FIND=Localizar Próxima +plugin.spellcheck.dialog.REPLACE=Substituir +plugin.spellcheck.dialog.ADD=Acrescentar Palavra +plugin.spellcheck.DICT_ERROR_TITLE=Erro alterando dicionário +plugin.spellcheck.DICT_ERROR=Não é possível alterar dicionário +plugin.spellcheck.DICT_RETRIEVE_ERROR=Dicionário não pode ser obtido de +plugin.spellcheck.UNINSTALL_DICTIONARY=Desinstalar +plugin.spellcheck.DICT_ERROR_DELETE_TITLE=Erro desinstalando dicionário +plugin.spellcheck.DICT_ERROR_DELETE=Não é possível desinstalar dicionário +plugin.spellcheck.SPELLCHECK=Corretor ortográfico #Certificate configuration plugin +plugin.certconfig.TITLE=Configuração TLS +plugin.certconfig.TRUSTSTORE_CONFIG=Fonte de certificados raiz confiáveis +plugin.certconfig.JAVA_TRUSTSTORE=Java +plugin.certconfig.WINDOWS_TRUSTSTORE=Windows +plugin.certconfig.CERT_LIST_TITLE=Configurações de autenticação de cliente TLS +plugin.certconfig.CERT_LIST_DESCRIPTION=As configurações aqui gerenciadas podem ser escolhidas como certificados de cliente TLS nas configurações de conta (ex.: para logar com um certificado em seu provedor SIP em vez de usuário e senha). +plugin.certconfig.ALIAS=Nome do identificador no KeyStore +plugin.certconfig.KEYSTORE_TYPE=Tipo +plugin.certconfig.EDIT_ENTRY=Editar configuração do certificado do cliente TLS plugin.certconfig.KEYSTORE=Arquivo +plugin.certconfig.KEYSTORE_PASSWORD=Senha +plugin.certconfig.INCOMPLETE=Por favor preencha todos os campos +plugin.certconfig.SHOW_CERT_EXCEPTION=Não foi possível mostrar o certificado ({0}). +plugin.certconfig.KEYSTORE_EXCEPTION=Não foi possível carregar o keystore ({0}). +plugin.certconfig.ALIAS_LOAD_EXCEPTION=Não foi possível obter identificadores do keystore ({0}). +plugin.certconfig.INVALID_KEYSTORE_TYPE=O tipo de KeyStore selecionado parece ser inválido ({0}). +plugin.certconfig.BROWSE_KEYSTORE=Abrir KeyStore +plugin.certconfig.REVOCATION_TITLE=Opções de revogação de certificado # Phone number contact source plugin +plugin.phonenumbercontactsource.DISPLAY_NAME=Números telefônicos # properties editor +plugin.propertieseditor.TITLE=Editor de propriedades +plugin.propertieseditor.NEW_PROPERTY_TITLE=Adicionar nova propriedade +plugin.propertieseditor.CHECK_BOX=Mostre este alerta na próxima vez plugin.propertieseditor.DESCRIPTION=O botão abaixo permite alterar as propriedades de configuração do Jitsi. Alterar estas configurações avançadas pode comprometer a estabilidade, segurança e performance deste aplicativo. Você deve continuar apenas se tiver certeza do que está fazendo. +plugin.propertieseditor.IM_AWARE=Estou ciente dos riscos +plugin.propertieseditor.NEED_RESTART=Nota: algumas propriedades exigem reinício antes que as alterações façam efeito. #Thunderbird address book plugin +plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird +plugin.thunderbird.ENABLED=Habilitado +plugin.thunderbird.PHONE_PREFIX=Prefixo do telefone: -- cgit v1.1 From 52556669e76475d8acaa9980ac59959cda95d7e3 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:51:35 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1494 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_zh_TW.properties | 1557 +++++++++++++++++++++++- 1 file changed, 1519 insertions(+), 38 deletions(-) diff --git a/resources/languages/resources_zh_TW.properties b/resources/languages/resources_zh_TW.properties index db996d1..b461fc9 100644 --- a/resources/languages/resources_zh_TW.properties +++ b/resources/languages/resources_zh_TW.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -27,147 +38,1617 @@ service.gui.ABOUT=關於 service.gui.ACCEPT=接受 +service.gui.ACCOUNT=帳號 +service.gui.ACCOUNT_ME=自己 +service.gui.ACCOUNT_REGISTRATION_WIZARD=帳號註冊精靈 service.gui.ACCOUNTS=帳號 service.gui.ADD=新增 -service.gui.ADD_ACCOUNT=新增帳號 service.gui.ADD_CONTACT=新增聯絡人 -service.gui.ADD_AUTHORIZED_CONTACT=新增{0}到你的通訊錄上 -service.gui.ADD_CONTACT_TO_CONTACTLIST=將此聯絡人新增到您的聯絡人列表中 +service.gui.ADD_AUTHORIZED_CONTACT=將 {0} 新增到您的通訊錄 +service.gui.ADD_CONTACT_TO_CONTACTLIST=將此聯絡人新增到您的通訊錄 service.gui.ADD_CONTACT_TO=新增聯絡人到 -service.gui.ADD_CONTACT_ERROR=新增聯絡人:{0}失敗 +service.gui.ADD_CONTACT_ERROR=新增聯絡人 {0} 失敗 service.gui.ADD_CONTACT_ERROR_TITLE=新增聯絡人錯誤 -service.gui.ADD_CONTACT_EXIST_ERROR=聯絡人{0}已經存在於您的聯絡人名單中了。 -service.gui.ADD_CONTACT_NETWORK_ERROR=伺服器未能回應你新增聯絡人ID為{0}的聯絡人的請求。 -service.gui.ADD_CONTACT_NOT_SUPPORTED=無法新增聯絡人Id為{0}的聯絡人。不支援此操作。 - - - - - - +service.gui.ADD_CONTACT_EXIST_ERROR=聯絡人 {0} 已經存在於您的通訊錄中了。 +service.gui.ADD_CONTACT_NETWORK_ERROR=伺服器未回應您新增以下聯絡人的請求: {0} +service.gui.ADD_CONTACT_NOT_SUPPORTED=無法新增聯絡人ID為 {0} 的聯絡人:不支援此操作。 +service.gui.ADD_CONTACT_NOT_CONNECTED=新增聯絡人時必須連上伺服器。請登入後再試。 +service.gui.ADD_GROUP_LOCAL_ERROR=新增群組 {0} 失敗:本地資料存取錯誤。 +service.gui.ADD_GROUP_EXIST_ERROR=群組 {0} 已經存在於您的通訊錄。請另取一個名稱。 +service.gui.ADD_GROUP_NET_ERROR=新增群組 {0} 失敗:網路錯誤。請檢查您的網路連線然後重試。 +service.gui.ADD_GROUP_ERROR=新增群組 {0} 失敗。 +service.gui.ADD_GROUP_EMPTY_NAME=群組名稱不得為空白。 +service.gui.ADDRESS=地址 +service.gui.ADMINISTRATOR=管理員 +service.gui.ADVANCED=進階 +service.gui.ALL_CONTACTS=所有聯絡人 +service.gui.ALTERNATE_ADDRESS=備用地址 +service.gui.APPLY=套用 +service.gui.ARE_CALLING={0} 正在呼叫... +service.gui.ARE_NOW=您現在是 {0} +service.gui.AT=位於 +service.gui.AUTHORIZE=授權 +service.gui.AUTHORIZATION_ACCEPTED={0} 已接受您的授權請求。 +service.gui.AUTHENTICATION_FAILED=帳號 {0} 身份驗證失敗:密碼輸入錯誤。 +service.gui.AUTHENTICATION_REQUESTED_SERVER=伺服器 {0} 已發送了您的身份驗證請求。 +service.gui.AUTHENTICATION_REJECTED={0 } 已拒絕了您的授權請求。 +service.gui.AUTHENTICATION_WINDOW_TITLE={0} 身份驗證 +service.gui.AUTHORIZATION_REQUESTED=已發送授權請求 +service.gui.AUTHORIZATION_REQUESTED_INFO=聯絡人 {0} 請求您的授權。 +service.gui.AUTHORIZATION_RESPONSE=授權回覆 +service.gui.AWAY_STATUS=離開 +service.gui.EXTENDED_AWAY_STATUS=長時間離開 +service.gui.BAN=封鎖 +service.gui.BANNED=已封鎖 +service.gui.BAN_FAILED=封鎖失敗 +service.gui.BAN_FAILED_GENERAL_ERROR=封鎖 {0} 失敗:伺服器發生錯誤。 +service.gui.BAN_FAILED_NOT_ALLOWED=封鎖 {0} 失敗:聊天室的主人和管理員不能被封鎖。 +service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS=封鎖 {0} 失敗:您沒有足夠的權限。 +service.gui.BRB_MESSAGE=我現在不在,稍後回來。 +service.gui.BROWSE=瀏覽 +service.gui.BUSY_MESSAGE=抱歉,我現在有點忙。 +service.gui.BUSY_STATUS=忙碌 +service.gui.CALL=呼叫 +service.gui.CALL_CONTACT=呼叫聯絡人 +service.gui.CALL_FAILED=呼叫失敗 +service.gui.CALL_HISTORY_TOOL_TIP=點擊這裡顯示通話記錄 +service.gui.CALL_HISTORY_GROUP_NAME=通話記錄 +service.gui.CALL_VIA=通話方式: +service.gui.CALL_NAME_OR_NUMBER=通話名稱或號碼 +service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=本次通話僅允許來自 {0} 網路以及您的 {1} 帳號的聯絡人參加,{2} 不在上述範圍。 +service.gui.CALL_WITH=與 ... 通話 +service.gui.CALL_NO_AUDIO_DEVICE=您沒有設定音頻設備。 +service.gui.CALL_NO_AUDIO_CODEC=您沒有啟用任何音頻編碼器。 +service.gui.CALL_NO_DEVICE_CODECS_Q=您要繼續呼叫嗎? +service.gui.CANCEL=取消 +service.gui.CHAT=聊天 +service.gui.CHANGE_FONT=變更字型 +service.gui.CHANGE_ROOM_SUBJECT=修改聊天室主題... +service.gui.CHANGE_ROOM_SUBJECT_LABEL=您可以在下方輸入本聊天室的新主題。 +service.gui.CHANGE_NICK=修改暱稱 +service.gui.CHANGE_NICKNAME=修改暱稱... +service.gui.CHANGE_NICKNAME_LABEL=請輸入您的新暱稱。 +service.gui.CHANGE_NICKNAME_ERROR=更改暱稱時發生錯誤 +service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=暱稱已存在 +service.gui.CHANGE_VIDEO_QUALITY=更改遠端視訊品質 +service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} 的語音會議 +service.gui.CHAT_ROOM_ALREADY_JOINED=您已經加入 {0} 聊天室。 +service.gui.CHAT_ROOM_CONFIGURATION={0} 聊天室設定 +service.gui.CHAT_ROOM_CONFIGURATION_FAILED=獲取 {0} 聊天室設定失敗。 +service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=無法取得 {0} 聊天室設定。只有聊天室的主人可以取得及變更設定。 +service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=無法取得 {0} 聊天室設定。只有聊天室的主人可以取得及變更設定。 +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=編輯成員清單 +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=本聊天室成員列於右側。當聊天室被設定為「僅成員」模式時,只有這些使用者被允許加入。 +service.gui.CHAT_ROOM_USER_JOINED={0} 加入聊天室 +service.gui.CHAT_ROOM_USER_LEFT={0} 離開聊天室 +service.gui.CHAT_ROOM_USER_KICKED={0} 被踢出聊天室 +service.gui.CHAT_ROOM_USER_QUIT={0} 退出聊天室 +service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=訊息發送被封鎖 (您被版主取消發言權了) +service.gui.CHAT_ROOM_NAME=聊天室名稱 +service.gui.CLEAR_CUSTOM_MESSAGES=清除自訂訊息 +service.gui.ROOM_NAME=聊天室 +service.gui.CHANGE_PASSWORD=修改密碼 +service.gui.CHAT_ROOM_NAME_INFO=請輸入新聊天室名稱。 +service.gui.CHAT_ROOM_NOT_EXIST=在伺服器 {1} 上找不到聊天室 {0} 。請檢查名稱是否正確。 +service.gui.CHAT_ROOM_NOT_CONNECTED=您必須先登入伺服器才能加入 {0} 聊天室。 +service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=您必須先登入伺服器才能退出聊天室。 +service.gui.CHAT_ROOM_OPTIONS=聊天室選項 +service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=需要註冊才能加入聊天室 {0} 。 +service.gui.CHAT_ROOM_REQUIRES_PASSWORD=聊天室 {0} 要求輸入密碼。 +service.gui.CHAT_ROOMS=聊天室 +service.gui.CHAT_ROOM=聊天室 +service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} 已將聊天室主題改為:{1} +service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=您可於下列聊天室繼續您的對話:{0} +service.gui.CHAT_NICKNAME_CHANGE={0} 現在是 {1} +service.gui.CHOOSE_CONTACT=選擇聯絡人 +service.gui.CHOOSE_NUMBER=選擇號碼 +service.gui.CHOOSE_ACCOUNT=請從列表中選擇一個帳號。 +service.gui.CITY=城市 +service.gui.COUNTRY=國家 +service.gui.SHOW_MORE_TOOLTIP=點擊查看更多結果 +service.gui.CLEAR=清除 +service.gui.CLOSE=關閉 +service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=您 2 秒前剛收到新訊息。是否要結束本次聊天? +service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=還有檔案沒傳完。您要取消它們嗎? +service.gui.CONNECTED_STATUS=已連線 +service.gui.CONNECTING=連線中... +service.gui.CONNECTING_STATUS=連線中 +service.gui.CONNECTING_EARLY_MEDIA_STATUS=連線中* +service.gui.CONNECTION=連線 +service.gui.CONNECTION_EXPIRED_MSG=您已經中斷與伺服器 {0} 的連線。 +service.gui.CONTACT_NAME=ID或號碼 +service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com +service.gui.CONTACT_NAME_INFO=新增一個及時通訊地址 (比如 jane.doe@example.com)或者 VoIP 號碼 +service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=您選擇的聯絡人 {0} 不支援群組聊天。 +service.gui.CONTACT_PAUSED_TYPING={0} 暫停輸入 +service.gui.CONTACT_TYPING={0} 正在輸入訊息 +service.gui.CONTACT_TYPING_SEND_FAILED=噓!我們不會告訴 {0} 您正在輸入訊息... +service.gui.CONTACT_INFO=聯絡人訊息 +service.gui.CONTACTS=聯絡人 +service.gui.COPY=複製 +service.gui.COPY_LINK=複製鏈結 +service.gui.CREATE=建立 +servoce.gui.CREATE_CALL_FAILED=通話建立失敗 +service.gui.CREATE_CHAT_ROOM=建立聊天室... +service.gui.CREATE_CHAT_ROOM_ERROR=建立聊天室 {0} 失敗 +service.gui.CREATE_CHAT_ROOM_WIZARD=聊天室建立精靈 +service.gui.CREATE_CONFERENCE_CALL=建立語音會議室... +service.gui.CREATE_GROUP=建立新群組... +service.gui.CREATE_GROUP_NAME=請在下面輸入欄中輸入您想要建立的群組名. +service.gui.CREATE_VIDEO_BRIDGE=建立視訊橋接中... +service.gui.CREATE_VIDEO_BRIDGE_MENU=建立視訊橋接 +service.gui.CREATE_JOIN_VIDEO_CONFERENCE=建立/加入視訊會議 +service.gui.CREATE_VIDEO_CONFERENCE=為此聊天室建立一個新的視訊會議 +service.gui.CONTACT_INFO_NOT_SUPPORTED=該聯絡人不支援網路名片 +service.gui.CUT=剪下 +service.gui.DELETE=刪除 +service.gui.DENY=拒絕 +service.gui.DESKTOP_SHARING_WARNING=您確定要開始螢幕共享?
    這個動作將允許對方觀看您的螢幕畫面。 +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=您正在共享螢幕 +service.gui.DIALPAD=撥號盤 +service.gui.DISPLAY_NAME=顯示名稱 +service.gui.DISPLAY_NAME_PROMPT=Jane Doe +service.gui.DISPLAY_NAME_INFO=為這個聯絡人新增一個名稱。如果留空的話,將會使用及時通訊地址或 VoIP 填補。(可選) +service.gui.DISCONNECTED_STATUS=已斷線 +service.gui.DND_STATUS=請勿打擾 +service.gui.DO_NOT_ASK_AGAIN=請勿重複詢問 +service.gui.DO_NOT_SHOW_AGAIN=請勿重複此訊息 +service.gui.DRAG_FOR_SHARING=將任何您想共享的東西拖動到這裡... +service.gui.DURATION=持續時間 +service.gui.DESTROY_CHATROOM=撤銷聊天室 +service.gui.DESTROY_MESSAGE=請提供說明以及替代聊天室的名稱以告知其他參與者。 +service.gui.EDIT=編輯 +service.gui.EDITED_AT=編輯於 {0} +service.gui.EMAIL=電子郵件 +service.gui.EMAILS=電子郵件 +service.gui.EMPTY_HISTORY=清空歷史紀錄 +service.gui.ENABLE_DESKTOP_REMOTE_CONTROL=啟用遠端控制 +service.gui.ENABLE_TYPING_NOTIFICATIONS=讓其他人知道我們正在發訊息(發送對話狀態) +service.gui.END_CONFERENCE=結束會議 +service.gui.ENTER_PHONE_NUMBER=輸入電話號碼 +service.gui.ENTER_NAME_OR_NUMBER=輸入名稱或號碼 +service.gui.ERROR=錯誤 +service.gui.ERROR_WAS=錯誤訊息:{0} +service.gui.ERROR_RECEIVED_FROM=從 {0} 收到錯誤訊息 +service.gui.ESTIMATED_TIME=預估時間: +service.gui.EVENTS=事件 +service.gui.EXIT=退出 +service.gui.GENERAL=通用 +service.gui.GENERAL_ERROR=常見錯誤 +service.gui.GROUP_NAME=群組名稱 +service.gui.FAILED_STATUS=呼叫失敗 +service.gui.FAILED_TO_JOIN_CHAT_ROOM=加入聊天室 {0} 失敗 +service.gui.FAX=傳真 +service.gui.FFC_STATUS=有空聊天 +service.gui.FILE=檔案 +service.gui.FILE_WAITING_TO_ACCEPT=等待 {0} 接收您的檔案 +service.gui.FILE_UNABLE_TO_SEND=向 {0} 傳送檔案時發生錯誤 +service.gui.FILE_RECEIVE_FAILED=從 {0} 接收檔案時發生錯誤 +service.gui.FILE_SENDING_TO=正在向 {0} 傳送檔案 +service.gui.FILE_RECEIVING_FROM=正在從 {0} 接收檔案 +service.gui.FILE_SEND_COMPLETED=向 {0} 傳送檔案成功 +service.gui.FILE_RECEIVE_COMPLETED=從 {0} 接收檔案成功 +service.gui.FILE_TRANSFER_CANCELED=檔案傳輸已取消 +service.gui.FILE_SEND_FAILED=檔案傳送失敗:{0} +service.gui.FILE_TOO_BIG=檔案大小超出通訊協定允許範圍:{0} +service.gui.FILE_SEND_REFUSED={0} 拒收這個檔案 +service.gui.FILE_TRANSFER_REFUSED=檔案傳輸被拒絕 +service.gui.FILE_TRANSFER_NOT_SUPPORTED=您選擇的聯絡人不支持檔案傳輸。 +service.gui.FILE_TRANSFER_PREPARING=正在準備和 {0} 的檔案傳輸。請稍候... +service.gui.FILE_TRANSFER_REQUEST_RECIEVED={0} 正在和您共享檔案 +service.gui.FILE_DOES_NOT_EXIST=無法找到這個檔案,它可能已被刪除或移動到別處。 +service.gui.FILE_OPEN_FAILED=開啟檔案失敗,它可能已被刪除或移動到別處。 +service.gui.FILE_OPEN_NOT_SUPPORTED=對不起!在當前平台上無法開啟檔案 +service.gui.FILE_OPEN_NO_PERMISSION=您沒有足夠的權限來開啟這個檔案。請檢查後重試。 +service.gui.FILE_OPEN_NO_APPLICATION=無法找到應用程式開啟這種類型的檔案 +service.gui.FINISH=完成 +service.gui.FOLDER_DOES_NOT_EXIST=無法找到包含這個檔案的資料夾。它可能已被刪除或移動到別處。 +service.gui.FOLDER_OPEN_FAILED=開啟資料夾失敗 +service.gui.FOLDER_OPEN_NO_PERMISSION=您沒有足夠的權限來開啟這個資料夾。請檢查後重試。 +service.gui.FOLDER_OPEN_NO_APPLICATION=無法找到應用程式開啟這個資料夾 +service.gui.FONT=字型 +service.gui.FONT_BOLD=粗體 +service.gui.FONT_COLOR=顏色 +service.gui.FONT_FAMILY=字型家族 +service.gui.FONT_ITALIC=斜體 +service.gui.FONT_SIZE=大小 +service.gui.FONT_STYLE=樣式 +service.gui.FONT_UNDERLINE=底線 +service.gui.GRANT_OWNERSHIP=晉升為主人 +service.gui.GRANT_ADMIN=提拔為管理員 +service.gui.GRANT_MODERATOR=提拔為主持人 +service.gui.GRANT_MEMBERSHIP=授予成員權限 +service.gui.GRANT_VOICE=授予語音權限 +service.gui.GUEST=訪客 +service.gui.HANG_UP=掛斷 +service.gui.HD_QUALITY=HD視訊 +service.gui.HELP=協助 +service.gui.HIDE=隱藏 +service.gui.HIDE_OFFLINE_CONTACTS=隱藏離線聯絡人 +service.gui.HIDE_MAIN_WINDOW=
    點擊視窗上的 X 只會隱藏視窗,不會退出程式。
    如果您要退出程式,請選擇「檔案/退出」。
    +service.gui.HISTORY=通訊紀錄 +service.gui.HISTORY_CONTACT=歷史記錄 - {0} +service.gui.HISTORY_TOGGLE_PER_CONTACT=關閉此聯絡人的歷史記錄 +service.gui.HISTORY_TOGGLE_PER_CHATROOM=關閉此聊天室的歷史記錄 +service.gui.HISTORY_TOGGLE_ALL=關閉所有聊天室及聯絡人的歷史記錄 +service.gui.HISTORY_ERASE_PER_CONTACT=清除此聯絡人的所有歷史記錄 +service.gui.HISTORY_ERASE_PER_CHATROOM=清除此聊天室的所有歷史記錄 +service.gui.HISTORY_ERASE_ALL=清除在 {0} 的所有聊天記錄 +service.gui.HISTORY_REMOVE_PER_CONTACT_WARNING=您確定要永久刪除 {0} 儲存在這部電腦上的所有訊息嗎? +service.gui.HISTORY_REMOVE_ALL_WARNING=您確認要永久刪除儲存在這部電腦上的所有訊息嗎? +service.gui.HISTORY_REMOVE_ERROR=刪除在這部電腦上的訊息時發生錯誤。 +service.gui.HOME=首頁 +service.gui.HOME_PAGE=首頁 +service.gui.ICE=ICE +service.gui.IDENTIFIER=識別名稱 +service.gui.IGNORE=忽略 +service.gui.INSERT_SMILEY=表情 +service.gui.INCOMING_CALL=來自 {0} 的通話請求 +service.gui.INCOMING_SCREEN_SHARE=來自 {0} 的螢幕共享請求 +service.gui.INCOMING_CALL_STATUS=來電呼叫 +service.gui.INCOMING_SCREEN_SHARE_STATUS=收到螢幕共享請求 +service.gui.INSTANT_MESSAGINGS=即時通訊 +service.gui.IM=即時通訊 +service.gui.INITIATING_CALL_STATUS=通訊正在建立 +service.gui.INVITATION=邀請說明 +service.gui.INVITATION_RECEIVED=收到邀請 +service.gui.INVITATION_RECEIVED_MSG={0} 邀請您加入聊天室 {1} 。您可以選擇同意,拒絕或忽略此邀請。 +service.gui.INVITATION_REJECTED={0} 已經拒絕您的加入聊天室邀請。原因:{1} +service.gui.INVITE=邀請 +service.gui.INVITE_CONTACT_MSG=如果想進行精確搜尋,請輸入該使用者的名稱。 +service.gui.INVITE_CONTACT_TO_CHAT=邀請其他聯絡人加入聊天 +service.gui.INVITE_CONTACT_TO_CALL=邀請其他聯絡人加入呼叫 +service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=邀請其他聯絡人加入視訊橋接 +service.gui.INVITE_REASON=邀請理由 +service.gui.IS_CALLING={0} 正在呼叫... +service.gui.IS_NOW={0} 已更名為 {1} +service.gui.JOIN=加入 +service.gui.JOIN_AS=加入為... +service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=加入現有的視訊會議 +service.gui.JOIN_VIDEO=加入視訊通話 +service.gui.JOB_TITLE=職稱 +service.gui.JOIN_CHAT_ROOM=加入聊天室... +service.gui.JOIN_CHAT_ROOM_TITLE=加入聊天室 +service.gui.JOIN_CHAT_ROOM_NAME=請輸入您想加入的聊天室名稱。 +service.gui.JOIN_CHAT_ROOM_WIZARD=聊天室加入精靈 +service.gui.JOIN_AUTOMATICALLY=自動加入 +service.gui.DONT_JOIN_AUTOMATICALLY=禁止自動加入 +service.gui.KICK=踢出 +service.gui.KICK_FAILED=踢出失敗 +service.gui.KICK_FAILED_GENERAL_ERROR=踢出 {0} 失敗:伺服器發生錯誤。 +service.gui.KICK_FAILED_NOT_ALLOWED=踢出 {0} 失敗:聊天室的主人或管理員不能被踢出。 +service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=踢出 {0} 失敗:您沒有權限 +service.gui.LAST_NAME=姓氏 +service.gui.LEAVE=離開 +service.gui.LIMIT_REACHED_FOR_IP=來自這個本地IP地址的註冊者太多,伺服器 {0} 不再接受新註冊。 +service.gui.LIST=清單 +service.gui.LOADING_ROOMS=正在載入聊天室... +service.gui.LOADING=載入中... +service.gui.LOCALLY_ON_HOLD_STATUS=本地通話保留 +service.gui.LOGIN_NETWORK_ERROR=使用者 {0} 登入 {1} 伺服器失敗:請檢查您的網路連線。 +service.gui.LOGIN_GENERAL_ERROR=使用者 {0} 登入 {1} 伺服器時發生錯誤。 +service.gui.LOGIN_INTERNAL_ERROR=使用者 {0} 登入 {1} 伺服器時發生錯誤:這應該是一個 bug!請將問題 email 回饋至 dev@jitsi.java.net。 +service.gui.LOGIN_INVALID_PROPERTIES_ERROR=使用者 {0} 登入 {1} 伺服器時發生錯誤:請檢查您的帳號設定。 +service.gui.LOGOFF_NOT_SUCCEEDED=使用者 {0} 登出 {1} 伺服器時發生錯誤。 +service.gui.LOW_QUALITY=低品質 +service.gui.MEMBER=成員 +service.gui.MERGE_TO_CALL=合併所有通話 +service.gui.MESSAGE=訊息 +service.gui.MISSED_CALLS_TOOL_TIP=未接來電來自: +service.gui.MISSED_CALLS_MORE_TOOL_TIP= 還有 {0} 條 +service.gui.MODERATOR=主持人 +service.gui.MORE_LABEL=展開 +service.gui.MOVE=移動 +service.gui.MOVE_SUBCONTACT=移動聯絡人 +service.gui.MOVE_SUBCONTACT_MSG=請選擇您要移動聯絡人到哪個群組。 +service.gui.MOVE_SUBCONTACT_FAILED=您選擇的聯絡人已經存在。\n請重新選擇! +service.gui.MOVE_SUBCONTACT_QUESTION=您確認要將 {0} 移動到 {1}? +service.gui.MOVE_TO_GROUP=移動到群組 +service.gui.MOVE_CONTACT=移動聯絡人 +service.gui.MSG_DELIVERY_FAILURE=以上訊息發送失敗 +service.gui.MSG_DELIVERY_NOT_SUPPORTED=您正在使用的通訊協定不支援離線訊息功能。請嘗試其他通訊協定,或者等待 {0} 上線。 +service.gui.MSG_DELIVERY_INTERNAL_ERROR=程式內部發生錯誤:這可能是一個BUG!請回饋問題到:http://www.jitsi.org/index.php/Development/BugsAndIssues +service.gui.MSG_DELIVERY_ERROR=發送訊息失敗。 +service.gui.MSG_DELIVERY_UNKNOWN_ERROR=發送訊息失敗,原因不明。 +service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION=不支持的操作。 +service.gui.MSG_NOT_DELIVERED=網路錯誤。請檢查網路設定後重試。 +service.gui.MSG_NOT_POSSIBLE=無法發送訊息給該聯絡人(通訊協定不支援) +service.gui.MSG_RECEIVED={0} 發送訊息給您了 +service.gui.MSG_SEND_CONNECTION_PROBLEM=請先登入伺服器再發送訊息。 +service.gui.MULTIPLE_LOGINS=使用者 {0} 在其他地方登入,{1} 伺服器連線中斷。 +service.gui.MY_CHAT_ROOMS=聊天室 +service.gui.MY_CHAT_ROOMS_TITLE=新增聊天室 +service.gui.MUTUALLY_ON_HOLD_STATUS=雙方等候接通 +service.gui.NAME=名稱 +service.gui.NETWORK=網路 +service.gui.NETWORK_FAILURE=網路錯誤 +service.gui.NEXT=下一個 +service.gui.NEW_ACCOUNT=建立新帳號... +service.gui.NEW_MESSAGE=新訊息... +service.gui.NEW_NAME=新名稱 +service.gui.NEW_STATUS_MESSAGE=新狀態訊息 +service.gui.NEW_STATUS_MESSAGE_SAVE=存為自定義訊息 +service.gui.NICKNAME=暱稱 +service.gui.NO=否 +service.gui.NONE=無 +service.gui.NO_CAMERA_AVAILABLE=沒有可用的攝影機 +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=此通訊協定不支援桌面共享功能。 +service.gui.NO_VIDEO_ENCODINGS=在設定檔中沒有啟用任何視訊解碼器 +service.gui.NO_VIDEO_FOR_PROTOCOL=此通訊協定不支持視訊通話 +service.gui.NO_AVAILABLE_ROOMS=目前無法取得伺服器上的聊天室列表。 +service.gui.NO_CONTACTS_FOUND=找不到相符的聯絡人。按下 Ctrl+Enter 或使用以下按鈕呼叫 {0} 。 +service.gui.NO_CONTACTS_FOUND_SHORT=未找到相符的聯絡人 +service.gui.NO_MESSAGE=沒有訊息 +service.gui.NO_GROUP_CHAT_ACCOUNT_AVAILABLE=沒有可用的群組聊天帳號。請到 jitsi.org 查詢哪些通訊協定支援群組聊天。 +service.gui.NO_ONLINE_CONFERENCING_ACCOUNT=沒有可用的會議帳號。請到 jitsi.org 查詢哪些通訊協定支援會議。 +service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=呼叫前必須確保至少一個電話帳號在線。請登入您的一個電話帳號然後重試。 +service.gui.NOT_AUTHORIZED=未授權 +service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=您正在嘗試關閉對話,但是還有未發送的訊息。您確定要關閉對話嗎? +service.gui.NON_EXISTING_USER_ID={0} 伺服器無法識別這個使用者 ID。 +service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=不在通訊錄中 +service.gui.SD_QUALITY=標準品質 +service.gui.OFFLINE=離線 +service.gui.OK=確定 +service.gui.ONLINE=在線 +service.gui.OPEN=開啟 +service.gui.OPEN_FILE_FROM_IMAGE=雙擊以開啟檔案 +service.gui.OPEN_FOLDER=開啟資料夾 +service.gui.OPEN_IN_BROWSER=在瀏覽器中開啟 +service.gui.OPTIONS=選項 +service.gui.OPEN_AUTOMATICALLY=在下列情況時自動開啟本聊天室 +service.gui.OPEN_ON_ACTIVITY=有活動時開啟 +service.gui.OPEN_ON_MESSAGE=僅在有訊息時開啟 +service.gui.OPEN_ON_IMPORTANT_MESSAGE=僅在有重要訊息時開啟 +service.gui.OR=或者 +service.gui.ORGANIZATION=組織 +service.gui.OTHER=其他 +service.gui.chat.role.OWNER=主人 +service.gui.chat.role.ADMINISTRATOR=管理員 +service.gui.chat.role.MODERATOR=主持人 +service.gui.chat.role.MEMBER=成員 +service.gui.chat.role.GUEST=遊客 +service.gui.chat.role.SILENT_MEMBER=靜音成員 +service.gui.chat.role.OUTCAST=被禁止加入 +service.gui.OWNER=聊天室主人 +service.gui.ON_MOBILE_TOOLTIP=(手機通話中) +service.gui.PASSWORD=密碼 +service.gui.PASSWORD_CHANGE_FAILURE=密碼修改失敗 +service.gui.PASSWORD_CHANGE_SUCCESS=密碼修改成功 +service.gui.PASTE=貼上 +service.gui.PERSONAL=私人 +service.gui.PORT=通訊埠 +service.gui.POSTAL_CODE=郵遞區號 +service.gui.PREFERENCES=偏好設定 +service.gui.PREFIX=前置字串 +service.gui.PRESENCE=上線狀況 +service.gui.PRESS_ENTER_FOR_SUGGESTIONS=按 Enter 鍵查看建議 +service.gui.PRESS_FOR_CALL_INFO=點擊查看通話訊息 +service.gui.PRESS_TO_OPEN_CRM=點擊開啟CRM程式 +service.gui.PREVIOUS=上一個 +service.gui.PRINT=列印 +service.gui.PROACTIVE_NOTIFICATION=正在輸入訊息 +service.gui.PROBLEMS_ENCOUNTERED=遇到問題 +service.gui.PROTOCOL=通訊協定 +service.gui.PUT_OFF_HOLD=取消等待通話 +service.gui.PUT_ON_HOLD=等待通話 +service.gui.QUIT=退出 +service.gui.READY=就緒 +service.gui.RECENT_MESSAGES=最近的對話 +service.gui.REASON=原因 +service.gui.RECEIVED=收到 {0} +service.gui.RECONNECTION_LIMIT_EXCEEDED=使用者 {0} 重複登入 {1} 伺服器:該帳號暫時被封鎖,請過一段時間後再試。 +service.gui.RE_REQUEST_AUTHORIZATION=重新請求授權 +service.gui.REFERRED_STATUS=轉接 +service.gui.REJECT=拒絕 +service.gui.REMEMBER_PASSWORD=記住密碼 +service.gui.REMOVE=刪除 +service.gui.REMOVE_ACCOUNT=刪除帳號 +service.gui.REMOVE_ACCOUNT_MESSAGE=確定要刪除這個帳號嗎? +service.gui.REMOVE_CONTACT=刪除聯絡人 +service.gui.REMOVE_CONTACT_TEXT=
    確定要將 {0}
    從通訊錄中刪除嗎?
    +service.gui.REMOVE_CONTACT_NOT_CONNECTED=您需要重新連線以移除此聯絡人。請登入後重試。 +service.gui.REMOVE_GROUP=刪除群組 +service.gui.REMOTELY_ON_HOLD_STATUS=對方等候通話 +service.gui.RENAME=重新命名 +service.gui.RENAME_CONTACT=重新命名聯絡人 +service.gui.RENAME_CONTACT_WIZARD=請輸入該聯絡人的新名稱。 +service.gui.RENAME_GROUP=重新命名群組 +service.gui.RENAME_GROUP_INFO=請輸入該群組的新名稱。 +service.gui.RENAME_CLEAR_USER_DEFINED=還原 +service.gui.RINGING_STATUS=響鈴中 +service.gui.REQUEST=請求 +service.gui.REQUEST_AUTHORIZATION=請求授權 +service.gui.REQUEST_AUTHORIZATION_MSG=無法新增 {0} 到您的通訊錄,必須等待 {0} 加您為好友。請輸入您的請求訊息。 +service.gui.RETRY=重試 +service.gui.REVOKE_OWNERSHIP=取消所有權 +service.gui.REVOKE_ADMIN=取消管理者權限 +service.gui.REVOKE_MODERATOR=取消主持人權限 +service.gui.REVOKE_MEMBERSHIP=取消成員權限 +service.gui.REVOKE_VOICE=取消發言權 +service.gui.SAVE=存檔 +service.gui.SEARCH=搜尋 +service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=點擊顯示本伺服器上所有聊天室,選擇您想加入的聊天室再點擊「加入」。 +service.gui.SEARCH_STRING_CONTACT_SOURCE=搜尋到的聯絡人 +service.gui.SECURITY=安全 +service.gui.SELECT_ACCOUNT_INFO=您想使用哪個帳號與這個聯絡人進行通訊? +service.gui.SELECT_COLOR=選擇顏色 +service.gui.SELECT_GROUP=選擇群組 +service.gui.SELECT_GROUP_INFO=您想將此聯絡人放置在哪個群組下顯示?(可選) +service.gui.SELECT_NO_GROUP=未加入群組 +service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=以下是您所有支援群組聊天的帳號。請選擇其中一個以建立聊天室。 +service.gui.SELECT_VIDEO_CONFERENCE=選擇視訊會議 +service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=聊天室 +service.gui.SEND=發送 +service.gui.SEND_FILE=傳送檔案 +service.gui.SEND_MESSAGE=發送訊息 +service.gui.SEND_PRIVATE_MESSAGE=傳送私密訊息 +service.gui.SEND_SMS=發送簡訊 +service.gui.SEND_SMS_DETAILS=請以國際電話號碼格式輸入,例如以 +886 開頭的台灣手機號碼 +886937123456。 +service.gui.SEND_SMS_NOT_SUPPORTED=您選擇的通訊協定不支援簡訊發送功能。 +service.gui.SMS=簡訊 +service.gui.SEND_VIA=轉發訊息 +service.gui.SENT=已發送 +service.gui.SERVER_CHAT_ROOMS=聊天室伺服器 +service.gui.SET_GLOBAL_STATUS=設定全域狀態 +service.gui.SET_STATUS_MESSAGE=設定狀態訊息 +service.gui.SET_SUBJECT=設定主題 +service.gui.SETTINGS=選項 +service.gui.SHARE_DESKTOP=共享桌面 +service.gui.SHARE_DESKTOP_WITH_CONTACT=共享桌面給聯絡人 +service.gui.SHARE_FULL_SCREEN=全螢幕共享 +service.gui.SHARE_REGION=局部螢幕共享 +service.gui.SHOW=顯示 +service.gui.SHOW_CONTACT_LIST_TOOL_TIP=點擊切換歷史記錄視窗及通訊錄。 +service.gui.SHOW_MORE=顯示更多... +service.gui.SHOW_OFFLINE_CONTACTS=顯示離線聯絡人 +service.gui.SIGN_IN=登入 +service.gui.SMS_SUCCESSFULLY_SENT=簡訊發送成功! +service.gui.SMS_SEND_CONNECTION_PROBLEM=必須先登入才能發送簡訊。請登入您的簡訊服務帳號。 +service.gui.SPECIFY_REASON=請輸入您這麼做的原因。 +service.gui.SPECIFY_SERVER=請補充您帳號設定的伺服器說明。 +service.gui.SOUND_OFF=關閉聲音 +service.gui.SOUND_ON=開啟聲音 +service.gui.START_SHARING=開始共享 +service.gui.STATUS=狀態 +service.gui.STATUS_CHANGED_CHAT_MESSAGE={0} 已上線 +service.gui.STATUS_CHANGE_GENERAL_ERROR=使用者 {0} 更新 {1} 伺服器狀態失敗:常見錯誤。 +service.gui.STATUS_CHANGE_NETWORK_FAILURE=使用者 {0} 更新 {1} 伺服器狀態失敗:網路錯誤。 +service.gui.STATUS_MESSAGE_INFO=請輸入您的新狀態訊息。 +service.gui.STOP_SHARING=停止共享 +service.gui.STREET=街道 +service.gui.SUBJECT=標題 +service.gui.SUMMARY=摘要 +service.gui.TELEPHONY=電話 +service.gui.TOOLS=工具 +service.gui.TRANSFER=轉接 +service.gui.TO=到: +service.gui.TRANSFER_CALL_MSG=先選擇要轉接聯絡人再點擊「轉接」。 +service.gui.TRANSFER_CALL_TITLE=轉接來電 +service.gui.TRANSFER_CALL_TO=轉接給: +service.gui.TRANSPARENCY_NOT_ENABLED=您當前的設定不支持透明化。 +service.gui.TYPE_YOUR_REQUEST=請在這裡輸入您的請求 +service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=我們無法變更本通話的視訊品質。 +service.gui.USER_IDENTIFIER=使用者ID: +service.gui.USER_EXISTS_ERROR=所選的網路已存在該使用者。請選擇其他使用者或網路。 +service.gui.USERNAME_NULL=請輸入使用者名稱和密碼。 +service.gui.WEBPAGE=開啟網頁 +service.gui.ACCOUNT_CREATION_FAILED=建立帳號失敗,原因:{0} +service.gui.UNKNOWN=未知使用者 +service.gui.UNKNOWN_STATUS=未知狀態 +service.gui.UNREGISTERED_MESSAGE=使用者 {0} 連線 {1} 伺服器失敗:您正處於離線狀態。 +service.gui.USE_PROVISIONING=使用在線配置 +service.gui.VALUE=數值 +service.gui.VIDEO_CALL=視訊通話 +service.gui.VIA=經由 +service.gui.VIEW=顯示 +service.gui.VIEW_HISTORY=檢視歷史紀錄 +service.gui.VIEW_SMILEYS=顯示表情 +service.gui.VIEW_TOOLBAR=顯示工具列 +service.gui.VIEW_SIMPLE_CHAT_THEME=簡單聊天主題皮膚 +service.gui.VOICEMAIL_NEW_URGENT_OLD_RECEIVED={0} 條新訊息 ( {1} 條緊急 ) 和 {2} 條舊訊息 +service.gui.VOICEMAIL_NEW_URGENT_RECEIVED={0} 條新訊息 ( {1} 條緊急 ) +service.gui.VOICEMAIL_NEW_OLD_RECEIVED={0} 條新訊息和 {1} 條舊訊息 +service.gui.VOICEMAIL_NEW_RECEIVED={0} 條新訊息 +service.gui.VOICEMAIL_OLD_RECEIVED={0} 條舊訊息 +service.gui.VOICEMAIL_NO_MESSAGES=沒有訊息 +service.gui.VOICEMAIL_TITLE=語音留言 +service.gui.VOICEMAIL_TOOLTIP=語音留言給: +service.gui.VOICEMAIL_TIP=點擊通話按鈕以收聽您的留言。 +service.gui.VOICEMAIL_TIP_NO_ACCOUNT=請在帳號精靈中設定可用以讀取語音信箱的網址 (URI) +service.gui.VOLUME_CONTROL_TOOL_TIP=調整音量 +service.gui.WAITING_AUTHORIZATION=正在等待授權 +service.gui.WARNING=警告 +service.gui.YES=是 +service.gui.NEW_GMAIL_HEADER=您有一封新郵件!收件箱:{0}
    +service.gui.NEW_GMAIL_MANY_HEADER=收件箱:{0}
    有 {2} 封新郵件。 +service.gui.NEW_GMAIL_FOOTER=多條未讀留言在您的收件箱
    +service.gui.NEW_GMAIL_MANY_FOOTER=有 {1} 個未讀留言在您的收件箱
    +service.gui.ACTIVATE=啟用 +service.gui.DEACTIVATE=停用 +service.gui.NEW=新增 +service.gui.ENTER_FULL_SCREEN_TOOL_TIP=進入全螢幕模式 +service.gui.EXIT_FULL_SCREEN_TOOL_TIP=退出全螢幕模式 +service.gui.HOLD_BUTTON_TOOL_TIP=啟用/停用通話等待 +service.gui.MUTE_BUTTON_TOOL_TIP=切換靜音或者按住按鈕以調整麥克風音量 +service.gui.PARK=保持 +service.gui.PARKING_SLOT=通話駐留通道: +service.gui.PARK_BUTTON_TOOL_TIP=呼叫保持 +service.gui.RECORD_BUTTON_TOOL_TIP=開啟/停止錄音 +service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=切換視訊 +service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=顯示/隱藏本地視訊 +service.gui.SHOW_HIDE_PEERS_TOOL_TIP=顯示/隱藏通話參與者列表 +service.gui.TRANSFER_BUTTON_TOOL_TIP=轉接來電 +service.gui.TRANSFER_TO=轉接給... +service.gui.SECURITY_INFO=安全訊息 +service.gui.SECURITY_WARNING=安全警告 +service.gui.SECURITY_ERROR=安全錯誤 +service.gui.SPEED=速率: +service.gui.SILENT_MEMBER=靜音成員 +service.gui.NON_SECURE_CONNECTION=無法為帳號 {0} 建立安全連線。如果您想連線到一個不安全的伺服器,請在您的帳號設定中勾選「允許不安全的連線」選項 +service.gui.MOBILE_PHONE=手機 +service.gui.VIDEO_PHONE=視訊 +service.gui.WORK_PHONE=工作 +service.gui.PHONE=電話 +service.gui.PHONES=電話 +service.gui.EDIT_NOT_SUPPORTED=此帳號不可編輯 +service.gui.SHOW_PREVIEW=(顯示預覽) +service.gui.SHOW_PREVIEW_WARNING_DESCRIPTION=您要繼續顯示此圖片?\n\n顯示圖片/視訊 可能讓您的匿名失效並且暴露您的活動狀態。 +service.gui.SHOW_PREVIEW_DIALOG_TITLE=顯示圖片/視訊預覽 + +service.gui.ZID_NAME_SET=ZRTP 識別碼名稱: +service.gui.ZID_NAME_NOT_SET=ZRTP 識別碼名稱未設定 +service.gui.ZID_NAME_BUTTON=點擊設定一個 ZRTP 識別碼名稱。 +service.gui.ZID_NAME_DIALOG=編輯 ZRTP 識別碼名稱 +service.gui.ZID_NAME_UNEXPECTED=ZRTP 識別碼不相符。
    請先比對身份驗證識別碼是否與對方一致!
    修改 ZRTP 身份驗證識別碼直至與對方一致再存檔。 + +service.gui.JANUARY=一月 +service.gui.FEBRUARY=二月 +service.gui.MARCH=三月 +service.gui.APRIL=四月 +service.gui.MAY=五月 +service.gui.JUNE=六月 +service.gui.JULY=七月 +service.gui.AUGUST=八月 +service.gui.SEPTEMBER=九月 +service.gui.OCTOBER=十月 +service.gui.NOVEMBER=十一月 +service.gui.DECEMBER=十二月 + +service.gui.callinfo.TECHNICAL_CALL_INFO=技術呼叫訊息 +service.gui.callinfo.CALL_INFORMATION=通話訊息 +service.gui.callinfo.CALL_IDENTITY=標識 +service.gui.callinfo.PEER_COUNT=參與人數 +service.gui.callinfo.IS_CONFERENCE_FOCUS=會議焦點 +service.gui.callinfo.CALL_TRANSPORT=信號呼叫傳輸 +service.gui.callinfo.CALL_DURATION=通話週期 +service.gui.callinfo.TLS_PROTOCOL=TLS 通訊協定 +service.gui.callinfo.TLS_CIPHER_SUITE=TLS 加密算法套件 +service.gui.callinfo.TLS_CERTIFICATE_CONTENT=以下是 TLS 伺服器憑證內容。 +service.gui.callinfo.VIEW_CERTIFICATE=查看憑證 +service.gui.callinfo.CODEC=編碼器/頻率 +service.gui.callinfo.NA=無 +service.gui.callinfo.VIDEO_SIZE=視訊大小 +service.gui.callinfo.AUDIO_INFO=音訊訊息 +service.gui.callinfo.VIDEO_INFO=視訊訊息 +service.gui.callinfo.LOCAL_IP=本地IP/通訊埠 +service.gui.callinfo.REMOTE_IP=遠端IP/通訊埠 +service.gui.callinfo.BANDWITH=帶寬 +service.gui.callinfo.LOSS_RATE=損失率 +service.gui.callinfo.RTT=RTT +service.gui.callinfo.JITTER=抖動 +service.gui.callinfo.MEDIA_STREAM_TRANSPORT_PROTOCOL=多媒體串流傳輸通訊協定 +service.gui.callinfo.MEDIA_STREAM_RTP=RTP +service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP +service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=密鑰交換通訊協定 +service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE 候選者拓展類型 +service.gui.callinfo.ICE_STATE=ICE 作業處理狀態 + +#enum values from IceProcessingState +service.gui.callinfo.ICE_STATE.WAITING=搜集候選者 +service.gui.callinfo.ICE_STATE.RUNNING=連通性檢查 +service.gui.callinfo.ICE_STATE.COMPLETED=已完成 +service.gui.callinfo.ICE_STATE.FAILED=失敗 + +service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=本地主機IP/通訊埠 +service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=本地自反IP/通訊埠 +service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=本地中繼IP/通訊埠 +service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=遠端主機IP/通訊埠 +service.gui.callinfo.ICE_REMOTE_REFLEXIVE_ADDRESS=遠端自反IP/通訊埠 +service.gui.callinfo.ICE_REMOTE_RELAYED_ADDRESS=遠端中繼IP/通訊埠 +service.gui.callinfo.TOTAL_HARVESTING_TIME=回收時間總計 +service.gui.callinfo.HARVESTING_TIME=回收時間 +service.gui.callinfo.HARVESTING_MS_FOR=ms (為 +service.gui.callinfo.HARVESTS= 收成) +service.gui.callinfo.DECODED_WITH_FEC=用 FEC 解碼封包 +service.gui.callinfo.DISCARDED_PERCENT=當前封包被捨棄 +service.gui.callinfo.DISCARDED_TOTAL=被捨棄封包數 +service.gui.callinfo.ADAPTIVE_JITTER_BUFFER=自適應抖動緩衝器 +service.gui.callinfo.JITTER_BUFFER_DELAY=抖動緩衝器 + +service.gui.ALWAYS_TRUST=總是信任這個憑證 +service.gui.CERT_DIALOG_TITLE=驗證憑證 +service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} 連接到 {1} 伺服器時無法驗證。

    該伺服器憑證不受信任,因而無法自動驗證。

    您確定要繼續連線?
    點擊 「檢視憑證」可取得進一步資訊。 +service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} 連接伺服器時無法驗證。

    該伺服器憑證不受信任,因而無法自動驗證。

    您確定要繼續連線?
    點擊 「檢視憑證」可取得進一步資訊。 +service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} 無法驗證客戶端 {1} 的身份。

    該客戶端的證書不受信任,因此無法自動驗證其身份。
    您確認要繼續連線?

    點擊「查看證書」獲取詳細訊息。 +service.gui.CONTINUE_ANYWAY=仍然繼續 +service.gui.CERT_INFO_CHAIN=證書鏈: +service.gui.CERT_INFO_ISSUED_TO=通用名: + +#service.gui.CERT_INFO_ are combined from Rdn names +service.gui.CERT_INFO_CN=通用名: +service.gui.CERT_INFO_O=組織: +service.gui.CERT_INFO_C=國家: +service.gui.CERT_INFO_ST=州/省: +service.gui.CERT_INFO_L=地址: +service.gui.CERT_INFO_ISSUED_BY=頒發者 +service.gui.CERT_INFO_OU=單位: +service.gui.CERT_INFO_VALIDITY=有效性 +service.gui.CERT_INFO_ISSUED_ON=簽發日: +service.gui.CERT_INFO_EXPIRES_ON=到期日: +service.gui.CERT_INFO_FINGERPRINTS=數位指紋 +service.gui.CERT_INFO_CERT_DETAILS=序號: +service.gui.CERT_INFO_SER_NUM=序號: +service.gui.CERT_INFO_VER=版本: +service.gui.CERT_INFO_SIGN_ALG=演算法簽章: +service.gui.CERT_INFO_PUB_KEY_INFO=公鑰訊息 +service.gui.CERT_INFO_ALG=演算法: +service.gui.CERT_INFO_PUB_KEY=公鑰: +service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits +service.gui.CERT_INFO_EXP=指數: +service.gui.CERT_INFO_KEY_SIZE=密鑰長度: +service.gui.CERT_INFO_SIGN=簽名: +service.gui.SHOW_CERT=顯示憑證 +service.gui.HIDE_CERT=隱藏憑證 + +service.gui.AUTO_ANSWER=自動接聽和轉接 +service.gui.AUTO_ANSWER_LABEL=自動接聽 +service.gui.AUTO_ANSWER_ALL_CALLS=所有來電 +service.gui.AUTO_ANSWER_ALERT_INFO_FIELDS=只用於來電 (那些包含 "Alert-Info" 欄位的來電設定為「自動接聽」) +service.gui.AUTO_ANSWER_CUSTOM_FIELDS=包含下列字段和數值的通話 +service.gui.AUTO_ANSWER_FIELD=字段/檔頭: +service.gui.AUTO_ANSWER_VALUE=數值: +service.gui.AUTO_ANSWER_DESCR_VLUE=始終留空 +service.gui.AUTO_ANSWER_FWD_CALLS=通話轉接 +service.gui.AUTO_ANSWER_FWD_CALLS_TO=轉接所有通話到下列號碼或網址 (URI): +service.gui.AUTO_ANSWER_VIDEO=視訊 +service.gui.AUTO_ANSWER_VIDEO_CALLS_WITH_VIDEO=用視訊接聽視訊通話 +service.gui.LOCAL_VIDEO_ERROR_TITLE=本地端視訊錯誤 +service.gui.LOCAL_VIDEO_ERROR_MESSAGE=啟用/禁用本地端視訊失敗。 + +service.gui.security.SECURE_AUDIO=加密音頻 +service.gui.security.AUDIO_NOT_SECURED=音訊未加密 +service.gui.security.SECURE_VIDEO=加密視訊 +service.gui.security.VIDEO_NOT_SECURED=視訊未加密 +service.gui.security.CALL_SECURED_TOOLTIP=通話已加密。更多詳情請點擊這裡。 +service.gui.security.CALL_NOT_SECURED_TOOLTIP=通話未加密 +service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=點擊這裡與對方核對安全密碼。 # keep the following string short - +service.gui.security.COMPARE_WITH_PARTNER_SHORT=請與參與者進行字串比對: +service.gui.security.STRING_COMPARED=字串比對成功! +service.gui.security.SAS_INFO_TOOLTIP=為了完成加密,您需要口頭讀出對方提供的一小段身份驗證文字,通過驗證後才能繼續通話。

    如果您清除了這條確認訊息,下次您仍將被要求重新驗證。 +service.gui.security.SECURITY_ALERT=嘗試啟動加密通話,即將重新連線。 + +service.gui.avatar.CHOOSE_ICON=選擇圖片 +service.gui.avatar.REMOVE_ICON=刪除這張圖片 +service.gui.avatar.CLEAR_RECENT=清除最近使用圖片: +service.gui.avatar.RECENT_ICONS=最近使用圖片: # service.gui.avatar.imagepicker +service.gui.avatar.imagepicker.CANCEL=取消 +service.gui.avatar.imagepicker.CHOOSE_FILE=選擇... +service.gui.avatar.imagepicker.CLICK=按一下,然後微笑 ^_^ +service.gui.avatar.imagepicker.IMAGE_FILES=圖片檔案 +service.gui.avatar.imagepicker.IMAGE_PICKER=圖片 +service.gui.avatar.imagepicker.IMAGE_SIZE=圖片大小 +service.gui.avatar.imagepicker.RESET=重置 +service.gui.avatar.imagepicker.SET=設定 +service.gui.avatar.imagepicker.TAKE_PHOTO=拍照 +service.gui.security.encryption.required=必須加密! +service.protocol.ICE_FAILED=無法建立連線(ICE失敗,找不到中繼器) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) +impl.protocol.sip.XCAP_ERROR_TITLE=SIP通訊錄存儲錯誤 +impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR={1} 的資源 {0} 無法讀取。 +impl.protocol.sip.XCAP_ERROR_UNAUTHORIZED={0} 用於 XCAP 的使用者名稱或密碼錯誤。 # systray +impl.systray.SET_STATUS=設定狀態 +impl.systray.FAILED_TO_OPEN_ADD_CONTACT_DIALOG=開啟「新增聯絡人」精靈失敗。 +impl.systray.POPUP_MESSAGE_HANDLER=工作列冒泡提示訊息 +impl.swingnotification.POPUP_MESSAGE_HANDLER={0} 彈出視窗 +impl.growlnotification.POPUP_MESSAGE_HANDLER=聲音提醒 +impl.galagonotification.POPUP_MESSAGE_HANDLER=freedesktop.org 桌面提醒 # New Account Dialog +impl.gui.main.account.DEFAULT_PAGE_TITLE=帳號新增精靈 +impl.gui.main.account.DEFAULT_PAGE_BODY=您可利用上述清單來選擇您想要新增帳號的網路。 +impl.gui.main.account.DUMMY_PROTOCOL_NAME=虛擬通訊協定名稱 +impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=選擇網路 # LDAP +impl.ldap.CONFIG_FORM_TITLE=LDAP 設定 +impl.ldap.GENERAL=通用 +impl.ldap.FIELDS=欄位 +impl.ldap.QUERY=查詢 +impl.ldap.QUERY_DEFAULT=自動建立 +impl.ldap.QUERY_CUSTOM=自定義查詢 +impl.ldap.QUERY_CUSTOM_HINT=使用 {0} 作為搜尋條件當中的位置標誌符號。 +impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=在搜尋條件當中自動補上通配字符。 +impl.ldap.QUERY_PHOTO_INLINE=經由其他屬性獲取圖片 +impl.ldap.EDIT=編輯 +impl.ldap.ENABLED=啟用 +impl.ldap.SERVER_NAME=伺服器名稱 +impl.ldap.SERVER_NAME_EXAMPLE=我的 LDAP 伺服器 +impl.ldap.SERVER_HOSTNAME=主機名稱 +impl.ldap.SERVER_EXIST=該伺服器名稱已存在,請重新命名。 +impl.ldap.USE_SSL=使用 SSL +impl.ldap.AUTH_NONE=沒有 +impl.ldap.AUTH_SIMPLE=簡易 +impl.ldap.SCOPE_SUB_TREE=子節點 +impl.ldap.SCOPE_ONE=一個 +impl.ldap.SAVE=存檔 +impl.ldap.CANCEL=取消 +impl.ldap.SERVER_PORT=通訊埠 +impl.ldap.AUTHENTICATION=身份驗證 +impl.ldap.USERNAME=使用者名稱 (Bind DN) +impl.ldap.PASSWORD=密碼 +impl.ldap.SEARCH_BASE=搜尋範圍 +impl.ldap.SCOPE=範圍 +impl.ldap.WRONG_CREDENTIALS=LDAP 目錄服務 {0} 驗證錯誤 (Wrong credentials) +impl.ldap.MAIL_FIELD_NAME=電子郵件欄位 +impl.ldap.MAILSUFFIX_FIELD_NAME=電子郵件後綴欄位 +impl.ldap.WORKPHONE_FIELD_NAME=工作電話欄位 +impl.ldap.MOBILEPHONE_FIELD_NAME=移動電話欄位 +impl.ldap.HOMEPHONE_FIELD_NAME=住家電話欄位 +impl.ldap.MAIL_FIELD_EXAMPLE=電子郵件 +impl.ldap.MAILSUFFIX_FIELD_EXAMPLE=@domain.org (別忘了加上 '@') +impl.ldap.WORKPHONE_FIELD_EXAMPLE=公司電話 +impl.ldap.MOBILEPHONE_FIELD_EXAMPLE=行動電話 +impl.ldap.HOMEPHONE_FIELD_EXAMPLE=住家電話 +impl.ldap.PHONE_PREFIX=國際電話碼 +impl.ldap.PHONE_PREFIX_EXAMPLE=例如 00 + +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS="{0}" 不是一個有效的 SIP 地址。 + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS="{0}" 不是一個有效的 XMPP JID。 # Address book plugin +plugin.addrbook.ADDRESS_BOOKS=通訊錄 +plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=允許搜尋 MacOS X 通訊錄 +plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK=允許搜尋 Microsoft Outlook +plugin.addrbook.DESCRIPTION=若啟用本功能,您於搜尋框輸入的文字會同時在線上和本機通訊錄進行搜尋,所有符合條件的聯絡人都能夠被找出來。 +plugin.addrbook.DEFAULT_IM_APP=以 Jitsi 作為預設的即時通訊商 (與 Outlook 整合) +plugin.addrbook.PREFIX=國際電話冠碼 +plugin.addrbook.PREFIX_EXAMPLE=例如 00 +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE=存取您的 Microsoft Outlook 聯絡人發生錯誤。 +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT={0} 目前無法訪問您的Microsoft Outlook聯絡人,因為Outlook不是您的預設電子郵件應用程式。 +plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=使用 Outlook 做為預設電子郵件軟體 # Google Contacts +impl.googlecontacts.CONFIG_FORM_TITLE=Google 聯絡人 +impl.googlecontacts.EDIT=編輯 +impl.googlecontacts.ENABLED=啟用 +impl.googlecontacts.ACCOUNT_NAME=帳號名稱 +impl.googlecontacts.SAVE=存檔 +impl.googlecontacts.CANCEL=取消 +impl.googlecontacts.USERNAME=帳號名稱 +impl.googlecontacts.PASSWORD=密碼 +impl.googlecontacts.PREFIX=電話區號 +impl.googlecontacts.WRONG_CREDENTIALS=Google 帳號 {0} 驗證錯誤 +impl.googlecontacts.OAUTH_DIALOG_TITLE=Google 通訊錄授權 +impl.googlecontacts.INSTRUCTIONS=

    點擊如下鏈接以授權 Google 通訊錄外掛訪問您的帳戶。

    點擊此鏈接後,您的瀏覽器就會開啟。請您登入指定的帳號並完成授權。在成功授權後,Google 會提供一串代碼。請複製這串代碼並粘貼到下面的文字對話框,然後點擊「保存」。

    本操作只需進行一次,往後不必反覆授權。 +impl.googlecontacts.CODE=代碼: +impl.googlecontacts.HYPERLINK_TEXT=點擊這裡以允許訪問 {0} 的授權請求 # account info +plugin.accountinfo.TITLE=帳號訊息 +plugin.accountinfo.EXTENDED=延伸訊息 +plugin.accountinfo.NOT_SUPPORTED=無法獲取帳號訊息。 +plugin.accountinfo.SELECT_ACCOUNT=請選擇一個帳號: +plugin.accountinfo.DISPLAY_NAME=顯示名稱: +plugin.accountinfo.FIRST_NAME=名字: +plugin.accountinfo.MIDDLE_NAME=字/號: +plugin.accountinfo.LAST_NAME=姓氏: +plugin.accountinfo.NICKNAME=暱稱: +plugin.accountinfo.URL=網址(URL): +plugin.accountinfo.AGE=年齡: +plugin.accountinfo.BDAY=生日: +plugin.accountinfo.BDAY_FORMAT=MMM月dd日, yyyy西元年 +plugin.accountinfo.GENDER=性別: +plugin.accountinfo.STREET=街道地址: +plugin.accountinfo.CITY=城市: +plugin.accountinfo.REGION=地區: +plugin.accountinfo.POST=郵遞區號: +plugin.accountinfo.COUNTRY=國家: +plugin.accountinfo.EMAIL=E-mail: +plugin.accountinfo.WORK_EMAIL=公司 Email: +plugin.accountinfo.PHONE=電話: +plugin.accountinfo.WORK_PHONE=公司電話: +plugin.accountinfo.MOBILE_PHONE=行動電話: +plugin.accountinfo.ORGANIZATION=組織名稱: +plugin.accountinfo.JOB_TITLE=職稱: +plugin.accountinfo.ABOUT_ME=關於我: +plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 +plugin.accountinfo.GLOBAL_ICON=使用全域圖標 +plugin.accountinfo.LOCAL_ICON=使用此圖標: # connection info +plugin.connectioninfo.TITLE=連接訊息 # contact info +plugin.contactinfo.TITLE=聯絡人詳情 +plugin.contactinfo.CONTACT_SUMMARY_DESCRIPTION=聯絡人摘要 +plugin.contactinfo.CONTACT_EXTENDED_DESCRIPTION=聯絡人備註 +plugin.contactinfo.NOT_SPECIFIED=[未指定] +plugin.contactinfo.USER_PICTURES=大頭照 +plugin.contactinfo.USER_STATUS_MESSAGE=狀態 # aimaccregwizz +plugin.aimaccregwizz.PROTOCOL_NAME=AIM +plugin.aimaccregwizz.PROTOCOL_DESCRIPTION=AIM服務通訊協定 +plugin.aimaccregwizz.USERNAME=AIM即時通暱稱: +plugin.aimaccregwizz.USERNAME_AND_PASSWORD=AIM 即時通暱稱和密碼 +plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=註冊新帳號 +plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=如果您沒有 AIM 帳號,可點擊這個按鈕註冊一個新帳號。 # branding +plugin.branding.ABOUT_WINDOW_TITLE=關於 {0} +plugin.branding.LOGO_MESSAGE=開放源碼 VoIP 以及即時通訊 +plugin.branding.ABOUT_MENU_ENTRY=關於 -# Dict protocol - -# facebookaccregwizz +plugin.busylampfield.PICKUP=接聽通話 # generalconfig +plugin.generalconfig.AUTO_START=開機或重啟時自動運行 {0} +plugin.generalconfig.CHATALERTS_ON_MESSAGE=以工作列圖標提醒來電 +plugin.generalconfig.GROUP_CHAT_MESSAGES=集中聊天訊息到同一個視窗 +plugin.generalconfig.LOG_HISTORY=保存聊天記錄 +plugin.generalconfig.SHOW_HISTORY=顯示 +plugin.generalconfig.HISTORY_SIZE=最近的聊天訊息 +plugin.generalconfig.SEND_MESSAGES_WITH=發送訊息經由: +plugin.generalconfig.BRING_WINDOW_TO_FRONT=將聊天視窗保持在最上層 +plugin.generalconfig.DEFAULT_LANGUAGE=介面語言 +plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=您的設定將在下次啟動時生效。 +plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% 已翻譯 +plugin.generalconfig.SIP_CLIENT_PORT=SIP 客戶端通訊埠 +plugin.generalconfig.SIP_CLIENT_SECURE_PORT=SIP 客戶端加密通訊埠 +plugin.generalconfig.SIP_SSL_PROTOCOLS=啟用 SSL/TLS 通訊協定 +plugin.generalconfig.ERROR_PORT_NUMBER=錯誤的通訊埠號 +plugin.generalconfig.CHECK_FOR_UPDATES=啟動時檢查更新 +plugin.generalconfig.STARTUP_CONFIG=啟動 +plugin.generalconfig.LEAVE_CHATROOM_ON_WINDOW_CLOSE=關閉視窗時退出聊天室 +plugin.generalconfig.SHOW_RECENT_MESSAGES=顯示最近的對話(依聊天記錄) +plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=撥號前刪除電話號碼中的特殊符號 +plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=轉換電話號碼中的英文字母 +plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=例如 +1-800-MYPHONE -> +1-800-6974663 +plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=搜尋聯絡人時使用所有資源 +plugin.generalconfig.OPUS_CONFIG=Opus +plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=採樣率: +plugin.generalconfig.OPUS_BITRATE=編碼器平均位元傳輸率(kbps): +plugin.generalconfig.OPUS_USE_DTX=使用 DTX: +plugin.generalconfig.OPUS_USE_FEC=使用 Inband FEC: +plugin.generalconfig.OPUS_COMPLEXITY=編碼器複雜度: +plugin.generalconfig.OPUS_MIN_EXPECTED_PACKET_LOSS=最低預期丟包率(%): +plugin.generalconfig.SILK_CONFIG=Silk +plugin.generalconfig.SILK_USE_FEC=使用 Inband FEC: +plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=始終假設丟包: +plugin.generalconfig.SILK_SAT=語音活性閾值(0-1): +plugin.generalconfig.SILK_ADVERTISE_FEC=SDP 支援的 FEC 宣告: +plugin.generalconfig.RESTORE=恢復預設值 # gibberish accregwizz +plugin.gibberishaccregwizz.PROTOCOL_NAME=胡言亂語 +plugin.gibberishaccregwizz.PROTOCOL_DESCRIPTION=Jitsi 測試通訊協定 +plugin.gibberishaccregwizz.USERNAME=使用者ID: +plugin.gibberishaccregwizz.USERNAME_AND_PASSWORD=ID 設定 # icqaccregwizz +plugin.icqaccregwizz.PROTOCOL_NAME=ICQ +plugin.icqaccregwizz.PROTOCOL_DESCRIPTION=AOL ICQ 服務通訊協定 +plugin.icqaccregwizz.USERNAME=ICQ 號碼: +plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=如果您沒有 ICQ 帳號,可點擊這個按鈕註冊一個新帳號。 +plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=建立新帳號 # irc accregwizz +plugin.ircaccregwizz.PROTOCOL_NAME=IRC +plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=IRC 通訊協定 +plugin.ircaccregwizz.USERNAME_AND_PASSWORD=IRC 使用者名稱 (UIN) 和密碼 +plugin.ircaccregwizz.USERNAME=暱稱 +plugin.ircaccregwizz.EXAMPLE_USERNAME=例如:ircuser +plugin.ircaccregwizz.INFO_PASSWORD=大部分 IRC 伺服器不需要密碼。 +plugin.ircaccregwizz.AUTO_NICK_CHANGE=當該暱稱已被佔用時,自動選擇暱稱。 +plugin.ircaccregwizz.USE_DEFAULT_PORT=使用預設通訊埠 +plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=我的暱稱不需要身份校驗 +plugin.ircaccregwizz.HOST=主機名稱: +plugin.ircaccregwizz.IRC_SERVER=伺服器 +plugin.ircaccregwizz.EXAMPLE_SERVER=例如:chat.freenode.net +plugin.ircaccregwizz.USE_SECURE_CONNECTION=使用安全連接 +plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=啟用聯絡人在線狀態 +plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=啟用聊天室在線狀態 +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=SASL 身份驗證 +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=啟用 SASL 身份驗證 +plugin.ircaccregwizz.SASL_USERNAME=使用者名稱 +plugin.ircaccregwizz.SASL_AUTHZ_ROLE=角色 +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=以上的 IRC 密碼用於 SASL 身份驗證 +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=總是使用代理進行DNS解析 # jabber accregwizz - -# mailbox - -# msn accregwizz +plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP +plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPP 通訊協定 +plugin.jabberaccregwizz.USERNAME=XMPP 使用者名稱 +plugin.jabberaccregwizz.PASSWORD_CONFIRM=確認密碼 +plugin.jabberaccregwizz.CSERVER=伺服器 +plugin.jabberaccregwizz.SERVER=連接伺服器 +plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=允許保持連線 +plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS=有新訊息時經由 Gmail 提醒 +plugin.jabberaccregwizz.ENABLE_GOOGLE_CONTACTS_SOURCE=允許搜尋 Google 聯絡人 +plugin.jabberaccregwizz.NEW_ACCOUNT_TITLE=註冊新的 XMPP 帳號 +plugin.jabberaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=建立新的 XMPP 帳號 +plugin.jabberaccregwizz.CHOOSE_SERVER_TITLE=XMPP 新帳號伺服器選擇器 +plugin.jabberaccregwizz.CHOOSE_SERVER_TEXT=從以下列表選擇要建立帳號的 XMPP 伺服器 +plugin.jabberaccregwizz.CHOOSE=選擇 +plugin.jabberaccregwizz.SERVER_COLUMN=伺服器 +plugin.jabberaccregwizz.COMMENT_COLUMN=評論 +plugin.jabberaccregwizz.RESOURCE=資源 +plugin.jabberaccregwizz.AUTORESOURCE=自動生成資源名稱 +plugin.jabberaccregwizz.PRIORITY=優先等級 +plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=不認識的 XMPP 錯誤 ({0}):請確認伺服器地址是否正確。 +plugin.jabberaccregwizz.NOT_SAME_PASSWORD=密碼不相符。 +plugin.jabberaccregwizz.USE_ICE=使用 ICE +plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=自動檢測 STUN/TURN 伺服器 +plugin.jabberaccregwizz.SUPPORT_TURN=支援 TURN +plugin.jabberaccregwizz.TURN_USERNAME=TURN 使用者名稱 +plugin.jabberaccregwizz.IP_ADDRESS=IP 地址 +plugin.jabberaccregwizz.ADD_STUN_SERVER=新增 STUN 伺服器 +plugin.jabberaccregwizz.EDIT_STUN_SERVER=編輯 STUN 伺服器 +plugin.jabberaccregwizz.ADDITIONAL_STUN_SERVERS=更多 STUN 伺服器 +plugin.jabberaccregwizz.NO_STUN_ADDRESS=請填寫合法的 STUN 伺服器地址再進行下一步。 +plugin.jabberaccregwizz.NO_STUN_USERNAME=請填寫合法的 STUN 伺服器使用者名稱再進行下一步。 +plugin.jabberaccregwizz.STUN_ALREADY_EXIST=該 STUN 伺服器已存在 +plugin.jabberaccregwizz.USE_DEFAULT_STUN_SERVER=若是沒有可用的 STUN 伺服器,則使用 {0} 作為預設的 STUN 伺服器。 +plugin.jabberaccregwizz.USE_JINGLE_NODES=使用 Jingle Nodes +plugin.jabberaccregwizz.AUTO_DISCOVER_JN=自動檢測 Jingle Nodes 中繼 +plugin.jabberaccregwizz.RELAY_SUPPORT=支援中繼 (relay) +plugin.jabberaccregwizz.ADD_JINGLE_NODE=新增 Jingle Node +plugin.jabberaccregwizz.EDIT_JINGLE_NODE=編輯 JINGLE NODE +plugin.jabberaccregwizz.JID_ADDRESS=JID 地址 +plugin.jabberaccregwizz.ADDITIONAL_JINGLE_NODES=更多 JINGLE NODES +plugin.jabberaccregwizz.USE_UPNP=啟用 UPnP +plugin.jabberaccregwizz.EXISTING_ACCOUNT=已新增的 XMPP 帳號 +plugin.jabberaccregwizz.DOMAIN_BYPASS_CAPS=將使用 GTalk 通話域 +plugin.jabberaccregwizz.TELEPHONY_DOMAIN=語音通話域 +plugin.jabberaccregwizz.ALLOW_NON_SECURE=允許非安全連線 +plugin.jabberaccregwizz.DISABLE_CARBON=禁止訊息複製 +plugin.jabberaccregwizz.DTMF_AUTO=自動:自動選擇 RTP 或 Inband +plugin.jabberaccregwizz.SERVER_OPTIONS=伺服器選項 +plugin.jabberaccregwizz.CHANGE_PASSWORD=更改帳號密碼 +plugin.jabberaccregwizz.PORT_FIELD_INVALID=請填入一個可用的通訊埠號碼,然後進行下一步。 +plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=變更密碼前,必須先登入該帳號。 +plugin.jabberaccregwizz.TLS_REQUIRED=該連線未使用 TLS,不會嘗試變更密碼。 +plugin.jabberaccregwizz.PASSWORD_CHANGED=密碼變更成功 +plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=您的 XMPP 伺服器不支援密碼變更。 +plugin.jabberaccregwizz.PASSWORD_NOT_STORED=密碼在伺服器上已變更,但是本地設定沒有更新。 +plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=請同時在兩個輸入框中輸入新密碼: +plugin.jabberaccregwizz.OVERRIDE_ENCODINGS=重載全域編碼設定 +plugin.jabberaccregwizz.ENCODINGS=編碼 +plugin.jabberaccregwizz.AUDIO=音訊 +plugin.jabberaccregwizz.VIDEO=視訊 +plugin.jabberaccregwizz.RESET=重置 +plugin.jabberaccregwizz.RESET_DESCRIPTION=重置全域設定 +plugin.jabberaccregwizz.DISABLE_JINGLE=禁用 Jingle (XMPP 音訊和視訊呼叫) # plugin manager +plugin.pluginmanager.INSTALL=安裝 +plugin.pluginmanager.UNINSTALL=解除安裝 +plugin.pluginmanager.PLUGINS=外掛 +plugin.pluginmanager.URL=網址 +plugin.pluginmanager.CHOOSE_FILE=選取檔案 +plugin.pluginmanager.SHOW_SYSTEM_BUNDLES=顯示系統外掛 +plugin.pluginmanager.SYSTEM=系統 +plugin.pluginmanager.NEW=新建 # simple accregwizz +plugin.simpleaccregwizz.LOGIN_USERNAME=使用者名稱 +plugin.simpleaccregwizz.INITIAL_ACCOUNT_REGISTRATION=只需點擊一次就能設定所有您偏好的通訊協定。 +plugin.simpleaccregwizz.SIGNUP=還沒註冊帳號? +plugin.simpleaccregwizz.SPECIAL_SIGNUP=還沒註冊帳號? - 點擊這裡獲取使用者名稱 # sipaccregwizz +plugin.sipaccregwizz.PROTOCOL_NAME=SIP +plugin.sipaccregwizz.PROTOCOL_DESCRIPTION=SIP 通訊協定 +plugin.sipaccregwizz.USERNAME=SIP ID +plugin.sipaccregwizz.USERNAME_AND_PASSWORD=帳號和密碼 +plugin.sipaccregwizz.CLIENT_CERTIFICATE=客戶 TLS 憑證 +plugin.sipaccregwizz.REGISTRAR=註冊 +plugin.sipaccregwizz.SERVER_PORT=伺服器通訊埠 +plugin.sipaccregwizz.PROXY=代理伺服器 +plugin.sipaccregwizz.PROXY_PORT=代理通訊埠 +plugin.sipaccregwizz.PREFERRED_TRANSPORT=首選傳輸方式 +plugin.sipaccregwizz.PROXY_OPTIONS=代理選項 +plugin.sipaccregwizz.PROXY_AUTO=自動設定代理伺服器 +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=在 HA 的情況下跳過代理安全檢查(請僅在需要時使用) +plugin.sipaccregwizz.ENABLE_PRESENCE=允許出席 (簡易) +plugin.sipaccregwizz.FORCE_P2P_PRESENCE=強制使用 P2P 出席模式 +plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=離線聯絡人拉取間隔 (單位:秒) +plugin.sipaccregwizz.SUBSCRIPTION_EXPIRATION=預設訂閱周期 (單位:秒) +plugin.sipaccregwizz.PRESENCE_OPTIONS=出席選項 +plugin.sipaccregwizz.KEEP_ALIVE=保持連線 +plugin.sipaccregwizz.KEEP_ALIVE_METHOD=保持連線方式 +plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=保持連接自動觸發間隔時間 +plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=1 到 3600 秒 +plugin.sipaccregwizz.DTMF_MINIMAL_TONE_DURATION=最小 RTP DTMF 校正周期(ms) +plugin.sipaccregwizz.DTMF_MINIMAL_TONE_DURATION_INFO=預設 RTP DTMF 周期是 70ms +plugin.sipaccregwizz.DTMF=DTMF +plugin.sipaccregwizz.DTMF_METHOD=DTMF 方式 +plugin.sipaccregwizz.DTMF_AUTO=自動:從 RTP 和 Inband (無SIP訊息) 自動選擇 +plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) +plugin.sipaccregwizz.DTMF_SIP_INFO=SIP 訊息 +plugin.sipaccregwizz.DTMF_INBAND=Inband +plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=啟用支援加密通話 +plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=表示支援 ZRTP 的信號通訊協定 +plugin.sipaccregwizz.AUTH_NAME=授權名稱 +plugin.sipaccregwizz.DISPLAY_NAME=顯示名稱 +plugin.sipaccregwizz.EXISTING_ACCOUNT=已新增的 SIP 帳號 +plugin.sipaccregwizz.CREATE_ACCOUNT=建立免費的 SIP 帳號 +plugin.sipaccregwizz.CREATE_ACCOUNT_TITLE=建立帳號 +plugin.sipaccregwizz.XCAP_OPTIONS=通訊錄選項 +plugin.sipaccregwizz.CLIST_TYPE=類型 +plugin.sipaccregwizz.XCAP_USE_SIP_CREDENTIALS=使用 SIP 認證 +plugin.sipaccregwizz.XCAP_USER=使用者 +plugin.sipaccregwizz.XCAP_PASSWORD=密碼 +plugin.sipaccregwizz.XCAP_SERVER_URI=伺服器網址 (URI) 或 IP 地址 +plugin.sipaccregwizz.VOICEMAIL=語音信箱 +plugin.sipaccregwizz.MWI=留言等待 (MWI) +plugin.sipaccregwizz.VOICEMAIL_URI=語音信箱訂閱網址 (URI) +plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=語音信箱查閱網址 (URI) +plugin.sipaccregwizz.NOT_SAME_PASSWORD=您的密碼不相符。 +plugin.sipaccregwizz.NO_CERTIFICATE=(使用一般身份驗證) +plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP 標示 +#used from SecurityPanel +plugin.sipaccregwizz.SAVP_OPTION_0=關閉 (只用 RTP/AVP) +plugin.sipaccregwizz.SAVP_OPTION_1=強制 (只用 RTP/SAVP) +plugin.sipaccregwizz.SAVP_OPTION_2=可選 (先用 RTP/SAVP,然後才用 RTP/AVP) +plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=選擇啟用加密通訊協定和它們的優先順序 (頂端通訊協定優先): +plugin.sipaccregwizz.CIPHER_SUITES=啟用加密套件: +plugin.sipaccregwizz.SECURITY_WARNING=

    {0} 會自動嘗試加密您的所有 ZRTP 通話,同時您會聽到和看到一個安全連線已就緒的提示。如果您已了解您正在做什麼,您僅需改變如下進階設定
    +plugin.sipaccregwizz.SHOW_ADVANCED=進階加密設定 +plugin.sipaccregwizz.ZRTP_OPTION=ZRTP 選項 +plugin.sipaccregwizz.SDES_OPTION=SDes 選項 # skin manager - -# ssh accregwizz +plugin.skinmanager.SKINS=佈景主題 +plugin.skinmanager.DEFAULT_SKIN=預設佈景主題 +plugin.skinmanager.ADD_NEW_SKIN=新增佈景主題 +plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=預設的佈景主題 # status update +plugin.autoaway.AUTO_STATUS=自動切換到離開狀態 +plugin.autoaway.ENABLE_CHANGE_STATUS=離開時更改狀態 +plugin.autoaway.AWAY_MINUTES=閒置幾分鐘自動切換到離開狀態: # updatechecker +plugin.updatechecker.DIALOG_TITLE=安裝系統更新 +plugin.updatechecker.DIALOG_MESSAGE=有更新的 {0} 版本可以下載。 +plugin.updatechecker.DIALOG_MESSAGE_2=
    {0} ({1}):
    +plugin.updatechecker.BUTTON_DOWNLOAD=下載 +plugin.updatechecker.BUTTON_CLOSE=關閉 +plugin.updatechecker.BUTTON_INSTALL=安裝 +plugin.updatechecker.UPDATE_MENU_ENTRY=檢查更新 +plugin.updatechecker.DIALOG_WARN=安裝更新前需要登出 {0} 帳號。所有通話將臨時中斷。您需要繼續安裝更新嗎? +plugin.updatechecker.DIALOG_NOUPDATE=您的版本已經是最新的。 +plugin.updatechecker.DIALOG_NOUPDATE_TITLE=沒有更新的版本 +plugin.updatechecker.DIALOG_MISSING_UPDATE=找不到更新管理器。 # usersearch +plugin.usersearch.USER_SEARCH=使用者搜尋 # whiteboard - -# yahoo accregwizz - -# zero accregwizz +plugin.whiteboard.TITLE=白板 [Beta] +plugin.whiteboard.MENU_ITEM=白板 +plugin.whiteboard.NOT_SUPPORTED=該聯絡人不支援白板 +plugin.whiteboard.DRAW=繪圖 +plugin.whiteboard.OPEN=開啟 +plugin.whiteboard.PEN=畫筆 +plugin.whiteboard.SELECT=選取 +plugin.whiteboard.LINE=線條 +plugin.whiteboard.RECTANGLE=矩形 +plugin.whiteboard.FILLED_RECTANGLE=實心矩形 +plugin.whiteboard.TEXT=文字 +plugin.whiteboard.IMAGE=圖片 +plugin.whiteboard.POLYGON=多邊形 +plugin.whiteboard.FILLEDPOLYGON=實心多邊形 +plugin.whiteboard.POLYLINE=折線 +plugin.whiteboard.CIRCLE=圓形 +plugin.whiteboard.FILLED_CIRCLE=實心圓形 +plugin.whiteboard.COLOR=顏色 +plugin.whiteboard.MODIFICATION=修改 +plugin.whiteboard.THICKNESS=粗細: +plugin.whiteboard.GRID=格線 +plugin.whiteboard.DESELECT=取消選取 +plugin.whiteboard.DELETE=刪除 +plugin.whiteboard.PROPERTIES=屬性 # gtalk accregwizz +plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk +plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=GOOGLE TALK 通訊協定 +plugin.googletalkaccregwizz.USERNAME=Google Talk 使用者名稱 +plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=如果您沒有 Google Talk 帳號,可點擊這個按鈕註冊一個新帳號。 +plugin.googletalkaccregwizz.NEW_ACCOUNT_TITLE=Google Talk 帳號註冊 # iptel accregwizz - -# sip2sip accregwizz +plugin.iptelaccregwizz.PROTOCOL_NAME=iptel.org +plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org,IP 電訊平台 +plugin.iptelaccregwizz.USERNAME=使用者名稱 +plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=訂閱 iptel.org # ippi accregwizz +plugin.sip2sipaccregwizz.USERNAME=使用者名稱 +plugin.sip2sipaccregwizz.RETYPE_PASSWORD=再次輸入密碼 +plugin.sip2sipaccregwizz.EMAIL=Email 地址 +plugin.sip2sipaccregwizz.EMAIL_NOTE=這個 email 地址將被用來發送語音留言、
    未接來電提醒和重置密碼服務。 +plugin.ippiaccregwizz.PROTOCOL_NAME=ippi +plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=網路電話 (VoIP) 與即時通訊 +plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=查閱本服務說明:
    http://ippi.fr +plugin.ippiaccregwizz.INFO_NOTE=查閱本服務說明:http://ippi.fr +plugin.ippiaccregwizz.EXISTING_ACCOUNT=已建立的 ippi 帳號 +plugin.ippiaccregwizz.CREATE_ACCOUNT=免費建立 ippi 帳號 # key binding chooser +#in new ChatWindow() -> manipulated +plugin.keybindings.CHAT_CLOSE=關閉聊天視窗 +plugin.keybindings.CHAT_COPY=複製 +plugin.keybindings.CHAT_CUT=剪下 +plugin.keybindings.CHAT_NEXT_TAB=下一個標籤 +plugin.keybindings.CHAT_OPEN_HISTORY=開啟歷史記錄 +plugin.keybindings.CHAT_OPEN_SMILIES=開啟表情 +plugin.keybindings.CHAT_PASTE=貼上 +plugin.keybindings.CHAT_PREVIOUS_TAB=上一個標籤 +plugin.keybindings.MAIN_NEXT_TAB=下一個標籤 +plugin.keybindings.MAIN_PREVIOUS_TAB=上一個標籤 +plugin.keybindings.MAIN_RENAME=重新命名聯絡人 +plugin.keybindings.OPEN_HISTORY=顯示聊天記錄 +plugin.keybindings.OPEN_SMILIES=顯示表情 +plugin.keybindings.globalchooser.ANSWER_CALL=通話應答 +plugin.keybindings.globalchooser.HANGUP_CALL=通話掛斷 +plugin.keybindings.globalchooser.ANSWER_HANGUP_CALL=通話應答/掛斷 +plugin.keybindings.globalchooser.SHOW_CONTACTLIST=顯示通訊錄 +plugin.keybindings.globalchooser.MUTE_CALLS=通話靜音 +plugin.keybindings.globalchooser.SHORTCUT_NAME=快捷鍵功能 +plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=主要快捷鍵 +plugin.keybindings.globalchooser.SHORTCUT_SECOND=次要快捷鍵 +plugin.keybindings.globalchooser.PRESS_BTN=點擊設定快捷鍵 +plugin.keybindings.globalchooser.PUSH_TO_TALK=按鍵通話 (Push to Talk) +plugin.keybindings.globalchooser.ENABLE_SPECIAL=啟用特殊鍵偵測 +plugin.keybindings.PLUGIN_NAME=快捷鍵 +#Enum KeybindingSet.Category +plugin.keybindings.CHAT=聊天 +plugin.keybindings.MAIN=主要 +plugin.keybindings.GLOBAL=全域快捷鍵 # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=啟用 +plugin.notificationconfig.DESCRIPTION=描述 +plugin.notificationconfig.TURN_ON_ALL=全部啟用 +plugin.notificationconfig.TURN_OFF_ALL=全部禁用 +plugin.notificationconfig.ACTIONS=動作 +plugin.notificationconfig.QUICK_CONTROLS=快捷控制 +plugin.notificationconfig.RESTORE=還原預設值 +plugin.notificationconfig.PLAY_SOUND=播放聲音: +plugin.notificationconfig.EXEC_PROG=執行程式: +plugin.notificationconfig.DISPLAY_POPUP=在彈出式視窗中顯示訊息 +plugin.notificationconfig.POPUP_NOTIF_HANDLER=彈出提醒類型 +plugin.notificationconfig.SOUND_FILE=音效檔案: +plugin.notificationconfig.PROGRAM_FILE=程式檔案: +plugin.notificationconfig.BROWSE_SOUND=選擇音效檔 +plugin.notificationconfig.BROWSE_PROGRAM=選擇程式 +plugin.notificationconfig.tableheader.ENABLE=啟用或禁用這個特性 +plugin.notificationconfig.tableheader.EXECUTE=執行程式 +plugin.notificationconfig.tableheader.POPUP=顯示訊息框 +plugin.notificationconfig.tableheader.SOUND=用提醒裝置播放提示音 +plugin.notificationconfig.tableheader.PLAYBACK_SOUND=用回放裝置播放提示音 +plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=用電腦喇叭播放聲音 +plugin.notificationconfig.tableheader.DESCRIPTION=事件描述 +#NotificationsTable constants +plugin.notificationconfig.event.IncomingCall=來電通知 +plugin.notificationconfig.event.SecurityMessage=安全訊息 +plugin.notificationconfig.event.IncomingFile=要傳進來的檔案 +plugin.notificationconfig.event.LogFilesArchived=紀錄檔已封存 +plugin.notificationconfig.event.CallSecurityError=通話加密發生錯誤 +plugin.notificationconfig.event.NetworkNotifications=網路通知 +plugin.notificationconfig.event.Dialing=正在撥號 +plugin.notificationconfig.event.ProactiveNotification=主動輸入通知 +plugin.notificationconfig.event.CallSecurityOn=啟動加密通話 +plugin.notificationconfig.event.IncomingMessage=收到訊息 +plugin.notificationconfig.event.OutgoingCall=通話撥出 +plugin.notificationconfig.event.BusyCall=通話忙線中 +plugin.notificationconfig.event.CallSaved=通話保留 +plugin.notificationconfig.event.HangUp=掛斷 +plugin.notificationconfig.event.DNSSEC_NOTIFICATION=DNSSEC 警告 +plugin.notificationconfig.event.DTMFTone.A=DTMF 音調 A +plugin.notificationconfig.event.DTMFTone.B=DTMF 音調 B +plugin.notificationconfig.event.DTMFTone.C=DTMF 音調 C +plugin.notificationconfig.event.DTMFTone.D=DTMF 音調 D +plugin.notificationconfig.event.DTMFTone.0=DTMF 音調 0 +plugin.notificationconfig.event.DTMFTone.1=DTMF 音調 1 +plugin.notificationconfig.event.DTMFTone.2=DTMF 音調 2 +plugin.notificationconfig.event.DTMFTone.3=DTMF 音調 3 +plugin.notificationconfig.event.DTMFTone.4=DTMF 音調 4 +plugin.notificationconfig.event.DTMFTone.5=DTMF 音調 5 +plugin.notificationconfig.event.DTMFTone.6=DTMF 音調 6 +plugin.notificationconfig.event.DTMFTone.7=DTMF 音調 7 +plugin.notificationconfig.event.DTMFTone.8=DTMF 音調 8 +plugin.notificationconfig.event.DTMFTone.9=DTMF 音調 9 +plugin.notificationconfig.event.DTMFTone.*=DTMF 音調 * +plugin.notificationconfig.event.DTMFTone.#=DTMF 音調 # +plugin.notificationconfig.event.DeviceConfigurationChanged=裝置設定已變更 +plugin.notificationconfig.event.NewSelectedDevice=新選取的裝置 # ZRTP Securing +impl.media.security.WARNING_NO_RS_MATCH=沒有可用的共享密鑰。
    建議採用 SAS 驗證。 +impl.media.security.WARNING_NO_EXPECTED_RS_MATCH=找不到共享密鑰。
    需要進行 SAS 驗證。
    如果 SAS 密碼不相符,請掛斷重撥。 +impl.media.security.SEVERE_GENERIC_MSG=檢測到嚴重的服務安全問題。
    您的通話不安全。
    錯誤代碼:{0} +impl.media.security.ZRTP_GENERIC_MSG=檢測到嚴重的 ZRTP 問題。
    您的通話並未加密。
    錯誤代碼: {0} +impl.media.security.INTERNAL_PROTOCOL_ERROR=發生了通訊協定內部錯誤。
    您的通話不安全。
    錯誤代碼:{0} +impl.media.security.CHECKSUM_MISMATCH=內部 ZRTP 封包校驗失敗。
    如果您看到這條訊息,可能是遭到了拒絕服務(DoS)攻擊! +impl.media.security.RETRY_RATE_EXCEEDED=嘗試安全協商次數過多。這很可能是對方的網路連線有問題。
    您的通話不安全。
    錯誤代碼:{0} +impl.media.security.DATA_SEND_FAILED=加密資料傳送失敗。資料連線中斷或是對方已斷線。
    您的通話不安全
    錯誤代碼:{0} +impl.media.security.SECURITY_OFF=加密通話已停用 +impl.media.security.SECURITY_ON=加密通話已啟用 # ZRTP Configuration +impl.media.security.zrtp.CONFIG=ZRTP 設定 +impl.media.security.zrtp.TITLE=通話 +impl.media.security.zrtp.PUB_KEYS=公開金鑰 +impl.media.security.zrtp.HASHES=雜湊 +impl.media.security.zrtp.SYM_CIPHERS=對稱加密演算法 +impl.media.security.zrtp.SAS_TYPES=SAS 類型 +impl.media.security.zrtp.SRTP_LENGTHS=SRTP 身份驗證長度 +impl.media.security.zrtp.STANDARD=標準 +impl.media.security.zrtp.MANDATORY=強制 +impl.media.security.zrtp.TRUSTED=可信任的 MitM +impl.media.security.zrtp.SASSIGNATURE=SAS 簽名進行中 +impl.media.security.zrtp.DESCRIPTION={0} 會自動嘗試加密您的所有通話,在此同時您會聽到和看到一條安全連線已就緒的提示。按下此按鈕表示您允許 ZRTP 專家微調 {0} 的 ZRTP 協商行為,您無需做任何調整即可獲得安全呼叫。您應僅在已詳細了解 ZRTP 和一般的加密工作原理後再變更此設定。 +impl.media.security.zrtp.ZRTP_NINJA=ZRTP 隱身 # Profiler4J - - - +plugin.profiler.PLUGIN_NAME=Profiler4j + +impl.media.configform.AUDIO=音訊系統: +impl.media.configform.AUDIO_IN=音訊輸入: +impl.media.configform.AUDIO_NOTIFY=通知: +impl.media.configform.AUDIO_OUT=音訊輸出: +impl.media.configform.AUTOMATICGAINCONTROL=自動取得控制權 +impl.media.configform.DENOISE=開啟降噪功能 +impl.media.configform.DEVICES=裝置 +impl.media.configform.DOWN=下移 +impl.media.configform.ECHOCANCEL=開啟回音消除功能 +impl.media.configform.ENCODINGS=編碼 +impl.media.configform.NO_AVAILABLE_AUDIO_DEVICE=無可用的音訊裝置。請連接一個。 +impl.media.configform.NO_DEVICE=<沒有裝置> +impl.media.configform.NO_PREVIEW=預覽 +impl.media.configform.UP=上移 +impl.media.configform.VIDEO=攝影機: +impl.media.configform.VIDEO_MORE_SETTINGS=更多設定 +impl.media.configform.VIDEO_RESOLUTION=視訊解析度 +impl.media.configform.VIDEO_FRAME_RATE=自定義影格率(每秒) +impl.media.configform.VIDEO_PACKETS_POLICY=RTP 步進門檻 (kB/s) +impl.media.configform.VIDEO_BITRATE=視訊位元傳輸率(kb/s) +impl.media.configform.VIDEO_RESET=重置為預設值 +impl.media.configform.AUDIO_DEVICE_CONNECTED=已連線的設備: +impl.media.configform.AUDIO_DEVICE_DISCONNECTED=斷線的設備: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_IN=新選擇的音訊輸入裝置: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_OUT=新選擇的音訊輸出裝置: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS=新選擇的提醒裝置: +impl.media.configform.VIDEO_DEVICE_SELECTED=新選擇的視訊裝置: +impl.media.configform.AUDIO_DEVICE_CONFIG_MANAGMENT_CLICK=點此進行裝置管理 + +impl.neomedia.configform.AUDIO=音訊 +impl.neomedia.configform.VIDEO=視訊 + +impl.neomedia.configform.H264=H.264 +impl.neomedia.configform.H264.defaultIntraRefresh=周期性內部更新 +impl.neomedia.configform.H264.defaultProfile=預設編碼設定: +#in JNIEncoder +impl.neomedia.configform.H264.defaultProfile.baseline=基準線 +impl.neomedia.configform.H264.defaultProfile.high=高 +impl.neomedia.configform.H264.defaultProfile.main=主要 +impl.neomedia.configform.H264.keyint=關鍵影格之間的最大間隔 +impl.neomedia.configform.H264.preferredKeyFrameRequester=以偏好方式請求關鍵影格: +impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTCP +impl.neomedia.configform.H264.preferredKeyFrameRequester.signaling=發送信號 +impl.neomedia.configform.H264.preset=預設編碼器 # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. +plugin.callrecordingconfig.CALL_RECORDING_CONFIG=通話錄音 +plugin.callrecordingconfig.SAVE_CALLS=儲存錄音檔至: +plugin.callrecordingconfig.SAVE_CALL=儲存錄音檔至... +plugin.callrecordingconfig.CHOOSE_DIR=選擇資料夾... +plugin.callrecordingconfig.SUPPORTED_FORMATS=錄音檔格式: +plugin.callrecordingconfig.CALL_SAVED=錄音檔儲存成功 +plugin.callrecordingconfig.CALL_SAVED_TO={0} # Security configuration form title +plugin.securityconfig.TITLE=安全 +plugin.securityconfig.masterpassword.TITLE=密碼 +plugin.securityconfig.masterpassword.CHANGE_MASTER_PASSWORD=修改主控密碼... +plugin.securityconfig.masterpassword.USE_MASTER_PASSWORD=使用主控密碼 +plugin.securityconfig.masterpassword.SAVED_PASSWORDS=已儲存的密碼... +plugin.securityconfig.masterpassword.INFO_TEXT=主控密碼是用來保護您儲存的帳號密碼。請務必牢記它。 +plugin.securityconfig.masterpassword.CURRENT_PASSWORD=目前密碼: +plugin.securityconfig.masterpassword.ENTER_PASSWORD=輸入新密碼: +plugin.securityconfig.masterpassword.REENTER_PASSWORD=再輸入一次新密碼: +plugin.securityconfig.masterpassword.MP_TITLE=主控密碼 +plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=您輸入的主控密碼錯誤。請重試。 +plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=主控密碼不正確! +plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=密碼變更失敗 +plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS=已成功變更密碼 +plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS_MSG=已成功變更主控密碼。 +plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE_MSG=無法用您提供的主控密碼解開加密的密碼。\n已儲存的密碼可能已被改動。 +plugin.securityconfig.masterpassword.MP_REMOVE_FAILURE=密碼刪除失敗 +plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS=已成功刪除密碼 +plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS_MSG=您已成功刪除主控密碼。 +plugin.securityconfig.masterpassword.COL_TYPE=類型 +plugin.securityconfig.masterpassword.COL_NAME=名稱 +plugin.securityconfig.masterpassword.COL_PASSWORD=密碼 +plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(未知) +plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(無法解密) +plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=儲存的密碼 +plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=全部刪除 +plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=您確定要刪除所有密碼嗎? +plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=刪除所有密碼 +plugin.securityconfig.masterpassword.SHOW_PASSWORDS_BUTTON=顯示密碼 +plugin.securityconfig.masterpassword.HIDE_PASSWORDS_BUTTON=隱藏密碼 +plugin.securityconfig.masterpassword.PASSWORD_QUALITY_METER=密碼強度 +plugin.securityconfig.masterpassword.MP_INPUT=請輸入主控密碼:\n\n # otr plugin +plugin.otr.menu.TITLE=密談 +plugin.otr.menu.START_OTR=開始私密對話 +plugin.otr.menu.END_OTR=結束私密對話 +plugin.otr.menu.FINISHED=您的好友已結束了與您的私密對話。您也應該這麼做。 +plugin.otr.menu.VERIFIED=您的私密對話已被確認 +plugin.otr.menu.UNVERIFIED=您的私密對話未被確認。請為您的好友進行身份驗證。 +plugin.otr.menu.LOADING_OTR=開始私密對話... +plugin.otr.menu.TIMED_OUT=啟動私密對話逾時。 +plugin.otr.menu.REFRESH_OTR=刷新私密對話 +plugin.otr.menu.AUTHENTICATE_BUDDY=好友身份驗證 +plugin.otr.menu.WHATS_THIS=這是什麼 +plugin.otr.menu.CB_AUTO=自動發起與 {0} 的私密對話 +plugin.otr.menu.CB_AUTO_ALL=自動建立與所有人的私密對話 +plugin.otr.menu.CB_ENABLE=允許私密對話 +plugin.otr.menu.CB_REQUIRE=私密對話邀請 +plugin.otr.menu.CB_RESET=重置 +plugin.otr.menu.OTR_TOOLTIP=使用 OTR 的私密對話 +plugin.otr.authbuddydialog.HELP_URI=https://jitsi.org/GSOC2009/OTR +plugin.otr.authbuddydialog.AUTHENTICATION_INFO=驗證好友能夠確保對方的真實身份。 +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD=您希望如何進行身份驗證? +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_QUESTION=以問答題進行身份驗證 +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_SECRET=以共享密碼進行身份驗證 +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_FINGERPRINT=以數位指紋進行身份驗證 +plugin.otr.authbuddydialog.AUTHENTICATION_FINGERPRINT=為了驗證數位指紋,您需要通過其他途徑聯絡您的好友,例如電話或由 GPG 驗證的電子郵件,告知對方您的數位指紋字串。如果字串相符,請在後續的對話中選擇接受此數位指紋驗證。 +plugin.otr.authbuddydialog.LOCAL_FINGERPRINT=您 ({0}) 的數位指紋:{1} +plugin.otr.authbuddydialog.REMOTE_FINGERPRINT={0} 的數位指紋:{1} +plugin.otr.authbuddydialog.AUTH_BY_QUESTION_INFO_INIT=若希望以問答題來進行身份驗證,您需要設定一組只有您和您的好友才知道答案的問題。若您的答案與對方提出的問題不相符,您的真實身份將被質疑。 +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_INIT=若希望以共享密碼進行身份驗證,您需要設定一組只有您和您的好友才知道的密碼。若您輸入的密碼與對方設定的密碼不相符,您的真實身份將被質疑。 +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_RESPOND=您的好友向您提出一個問題以確認您的真實身份。若要通過身份驗證,請輸入您的答案。 +plugin.otr.authbuddydialog.SHARED_SECRET=輸入您們的共享密碼: +plugin.otr.authbuddydialog.QUESTION_RESPOND=您的好友問您: +plugin.otr.authbuddydialog.QUESTION_INIT=在此輸入您的問題: +plugin.otr.authbuddydialog.ANSWER=在此輸入您的答案 (英文字母區分大小寫): +plugin.otr.authbuddydialog.AUTHENTICATION_FROM=來自 {0} 的身份驗證。 +plugin.otr.authbuddydialog.CANCEL=取消 +plugin.otr.authbuddydialog.HELP=求助 +plugin.otr.authbuddydialog.TITLE=好友身份驗證 +plugin.otr.authbuddydialog.AUTHENTICATE_BUDDY=驗證好友身份 +plugin.otr.authbuddydialog.I_HAVE=我已經 +plugin.otr.authbuddydialog.I_HAVE_NOT=我還沒有 +plugin.otr.authbuddydialog.VERIFY_ACTION=驗證了 {0} 的數位指紋正確性。 +plugin.otr.authbuddydialog.FINGERPRINT_CHECK=請輸入從 {0} 收到的數位指紋。 +plugin.otr.smpprogressdialog.TITLE=身份驗證進度 +plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS=身份驗證成功! +plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL=身份驗證失敗! +plugin.otr.configform.MY_PRIVATE_KEYS=我的私密金鑰 +plugin.otr.configform.KNOWN_FINGERPRINTS=已知的數位指紋 +plugin.otr.configform.CB_AUTO=自動啟動私密對話 +plugin.otr.configform.CB_ENABLE=允許私密對話 +plugin.otr.configform.CB_REQUIRE=邀請私密對話 +plugin.otr.configform.NO_KEY_PRESENT=金鑰不存在 +plugin.otr.configform.GENERATE=產生 +plugin.otr.configform.REGENERATE=重新產生 +plugin.otr.configform.FINGERPRINT=數位指紋 +plugin.otr.configform.VERIFY_FINGERPRINT=確認數位指紋 +plugin.otr.configform.FORGET_FINGERPRINT=不要記住數位指紋 +plugin.otr.configform.COLUMN_NAME_CONTACT=聯絡人 +plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=已驗證 +plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=是 +plugin.otr.configform.COLUMN_VALUE_VERIFIED_FALSE=否 +plugin.otr.activator.unverifiedsessionwarning={0} 透過來路不明的電腦與您通話。建議您對 {0} 進行身份驗證。 +plugin.otr.activator.unverifiedsessionstared=與 {0} 的未驗證的私密對話開始。 +plugin.otr.activator.sessionstared=已開始和 {0} 的私密對話 +plugin.otr.activator.sessionfinished={0} 已經結束了和您的私密對話;您也應該這樣做。 +plugin.otr.activator.sessionlost=與 {0} 的私密對話已中斷。 +plugin.otr.activator.historyon=正在記錄您與 {0} 的對話內容。您可以在此關閉聊天紀錄。 +plugin.otr.activator.historyoff=您與 {0} 的對話內容沒有記錄。您可以啟用聊天紀錄。 +plugin.otr.activator.sessionfinishederror=您的訊息 "{0}" 未送出。請結束與 {1} 的私密對話。 +plugin.otr.activator.smpaborted={0} 已經終止了身份驗證程序。 +plugin.otr.activator.smperror=在身份驗證過程中出現了一個錯誤。 +plugin.otr.activator.unencryptedmsgreceived=收到的訊息是未經加密的。 +plugin.otr.activator.unreadablemsgreceived={0} 發送給您一條無法讀取的加密訊息。 +plugin.otr.activator.requireencryption=您的訊息 "{0}" 未送出。需要啟動私密對話。 +plugin.otr.activator.unreadablemsgreply=您發送給 {0} 的加密訊息無法被讀取。請關閉與 {1} 的私密對話或刷新對話。 +plugin.otr.activator.fallbackmessage={0} 正試圖發起一個加密的私密對話。 然而您的軟體不支援私密對話。 請參閱:http://en.wikipedia.org/wiki/Off-the-Record_Messaging +plugin.otr.activator.multipleinstancesdetected=您的好友 {0} 重複登入並且建立了多組私密對話。您可以從下列清單當中選擇其中一組。 +plugin.otr.activator.msgfromanotherinstance={0} 發送給您一條被用於另一對話的訊息。若您重複登入,這條訊息會在另一對話收到。 # global proxy plugin +plugin.globalproxy.GLOBAL_PROXY_CONFIG=全域代理設定 +plugin.globalproxy.PROXY_TYPE=代理類型 +plugin.globalproxy.PROXY_ADDRESS=代理伺服器 +plugin.globalproxy.PROXY_PORT=代理通訊埠 +plugin.globalproxy.PROXY_USERNAME=代理使用者名稱 +plugin.globalproxy.PROXY_PASSWORD=代理密碼 +plugin.globalproxy.DESCRIPTION={0} 將對所有網路連接套用以上代理設定。\n目前對代理的支援尚處於試驗階段,並且只支援部分通訊協定。詳情請參閱下表: #plugin.globalproxy.PROTOCOL_SUPPORT +plugin.globalproxy.FWD_DNS=同時代理 DNS +plugin.globalproxy.FWD_DNS_NOTE=經由 Tor 的代理功能,可協助避免 DNS 洩漏您的行蹤。這項服務需要重新啟動程式。 +plugin.globalproxy.FWD_DNS_ADDR=DNS 代理地址 +plugin.globalproxy.FWD_DNS_PORT=DNS 代理通訊埠 # plugin reconnect +plugin.reconnectplugin.CONNECTION_FAILED_MSG=使用者 {0} 登入 {1} 伺服器失敗!\n請檢查您的系統設定或尋求網路管理員協助。 +plugin.reconnectplugin.NETWORK_DOWN=網路連接已中斷! #plugin chat config +plugin.chatconfig.TITLE=聊天 +plugin.chatconfig.replacement.TITLE=圖片/視訊: +plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=允許插入表情 +plugin.chatconfig.replacement.REPLACEMENT_TITLE=替換圖像和視訊 +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=啟用 +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL=禁用(顯示預覽鏈接) +plugin.chatconfig.replacement.DISABLE_REPLACEMENT=禁用 +plugin.chatconfig.replacement.CONFIGURE_REPLACEMENT=圖像和視訊替換設定選項更改 +plugin.chatconfig.replacement.REPLACEMENT_SOURCES=來源: +plugin.chatconfig.spellcheck.TITLE=拼字檢查 #provisioning plugin +plugin.provisioning.PROVISIONING=網路服務 +plugin.provisioning.ENABLE_DISABLE=允許提供網路服務 +plugin.provisioning.AUTO=自動偵測預置服務網址 (URI) +plugin.provisioning.DHCP=DHCP +plugin.provisioning.DNS=DNS +plugin.provisioning.BONJOUR=Bonjour +plugin.provisioning.MANUAL=手動指定預置服務網址 (URI) +plugin.provisioning.URI=網址 (URI) +plugin.provisioning.RESTART_WARNING=請注意:所有的變更需要在下次啟動 {0} 後才會生效! +plugin.provisioning.UUID=UUID +plugin.provisioning.COPYTOCLIPBOARD=複製 UUID 到剪貼簿 +plugin.provisioning.CLIPBOARD_FAILED=複製 UUID 到剪貼簿失敗 +plugin.provisioning.CREDENTIALS=最後存儲的預置證書 +plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=確定要刪除預置的密碼嗎? +plugin.provisioning.PROV_FAILED=預置失敗 +plugin.provisioning.PROV_FAILED_MSG={0} 預置失敗!
    請稍後再試,或聯絡管理員。 +plugin.provisioning.FORGET_PASSWORD=忘記密碼 # packet logging service +plugin.loggingutils.PACKET_LOGGING_CONFIG=記錄 +plugin.loggingutils.ENABLE_DISABLE=啟用紀錄包裹 +plugin.loggingutils.PACKET_LOGGING_RTP=RTP +plugin.loggingutils.PACKET_LOGGING_RTP_DESCRIPTION=(每5000 條紀錄儲存成一個包裹) +plugin.loggingutils.PACKET_LOGGING_ICE4J=ice4j.org +plugin.loggingutils.PACKET_LOGGING_DESCRIPTION=使用 PCAP (tcpdump/wireshark) 格式,將各種
    通訊協定的除錯紀錄包裹存放到紀錄資料夾。 +plugin.loggingutils.PACKET_LOGGING_FILE_COUNT=紀錄檔檔案數目 +plugin.loggingutils.PACKET_LOGGING_FILE_SIZE=最大的紀錄檔檔案大小 (單位:KB) +plugin.loggingutils.ARCHIVE_BUTTON=將紀錄檔封存 +plugin.loggingutils.UPLOAD_LOGS_BUTTON=將紀錄檔上傳 +plugin.loggingutils.UPLOAD_BUTTON=上傳 +plugin.loggingutils.ARCHIVE_FILECHOOSE_TITLE=選擇檔案 +plugin.loggingutils.ARCHIVE_UPREPORT_EMAIL=johnsmith@email.com +plugin.loggingutils.ARCHIVE_MESSAGE_OK=紀錄檔封存成功\n{0} +plugin.loggingutils.ARCHIVE_MESSAGE_NOTOK=紀錄檔封存錯誤 \n{0} # dns config plugin +plugin.dnsconfig.TITLE=DNS +plugin.dnsconfig.DNSSEC=安全DNS(DNSSEC) +plugin.dnsconfig.PARALLEL_DNS=DNS平行解析 +plugin.dnsconfig.border.TITLE=備用解析器 +plugin.dnsconfig.chkBackupDnsEnabled.text=允許 DNS 平行解析 +plugin.dnsconfig.lblBackupResolver.text=主機名稱 +plugin.dnsconfig.lblBackupResolverFallbackIP.text=備用IP +plugin.dnsconfig.lblBackupPort.text=通訊埠 +plugin.dnsconfig.lblRedemption.text=切換回主解析器 +plugin.dnsconfig.lblRedemption.description=在我們停用備用解析器之前,主解析器必須返回的迅速回應次數。 +plugin.dnsconfig.lblPatience.text=啟用備用解析器 +plugin.dnsconfig.lblPatience.description=啟用備用解析器之前最長等待主DNS回應時間(毫秒) +plugin.dnsconfig.dnssec.chkEnabled=啟用DNSSEC解析器 +plugin.dnsconfig.dnssec.lblDefault=預設行為 +plugin.dnsconfig.dnssec.chkAbsolute=處理所有域名為絕對值 +plugin.dnsconfig.dnssec.lblNameservers=自定義名稱伺服器 +plugin.dnsconfig.dnssec.lblNameserversHint=多個伺服器可以用逗號分隔,e.g. 149.20.64.20, 149.20.64.21 (OARC的公開DNSSEC驗證解析伺服器) +plugin.dnsconfig.dnssec.DOMAIN_NAME=域 +plugin.dnsconfig.dnssec.MODE=行為 +plugin.dnsconfig.dnssec.ENABLE_FAILED=狀態變更失敗 +plugin.dnsconfig.dnssec.ENABLE_FAILED_MSG=變更DNSSEC啟用狀態失敗。 +plugin.dnsconfig.dnssec.RESTART_WARNING=注意因啟用或禁用DNSSEC而禁用平行解析器會在下次啟動 {0} 時生效。 +net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=略過 +net.java.sip.communicator.util.dns.SecureResolveMode.SecureOnly=必需 +net.java.sip.communicator.util.dns.SecureResolveMode.SecureOrUnsigned=簽名區需求 +net.java.sip.communicator.util.dns.SecureResolveMode.WarnIfBogus=輪詢偽回複 +net.java.sip.communicator.util.dns.SecureResolveMode.WarnIfBogusOrUnsigned=輪詢未簽名的或虛假回複 +util.dns.INSECURE_ANSWER_TITLE=DNSSEC失敗 +util.dns.INSECURE_ANSWER_MESSAGE_NO_REASON=DNS對 {0} 應答是非安全的。 +util.dns.INSECURE_ANSWER_MESSAGE_REASON=DNS應答 {0} 是不安全的。\n原因: {1} +util.dns.DNSSEC_ADVANCED_OPTIONS=顯示進階選項 +util.dns.DNSSEC_ADVANCED_REASON_BOGUS=DNSSEC簽名區 {0} 返回無效數據。
    {1} +util.dns.DNSSEC_ADVANCED_REASON_UNSIGNED=為 {1} 執行的 {0} 查詢是未簽名的。 +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Accept=總是接受 +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysAccept=總是接受 +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=拒絕 +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysDeny=總是拒絕 +util.dns.DNSSEC_WARNING=
    {0} 已試圖連接位於{1}的伺服器,此域由DNSSEC提供強安全防護。 {0} 從DNS伺服器處獲取的訊息同此域DNSSEC提供的訊息不符。

    此問題一般不會發生,除非 {1} 處發生非常嚴重的錯誤。 它有力的表明您的網路連接可信度發生嚴重問題。

    如果您正在使用某些網路(例如WiFi熱點)或基於特殊原因不再信任您的互聯網服務提供商,我們強烈建議您立即停止使用並尋找一個可信的替代互聯網接入點。當您安全的接入另一個網路,此問題會自動消除。如非上述原因,請聯絡您的服務提供商並告知他們有關問題。
    #plugin spellcheck - +plugin.spellcheck.TITLE=拼寫和語法檢查 +plugin.spellcheck.MENU=顯示拼寫和語法 +plugin.spellcheck.ENABLE_SPELL_CHECK=啟用拼寫檢查 +plugin.spellcheck.dialog.FIND=查找下一個 +plugin.spellcheck.dialog.REPLACE=替換 +plugin.spellcheck.dialog.ADD=新增單詞 +plugin.spellcheck.DICT_ERROR_TITLE=切換字典錯誤 +plugin.spellcheck.DICT_ERROR=無法切換字典 +plugin.spellcheck.DICT_RETRIEVE_ERROR=字典無法被獲取自 +plugin.spellcheck.DICT_PROCESS_ERROR=本地未識別 +plugin.spellcheck.UNINSTALL_DICTIONARY=卸載 +plugin.spellcheck.DICT_ERROR_DELETE_TITLE=卸載字典時發生錯誤 +plugin.spellcheck.DICT_ERROR_DELETE=無法卸載字典 +plugin.spellcheck.SPELLCHECK=拼寫檢查 + +plugin.contactsourceconfig.CONTACT_SOURCE_TITLE=聯絡源 #Certificate configuration plugin +plugin.certconfig.TITLE=TLS設定 +plugin.certconfig.TRUSTSTORE_CONFIG=受信任的根證書源 +plugin.certconfig.JAVA_TRUSTSTORE=Java +plugin.certconfig.WINDOWS_TRUSTSTORE=Windows +plugin.certconfig.CERT_LIST_TITLE=TLS 客戶端身份驗證設定 +plugin.certconfig.CERT_LIST_DESCRIPTION=這裡的設定可以被用作帳號設定中的客戶端 TLS 證書 (亦即用 SIP 提供的身份驗證憑證替代使用者名稱和密碼驗證)。 +plugin.certconfig.ALIAS=密鑰庫中的別名稱 +plugin.certconfig.KEYSTORE_TYPE=類型 +plugin.certconfig.EDIT_ENTRY=編輯TLS客戶端證書設定 +plugin.certconfig.KEYSTORE=檔案 +plugin.certconfig.KEYSTORE_PASSWORD=密碼 +plugin.certconfig.INCOMPLETE=請為所有字段錄入值 +plugin.certconfig.SHOW_CERT_EXCEPTION=證書不可顯示({0})。 +plugin.certconfig.KEYSTORE_EXCEPTION=無法加載密鑰庫({0})。 +plugin.certconfig.FILE_TYPE_DESCRIPTION=證書存儲(PKCS#11 模式,PKCS#12檔案,Java ks 密鑰庫) +plugin.certconfig.ALIAS_LOAD_EXCEPTION=無法從密鑰庫獲取別名({0})。 +plugin.certconfig.INVALID_KEYSTORE_TYPE=勾選的密鑰庫類型可能不可用({0})。 +plugin.certconfig.BROWSE_KEYSTORE=開啟密鑰庫 +plugin.certconfig.REVOCATION_TITLE=證書吊銷選項 +plugin.certconfig.REVOCATION_CHECK_ENABLED=啟用CRL(證書吊銷列表) +plugin.certconfig.REVOCATION_OCSP_ENABLED=啟用OCSP(在線證書狀態通訊協定) # Phone number contact source plugin +plugin.phonenumbercontactsource.DISPLAY_NAME=電話號碼 # properties editor +plugin.propertieseditor.TITLE=屬性編輯器 +plugin.propertieseditor.NEW_PROPERTY_TITLE=增加新屬性 +plugin.propertieseditor.CHECK_BOX=下次顯示此警告 +plugin.propertieseditor.DESCRIPTION=下列按鈕允許修改Jitsi性能設定。改變這些進階設定可能會妨害程式的穩定性,安全性和性能。如果您確信已了解您的變更,請繼續。 +plugin.propertieseditor.IM_AWARE=我了解相關的風險 +plugin.propertieseditor.NEED_RESTART=注意:某些屬性需要重新啟動,新設定才會生效。 #Thunderbird address book plugin +plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird +plugin.thunderbird.ENABLED=已啟用 +plugin.thunderbird.PHONE_PREFIX=電話區碼: -- cgit v1.1 From 19ac5753d89b1228c27c20df1dc402166f7c580c Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:51:44 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1492 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_fr.properties | 239 +++++++--------------------- 1 file changed, 54 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_fr.properties b/resources/languages/resources_fr.properties index 6f81b83..e9aac93 100644 --- a/resources/languages/resources_fr.properties +++ b/resources/languages/resources_fr.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Moi service.gui.ACCOUNT_REGISTRATION_WIZARD=Assistant d'enregistrement de compte service.gui.ACCOUNTS=Comptes service.gui.ADD=&Ajouter -service.gui.ADD_ACCOUNT=Ajouter un compte service.gui.ADD_CONTACT=&Ajouter un contact service.gui.ADD_AUTHORIZED_CONTACT=Ajouter {0} à votre liste de contacts service.gui.ADD_CONTACT_TO_CONTACTLIST=Ajouter le contact à votre liste de contacts @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Échec lors de l'ajout du contact service.gui.ADD_CONTACT_EXIST_ERROR=Le contact {0} existe déjà dans votre liste de contact. service.gui.ADD_CONTACT_NETWORK_ERROR=Le serveur n''a pas répondu à la requête d''ajout du contact avec l''id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Échec lors de l''ajout du contact id: {0}. L''opération n''est pas prise en charge. -service.gui.ADD_CONTACT_IDENTIFIER=Dans le champ suivant, veuillez entrer l'identifiant du contact que vous souhaitez ajouter. -service.gui.ADD_CONTACT_WIZARD=Assistant d'ajout de contact service.gui.ADD_CONTACT_NOT_CONNECTED=Vous devez être connecté pour ajouter un contact. Veuillez vous connecter au fournisseur sélectionné avant de réessayer. service.gui.ADD_GROUP_LOCAL_ERROR=Échec lors de l''ajout du groupe : {0}. Le problème est dû à un échec d''E/S lors d''une opération locale. service.gui.ADD_GROUP_EXIST_ERROR=Le groupe {0} existe déjà dans votre liste de contact. Veuillez choisir un nom différent. service.gui.ADD_GROUP_NET_ERROR=Échec lors de l''ajout du groupe : {0}. Le problème est dû à une erreur réseau. Veuillez vérifier votre connexion au réseau puis réessayez. service.gui.ADD_GROUP_ERROR=Échec lors de l''ajout du groupe : {0}. service.gui.ADD_GROUP_EMPTY_NAME=Le nom du groupe ne doit pas être vide. -service.gui.ADD_GROUP=Créer un groupe -service.gui.ADD_SUBCONTACT=&Ajouter un sous-contact service.gui.ADDRESS=Adresse service.gui.ADMINISTRATOR=administrateur service.gui.ADVANCED=&Avancé -service.gui.ALL=&Tous service.gui.ALL_CONTACTS=&Tous les contacts service.gui.ALTERNATE_ADDRESS=Autre adresse service.gui.APPLY=&Appliquer @@ -65,7 +70,6 @@ service.gui.AT=à service.gui.AUTHORIZE=Autoriser service.gui.AUTHORIZATION_ACCEPTED={0} a accepté votre demande d''autorisation. service.gui.AUTHENTICATION_FAILED=L''authentification a échoué pour {0}. Le mot de passe que vous avez fourni est incorrect. -service.gui.AUTHENTICATION_REQUESTED=Authentification requise service.gui.AUTHENTICATION_REQUESTED_SERVER=Le serveur {0} demande votre authentification. service.gui.AUTHENTICATION_REJECTED={0} a rejeté votre demande d''authentification. service.gui.AUTHENTICATION_WINDOW_TITLE=Authentification de {0} @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Vous pouvez saisir votre surnom dans le champ service.gui.CHANGE_NICKNAME_ERROR=Erreur lors du changement de pseudonyme service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Ce pseudonyme existe déjà service.gui.CHANGE_VIDEO_QUALITY=Changer la qualité de la vidéo -service.gui.CHAT_CONFERENCE_LABEL=Conférence service.gui.CHAT_CONFERENCE_ITEM_LABEL=Conférence de {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Vous avez déjà rejoint la conversation {0}. service.gui.CHAT_ROOM_CONFIGURATION=Configuration de la conversation {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=a quitté la conversation {0} service.gui.CHAT_ROOM_USER_KICKED=a été banni par {0} service.gui.CHAT_ROOM_USER_QUIT=a mis un terme à {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=L'envoi de message est interdit (voix annulée) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Enregistrer la discussion pour un usage futur -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Supprime la discussion sélectionnée de ma liste de favoris service.gui.CHAT_ROOM_NAME=Nom de la conversation service.gui.CLEAR_CUSTOM_MESSAGES=Effacer les messages personnalisés service.gui.ROOM_NAME=Conversation -service.gui.AUTOJOIN=Connexion automatique service.gui.CHANGE_PASSWORD=Modifier le mot de passe service.gui.CHAT_ROOM_NAME_INFO=Dans le champ suivant, veuillez entrer le nom de la conversation que vous souhaitez créer. service.gui.CHAT_ROOM_NOT_EXIST=Le salon {0} est introuvable sur le serveur {1}. Veuillez vérifier la validité du nom que vous avez saisi. service.gui.CHAT_ROOM_NOT_CONNECTED=Vous devez vous connecter pour rejoindre la conversation {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Vous devez être connecté pour pouvoir quitter une conversation. -service.gui.CHAT_ROOM_NOT_JOINED=Vous devez d'abord rejoindre une conversation pour effectuer cette opération. service.gui.CHAT_ROOM_OPTIONS=Options de la conversation service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Vous devez être enregistré afin de pouvoir le rejoindre le salon {0}. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Le salon {0} nécessite un mot de passe. @@ -151,22 +150,20 @@ service.gui.CLEAR=Effacer service.gui.CLOSE=F&ermer service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Vous avez reçu un message il y a moins de 2 secondes. Êtes-vous sûr de vouloir fermer cette conversation ? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Des fichier sont en cours de transfert. Êtes-vous sûr de vouloir les annuler ? -service.gui.CONFIRM=Confirmer service.gui.CONNECTED_STATUS=Connecté service.gui.CONNECTING=Connexion... service.gui.CONNECTING_STATUS=Connexion service.gui.CONNECTING_EARLY_MEDIA_STATUS=Connexion* service.gui.CONNECTION=Connexion -service.gui.CONNECTION_FAILED_MSG=Échec de connexion pour le compte : Nom d''utilisateur : {0}, Nom du serveur : {1}. Veuillez vérifier votre connexion au réseau ou contacter votre administrateur réseau pour plus d''informations. service.gui.CONNECTION_EXPIRED_MSG=Vous êtes déconnecté du serveur {0}. service.gui.CONTACT_NAME=ID ou numéro -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Le contact {0} ne supporte pas la téléphonie. +service.gui.CONTACT_NAME_PROMPT=joan.martin@exemple.com +service.gui.CONTACT_NAME_INFO=Ajoutez soit une adresse de messagerie instantanée - telle que joan.martin@exemple.com - ou un numéro VoIP. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Le contact {0} ne supporte pas les conférences de messagerie. service.gui.CONTACT_PAUSED_TYPING={0} s''est arrêté d''écrire le message service.gui.CONTACT_TYPING={0} écrit un message service.gui.CONTACT_TYPING_SEND_FAILED=Oups...nous ne pouvons envoyer à {0} la notification d''écriture service.gui.CONTACT_INFO=Informations sur le &contact -service.gui.CONTACTLIST=Liste de contacts service.gui.CONTACTS=Contacts service.gui.COPY=&Copier service.gui.COPY_LINK=Copier &l'adresse @@ -176,28 +173,26 @@ service.gui.CREATE_CHAT_ROOM=&Créer un salon... service.gui.CREATE_CHAT_ROOM_ERROR=Échec lors de la création du salon {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Assistant de création de salon service.gui.CREATE_CONFERENCE_CALL=&Créer une conférence téléphonique... -service.gui.CREATE_CONFERENCE_CHAT=&Créer une conférence de messagerie... service.gui.CREATE_GROUP=&Créer un groupe... service.gui.CREATE_GROUP_NAME=Veuillez saisir dans le champ suivant le nom du groupe que vous désirez créer. -service.gui.CREATE_FIRST_GROUP_WIZARD=Votre liste de contacts ne contient aucun groupe. Veuillez créer un groupe (Fichier/Créer un groupe) en premier lieu. service.gui.CREATE_VIDEO_BRIDGE=Créer un &pont vidéo service.gui.CREATE_VIDEO_BRIDGE_MENU=Créer un &pont vidéo service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Créer / Joindre la video conférence service.gui.CREATE_VIDEO_CONFERENCE=Créer une nouvelle conférence vidéo pour ce salon de discussion service.gui.CONTACT_INFO_NOT_SUPPORTED=Ce contact ne dispose pas d'informations en ligne service.gui.CUT=&Couper -service.gui.DATE=Date service.gui.DELETE=Supprimer service.gui.DENY=&Refuser service.gui.DESKTOP_SHARING_WARNING=Êtes vous certain de vouloir démarrer le partage d'écran?
    En cliquant sur OK, vos correspondants sur cet appel pourront voir votre écran. service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Vous partagez votre écran service.gui.DIALPAD=Clavier téléphonique service.gui.DISPLAY_NAME=Nom affiché +service.gui.DISPLAY_NAME_PROMPT=Joan Martin +service.gui.DISPLAY_NAME_INFO=Ajouter un nom à ce contact. Si laissé vide, l'adresse de messagerie instantanée ou le numéro VoIP sera utilisé à la place. (Optionnel) service.gui.DISCONNECTED_STATUS=Déconnecté service.gui.DND_STATUS=Ne pas déranger service.gui.DO_NOT_ASK_AGAIN=Ne plus redemander service.gui.DO_NOT_SHOW_AGAIN=Ne plus afficher ce message -service.gui.DOWNLOAD_NOW=&Télécharger maintenant service.gui.DRAG_FOR_SHARING=Glisser ici pour partager service.gui.DURATION=durée service.gui.DESTROY_CHATROOM=Supprimer le salon @@ -218,7 +213,6 @@ service.gui.ERROR_RECEIVED_FROM=Erreur reçu de {0} service.gui.ESTIMATED_TIME=Temps estimé : service.gui.EVENTS=Événements service.gui.EXIT=Q&uitter -service.gui.EXTENDED_CRITERIA=Critères étendus service.gui.GENERAL=Général service.gui.GENERAL_ERROR=Erreur générale service.gui.GROUP_NAME=Nom du groupe @@ -260,7 +254,6 @@ service.gui.FONT_ITALIC=Italique service.gui.FONT_SIZE=Taille service.gui.FONT_STYLE=Style service.gui.FONT_UNDERLINE=Souligné -service.gui.FROM={0} sur {1} service.gui.GRANT_OWNERSHIP=Attribuer la propriété... service.gui.GRANT_ADMIN=Attribuer le statut administrateur... service.gui.GRANT_MODERATOR=Attribuer le statut modérateur @@ -286,7 +279,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Voulez-vous vraiment supprimer définitiv service.gui.HISTORY_REMOVE_ERROR=Erreur lors de la suppression des messages. service.gui.HOME=Domicile service.gui.HOME_PAGE=Page d'accueil -service.gui.HOUR=Heure service.gui.ICE=ICE service.gui.IDENTIFIER=Identifiant service.gui.IGNORE=&Ignorer @@ -310,13 +302,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Inviter des contacts à la visio-conf service.gui.INVITE_REASON=Motif de l'invitation service.gui.IS_CALLING={0} appelle... service.gui.IS_NOW={0} est maintenant {1} -service.gui.JITSI_WARNING=Le communicateur SIP a récemment été renommé Jitsi.
    Si vous souhaitez garder votre version à jour, veuillez télécharger Jitsi.

    Nous sommes désolés pour ce désagrément.

    L'équipe de développement de Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator devient Jitsi service.gui.JOIN=&Rejoindre service.gui.JOIN_AS=&Rejoindre comme service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Joindre une conférence vidéo existante service.gui.JOIN_VIDEO=Joindre avec vidéo -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Fermer service.gui.JOB_TITLE=Profession service.gui.JOIN_CHAT_ROOM=Re&joindre la conversation... service.gui.JOIN_CHAT_ROOM_TITLE=Rejoindre la conversation @@ -329,7 +318,6 @@ service.gui.KICK_FAILED=Échec de la tentative d'exclusion service.gui.KICK_FAILED_GENERAL_ERROR=Échec de l''exclusion de {0}. Une erreur du serveur est survenue. service.gui.KICK_FAILED_NOT_ALLOWED=Échec de l''exclusion de {0}. Le propriétaire et l''administrateur de la conversation ne peuvent être exclus. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Échec de l''exclusion de {0}. Vous n''avez pas les droits suffisants pour cela. -service.gui.LAST=Dernier service.gui.LAST_NAME=Nom : service.gui.LEAVE=&Quitter service.gui.LIMIT_REACHED_FOR_IP=Vous avez trop de connexions existantes de l''adresse IP locale et le serveur {0} ne permet pas d''en ouvrir plus. @@ -349,7 +337,6 @@ service.gui.MESSAGE=Message service.gui.MISSED_CALLS_TOOL_TIP=Appels en absence de: service.gui.MISSED_CALLS_MORE_TOOL_TIP= ainsi que {0} autre(s) service.gui.MODERATOR=modérateur -service.gui.MORE=Voir d'avantage service.gui.MORE_LABEL=Plus service.gui.MOVE=Déplacer service.gui.MOVE_SUBCONTACT=D&éplacer le sous-contact @@ -358,7 +345,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Le contact choisi est le même que celui que service.gui.MOVE_SUBCONTACT_QUESTION=Êtes-vous sûr de vouloir déplacer {0} vers {1} ? service.gui.MOVE_TO_GROUP=&Déplacer vers le groupe service.gui.MOVE_CONTACT=D&éplacer le contact -service.gui.MOVE_CONTACT_ERROR=Le &contact ne peut pas être déplacé service.gui.MSG_DELIVERY_FAILURE=Le message ci-dessus n'a pas pu être délivré service.gui.MSG_DELIVERY_NOT_SUPPORTED=Le protocole que vous utilisez n''offre pas le support de l''envoi de messages en mode déconnecté. Vous pouvez essayer de joindre {0} au moyen d''un autre protocole ou attendre que celui-ci se connecte. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Une erreur interne est survenue. Il s''agit certainement d''un bug. Veuillez le signaler ici : https://jitsi.org/Development/BugsAndIssues. @@ -372,7 +358,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Vous devez être connecté pour pouvoir service.gui.MULTIPLE_LOGINS=Vous vous êtes connecté plus d''une fois avec le même compte. Le compte suivant : Nom d''utilisateur : {0}, Nom du serveur : {1} est actuellement déconnecté. service.gui.MY_CHAT_ROOMS=Ajouter un salon de discussion service.gui.MY_CHAT_ROOMS_TITLE=Ajouter un salon de discussion -service.gui.MUTE=Muet service.gui.MUTUALLY_ON_HOLD_STATUS=Les deux en attente service.gui.NAME=Nom service.gui.NETWORK=Réseau @@ -404,7 +389,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Pas dans la liste de contacts service.gui.SD_QUALITY=Qualité standard service.gui.OFFLINE=Déconnecté service.gui.OK=&Ok -service.gui.OLDER_CALLS=Anciens appels service.gui.ONLINE=Connecté service.gui.OPEN=Ouvrir service.gui.OPEN_FILE_FROM_IMAGE=Double-cliquez pour ouvrir le fichier. @@ -416,7 +400,6 @@ service.gui.OPEN_ON_ACTIVITY=Ouvrir lors d'activité service.gui.OPEN_ON_MESSAGE=Ouvrir seulement lors d'un message service.gui.OPEN_ON_IMPORTANT_MESSAGE=Ouvrir seulement lors de messages importants service.gui.OR=ou -service.gui.OR_ENTER_PHONE_NUMBER=Ou entrez un numéro de téléphone ici... service.gui.ORGANIZATION=Entreprise : service.gui.OTHER=Autre service.gui.chat.role.OWNER=Propriétaire @@ -442,7 +425,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Entrée' pour les suggestions service.gui.PRESS_FOR_CALL_INFO=Détails d'appel service.gui.PRESS_TO_OPEN_CRM=Appuyer pour ouvrir l'application CRM service.gui.PREVIOUS=Précédent -service.gui.PREVIOUS_TOOLTIP=Parcourir les anciennes conversations service.gui.PRINT=&Imprimer service.gui.PROACTIVE_NOTIFICATION=est en train d'écrire un message service.gui.PROBLEMS_ENCOUNTERED=Problème survenu @@ -458,7 +440,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Vous vous êtes déconnecté et reconnec service.gui.RE_REQUEST_AUTHORIZATION=Re-demander l'autorisation service.gui.REFERRED_STATUS=Renvoyé service.gui.REJECT=&Rejeter -service.gui.REMIND_ME_LATER=Rappelez-moi plus tard service.gui.REMEMBER_PASSWORD=Mémoriser le mot de passe service.gui.REMOVE=&Supprimer service.gui.REMOVE_ACCOUNT=&Supprimer le compte @@ -484,29 +465,22 @@ service.gui.REVOKE_ADMIN=Révoquer le statut administrateur service.gui.REVOKE_MODERATOR=Révoquer le statut modérateur service.gui.REVOKE_MEMBERSHIP=Révoquer le statut membre service.gui.REVOKE_VOICE=Révoquer le droit de parole -service.gui.ROOT_GROUP=Groupe racine service.gui.SAVE=&Sauvegarder -service.gui.SAVE_AS_DEFAULT=Enregistrer comme valeur par défaut service.gui.SEARCH=&Rechercher service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Cliquez sur le bouton ci-dessous pour afficher tous les salons existant du serveur sélectionné. Puis, choisissez celui que vous souhaitez rejoindre et cliquez le bouton "rejoindre". service.gui.SEARCH_STRING_CONTACT_SOURCE=Contact recherché service.gui.SECURITY=Sécurité -service.gui.SELECT_ACCOUNT=Choix d'un compte +service.gui.SELECT_ACCOUNT_INFO=Quel compte souhaitez-vous utiliser pour communiquer avec ce contact ? service.gui.SELECT_COLOR=Choix de la couleur service.gui.SELECT_GROUP=Choisissez un groupe -service.gui.SELECT_GROUP_WIZARD_MSG=La liste suivante contient tous les groupes de votre liste de contacts. Choisissez celui auquel vous souhaitez ajouter un nouveau contact. +service.gui.SELECT_GROUP_INFO=Quel groupe souhaitez-vous afficher pour ce contact ? (Optionnel) service.gui.SELECT_NO_GROUP=Pas de groupe -service.gui.SELECT_GROUP_WIZARD=Spécifiez un groupe service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=La liste suivante contient tous les comptes qui permettent de participer à des salons de discussion. Choisissez celui que vous souhaitez utiliser pour créer un salon. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=La liste suivante contient tous les comptes enregistrés. Choisissez celui que vous souhaitez utiliser pour communiquer avec le nouveau contact. -service.gui.SELECT_PROVIDERS_WIZARD=Choisir un compte service.gui.SELECT_VIDEO_CONFERENCE=Sélectionner une vidéoconférence service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Sélectionner un salon de discussion sur la liste et appuyer sur OK pour l'ajouter. service.gui.SEND=&Envoyer service.gui.SEND_FILE=Envoyer un &fichier -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Aucune information n'est disponible pour ce contact. service.gui.SEND_MESSAGE=&Envoyer un message -service.gui.SEND_AS_SMS=Envoyer en tant que SMS service.gui.SEND_PRIVATE_MESSAGE=Envoyer un message privé service.gui.SEND_SMS=E&nvoyer un SMS service.gui.SEND_SMS_DETAILS=Vous devez entrer le numéro de téléphone dans un format international, par exemple en commençant par +33 pour téléphoner en France. @@ -545,7 +519,6 @@ service.gui.STREET=Rue service.gui.SUBJECT=Sujet service.gui.SUMMARY=Résumé service.gui.TELEPHONY=Téléphonie -service.gui.TODAY=Aujourd'hui service.gui.TOOLS=&Outils service.gui.TRANSFER=Trans&férer service.gui.TO=À : @@ -555,7 +528,6 @@ service.gui.TRANSFER_CALL_TO=Transférer à : service.gui.TRANSPARENCY_NOT_ENABLED=La transparence ne peut pas être prise en charge avec votre configuration actuelle. service.gui.TYPE_YOUR_REQUEST=Saisissez ici votre demande service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Nous n'avons pas pu changer la qualité vidéo pour cet appel. -service.gui.UNMUTE=Désactiver muet service.gui.USER_IDENTIFIER=Identificateur : service.gui.USER_EXISTS_ERROR=Cet utilisateur existe déjà sur le réseau sélectionné. Veuillez choisir un autre utilisateur ou réseau. service.gui.USERNAME_NULL=Veuillez renseigner votre nom d'utilisateur et votre mot de passe. @@ -568,7 +540,6 @@ service.gui.USE_PROVISIONING=Utiliser le service en ligne service.gui.VALUE=Valeur service.gui.VIDEO_CALL=Appel video service.gui.VIA=via -service.gui.VIA_SMS=Par SMS service.gui.VIEW=&Voir service.gui.VIEW_HISTORY=Voir l'&historique service.gui.VIEW_SMILEYS=Afficher les &smileys @@ -588,9 +559,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Ajuster le volume service.gui.WAITING_AUTHORIZATION=Attente d'autorisation service.gui.WARNING=Avertissement service.gui.YES=Oui -service.gui.YESTERDAY=Hier -service.gui.EXISTING_ACCOUNT_ERROR=Le compte saisi est déjà installé. -service.gui.NEW_MAIL=Vous avez un nouvel email !
    De : {0} {1}
    Sujet : {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Vous avez reçu un nouvel email dans votre boîte de réception {0} :
    service.gui.NEW_GMAIL_MANY_HEADER=Vous avez reçu {2} nouveaux emails dans votre boîte de réception {0} :
    service.gui.NEW_GMAIL_FOOTER=une conversation non-lue supplémentaire dans votre boîte de réception.
    @@ -602,6 +570,9 @@ service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Activer le mode plein-écran service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Désactiver le mode plein-écran service.gui.HOLD_BUTTON_TOOL_TIP=Activer/Désactiver la mise en attente service.gui.MUTE_BUTTON_TOOL_TIP=Activer/Désactiver le microphone ou ajuster le volume du microphone +service.gui.PARK=Parcage +service.gui.PARKING_SLOT=Place de parcage: +service.gui.PARK_BUTTON_TOOL_TIP=Parcage de l'appel service.gui.RECORD_BUTTON_TOOL_TIP=Activer/Désactiver l'Enregistrement service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=Activer/Désactiver la Vidéo service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Montrer/cacher la vidéo locale @@ -614,7 +585,6 @@ service.gui.SECURITY_ERROR=Erreur de sécurité service.gui.SPEED=Vitesse : service.gui.SILENT_MEMBER=membre muet service.gui.NON_SECURE_CONNECTION=Aucune connexion sécurisée ne peut être établie avec le compte {0}. Pour établir une connexion non sécurisée du serveur, l''option "autoriser une connexion non sécurisée" doit être activée. -service.gui.UPDATE=Mise à jour service.gui.MOBILE_PHONE=Mobile service.gui.VIDEO_PHONE=Vidéo service.gui.WORK_PHONE=Professionnel @@ -649,12 +619,10 @@ service.gui.callinfo.CALL_INFORMATION=Information d'appel service.gui.callinfo.CALL_IDENTITY=Identité service.gui.callinfo.PEER_COUNT=Nombre de participants service.gui.callinfo.IS_CONFERENCE_FOCUS=Organisateur de conférences -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Encodage actif service.gui.callinfo.CALL_TRANSPORT=Transport du canal de signalisation service.gui.callinfo.CALL_DURATION=Durée d'appel service.gui.callinfo.TLS_PROTOCOL=Protocole TLS service.gui.callinfo.TLS_CIPHER_SUITE=Liste de chiffrement TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Liste de certificats du serveur TLS service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Le contenu du certificat du serveur TLS est affiché ci-dessous. service.gui.callinfo.VIEW_CERTIFICATE=Voir le certificat service.gui.callinfo.CODEC=Codec / Fréquence @@ -664,7 +632,7 @@ service.gui.callinfo.AUDIO_INFO=Information audio service.gui.callinfo.VIDEO_INFO=Information vidéo service.gui.callinfo.LOCAL_IP=IP local / Port service.gui.callinfo.REMOTE_IP=IP partenaire / Port -service.gui.callinfo.BANDWITH=Largeur de bande +service.gui.callinfo.BANDWITH=Bande passante service.gui.callinfo.LOSS_RATE=taux de perte service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -674,10 +642,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocole d'échange de clés service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Amélioration du candidat type ICE service.gui.callinfo.ICE_STATE=Statut du traitement ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Candidats regroupés service.gui.callinfo.ICE_STATE.RUNNING=contrôles de connexion service.gui.callinfo.ICE_STATE.COMPLETED=Terminé service.gui.callinfo.ICE_STATE.FAILED=Échec + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP local / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=IP local réfléchi / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=IP local transmis / Port @@ -698,11 +669,12 @@ service.gui.ALWAYS_TRUST=Toujours faire confiance à ce certificat service.gui.CERT_DIALOG_TITLE=Vérifier le certificat service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} ne peut pas vérifier l''identité du serveur lors de la connexion à {1}.

    Le certificat est inconnu, ce qui signifie que l''identité du serveur n''a pu être vérifiée automatiquement.

    Voulez-vous poursuivre la connexion ?

    Pour plus d''informations, cliquez sur "Afficher le certificat". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} ne peut pas vérifier l''identité du serveur.

    Le certificat est inconnu, ce qui signifie que l''identité du serveur n''a pu être vérifiée automatiquement. Voulez-vous poursuivre la connexion ?

    Pour plus d''informations, cliquez sur "Afficher le certificat". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} ne peut pas vérifier l''identité du client.

    Le certificat est inconnu, ce qui signifie que l''identité du client n''a pu être vérifiée automatiquement.

    Voulez-vous poursuivre la connexion ?

    Pour plus d''informations, cliquez sur "Afficher le certificat". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} ne peut vérifier l''identité du vis-àvis {1}.

    Le certificat est inconnu, ce qui signifie que l''identité du vis-à-vis n''a pu être vérifiée automatiquement.

    Voulez-vous poursuivre la connexion ?

    Pour plus d''informations, cliquez sur "Afficher le certificat". service.gui.CONTINUE_ANYWAY=Continuer quand même service.gui.CERT_INFO_CHAIN=Chaîne de certificat : service.gui.CERT_INFO_ISSUED_TO=Émis pour + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nom Commun : service.gui.CERT_INFO_O=Organisation : service.gui.CERT_INFO_C=Pays : @@ -721,16 +693,14 @@ service.gui.CERT_INFO_SIGN_ALG=Algorithme de signature : service.gui.CERT_INFO_PUB_KEY_INFO=Information sur la clé publique service.gui.CERT_INFO_ALG=Algorithme : service.gui.CERT_INFO_PUB_KEY=Clé publique : -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} octets : {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Exposant service.gui.CERT_INFO_KEY_SIZE=Taille de la clé : service.gui.CERT_INFO_SIGN=Signature : -service.gui.CONTINUE=Continuer service.gui.SHOW_CERT=Afficher le certificat service.gui.HIDE_CERT=Masquer le certificat -service.gui.AUTO_ANSWER=Réponse automatique et transmisssion de l'appel +service.gui.AUTO_ANSWER=Réponse automatique et transmission de l'appel service.gui.AUTO_ANSWER_LABEL=Réponse automatique service.gui.AUTO_ANSWER_ALL_CALLS=Tous les appels service.gui.AUTO_ANSWER_ALERT_INFO_FIELDS=Uniquement pour les appels qui demandent une réponse automatique ("Alerte-info" avec "réponse automatique") @@ -749,12 +719,9 @@ service.gui.security.SECURE_AUDIO=Audio crypté service.gui.security.AUDIO_NOT_SECURED=Audio non crypté service.gui.security.SECURE_VIDEO=Vidéo crypté service.gui.security.VIDEO_NOT_SECURED=Vidéo non crypté -service.gui.security.NO_VIDEO=Aucune vidéo -service.gui.security.CIPHER=Algorithme: {0} service.gui.security.CALL_SECURED_TOOLTIP=Appel crypté. Cliquez pour plus d'information. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Appel non crypté. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Cliquez ici pour comparer le secret sécurisé avec votre interlocuteur. -service.gui.security.COMPARE_WITH_PARTNER=Comparez avec votre correspondant et cliquez sur le cadenas pour confirmer. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparez avec votre correspondant: service.gui.security.STRING_COMPARED=SAS confirmé @@ -772,20 +739,14 @@ service.gui.avatar.imagepicker.CLICK=Cliquez et souriez service.gui.avatar.imagepicker.IMAGE_FILES=Fichiers d'images service.gui.avatar.imagepicker.IMAGE_PICKER=Image service.gui.avatar.imagepicker.IMAGE_SIZE=Taille de l'image -service.gui.avatar.imagepicker.INITIALIZING=Initialisation service.gui.avatar.imagepicker.RESET=Réinitialiser service.gui.avatar.imagepicker.SET=Définir service.gui.avatar.imagepicker.TAKE_PHOTO=Prendre une photo -service.gui.avatar.imagepicker.WEBCAM_ERROR=Erreur de la webcam service.gui.security.encryption.required=Cryptage requis service.protocol.ICE_FAILED=Impossible d'établir la connexion (ICE a échoué et aucun relais n'a été trouvé) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Erreur dans les contacts SIP itinérants impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=La ressource{0} ne peut être lu. Compte: {1} @@ -815,9 +776,7 @@ impl.ldap.QUERY_CUSTOM=Requête personnalisée impl.ldap.QUERY_CUSTOM_HINT=Utilisez {0} comme espace réservé pour la recherche. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Ajouter automatiquement des caractères génériques pour la requête impl.ldap.QUERY_PHOTO_INLINE=Récupérer la photo avec d'autres attributs -impl.ldap.NEW=Nouveau impl.ldap.EDIT=Édition -impl.ldap.REMOVE=Supprimer impl.ldap.ENABLED=Activer impl.ldap.SERVER_NAME=Nom du serveur impl.ldap.SERVER_NAME_EXAMPLE=Mon serveur LDAP @@ -850,6 +809,12 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=TéléphoneDomicile impl.ldap.PHONE_PREFIX=Indicatif téléphonique impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS=''{0}'' n'est pas une adresse SIP correcte. + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS=''{0}'' n'est pas un JID XMPP valide. + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Carnet d'adresses plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Activer les recherches dans le carnet MacOSX @@ -864,9 +829,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Définir Outlook comme logiciel # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Contacts Google -impl.googlecontacts.NEW=Nouveau impl.googlecontacts.EDIT=Édition -impl.googlecontacts.REMOVE=Supprimer impl.googlecontacts.ENABLED=Activer impl.googlecontacts.ACCOUNT_NAME=Nom du compte impl.googlecontacts.SAVE=Enregistrer @@ -875,6 +838,9 @@ impl.googlecontacts.USERNAME=Nom du compte impl.googlecontacts.PASSWORD=Mot de passe impl.googlecontacts.PREFIX=Indicatif téléphonique impl.googlecontacts.WRONG_CREDENTIALS=Mauvais identifiants pour le compte Google {0} +impl.googlecontacts.OAUTH_DIALOG_TITLE=Autorisation de contacts Google +impl.googlecontacts.CODE=Code : +impl.googlecontacts.HYPERLINK_TEXT=Cliquer ici pour donner accès à {0} # account info plugin.accountinfo.TITLE=Informations du compte @@ -905,11 +871,8 @@ plugin.accountinfo.ORGANIZATION=Entreprise: plugin.accountinfo.JOB_TITLE=Profession: plugin.accountinfo.ABOUT_ME=À mon propos: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Images du contact plugin.accountinfo.GLOBAL_ICON=Utilisez l'icône global plugin.accountinfo.LOCAL_ICON=Utiliser cette icône: -plugin.accountinfo.CHANGE=Changer -plugin.accountinfo.ONLY_MESSAGE=Messages uniquement # connection info plugin.connectioninfo.TITLE=Informations de connexion @@ -929,49 +892,13 @@ plugin.aimaccregwizz.USERNAME=Nom d'utilisateur AIM : plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nom d'utilisateur et mot de passe plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Enregistrer un nouveau compte plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Si vous n'avez pas de compte AIM, cliquez sur ce bouton pour en créer un nouveau. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Passer outre les paramètres par défaut du serveur # branding plugin.branding.ABOUT_WINDOW_TITLE=À propos de {0} plugin.branding.LOGO_MESSAGE=VoIP && Messagerie instantanée Open Source -plugin.branding.LOADING=Chargement plugin.branding.ABOUT_MENU_ENTRY=&À propos -plugin.branding.WELCOME_MESSAGE=
    {1} est actuellement en développement intensif. Cette version est expérimentale et peut NE PAS fonctionner comme elle devrait. Plus d''informations sur {2}.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Tous droits réservés. Rendez-vous sur https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi est distribué selon les conditions de la LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Dictionnaires -plugin.dictaccregwizz.ANY_DICTIONARY=Tous les dictionnaires -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Tous les dictionnaires de {0} -plugin.dictaccregwizz.FIRST_MATCH=Premier résultat -plugin.dictaccregwizz.NO_MATCH=Aucun résultat -plugin.dictaccregwizz.MATCH_RESULT=Aucune définition trouvée pour "{0}", peut-être vouliez vous dire :\n -plugin.dictaccregwizz.INVALID_DATABASE=Le dictionnaire actuel "{0}" n''existe plus sur le serveur. -plugin.dictaccregwizz.INVALID_STRATEGY=La stratégie actuelle n'existe plus sur le serveur. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Protocole du service Dict -plugin.dictaccregwizz.HOST=Hôte -plugin.dictaccregwizz.SERVER_INFO=Informations sur le serveur -plugin.dictaccregwizz.STRATEGY_SELECTION=Sélection de la stratégie -plugin.dictaccregwizz.STRATEGY_LIST=Liste des stratégies : -plugin.dictaccregwizz.SEARCH_STRATEGIES=Rechercher les stratégies -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Les stratégies sont utilisées pour rechercher les mots similaires si aucune définition n'a été trouvée. Il existe différentes approches ; par exemple : la stratégie Prefix recherchera tous les mots qui commencent comme le mot dont vous cherchez la définition. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Information sur le compte Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Cet assistant va créer votre premier compte Dict sur le serveur dict.org.\n\nVous pouvez ajouter d'autres serveurs de dictionnaires en utilisant à nouveau cet assistant. Renseignez le champ Hôte avec le dictionnaire que vous souhaitez ajouter. -plugin.dictaccregwizz.THREAD_CONNECT=Tentative de connexion au serveur -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=La tentative de connexion a échoué. Le serveur est hors ligne ou ce n'est pas un serveur de dictionnaires. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Récupération des stratégies -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Aucune stratégie n'a été trouvée sur le serveur -plugin.dictaccregwizz.POPULATE_LIST=Mise à jour de la liste -plugin.dictaccregwizz.CLOSING_CONNECTION=Fermeture de la connexion - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Pour utiliser la discussion instantanée de Facebook, vous devez vous créer un "nom d'utilisateur"
    depuis la page "Paramètres du compte" sur Facebook.


    Note: lorsque vous créez votre nom d'utilisateur, vous devrez vous déconnecter de la page web.
    Cela peut prendre un peu de temps avant que vous puissiez vous connecter avec votre nouveau nom d'utilisateur !
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protocole de discussion instantanée Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nom d'utilisateur : -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nom d'utilisateur et mot de passe + +plugin.busylampfield.PICKUP=Répondre à l'appel # generalconfig plugin.generalconfig.AUTO_START=Ouvrir {0} automatiquement au démarrage de l''ordinateur @@ -982,9 +909,6 @@ plugin.generalconfig.SHOW_HISTORY=Afficher les plugin.generalconfig.HISTORY_SIZE=derniers messages plugin.generalconfig.SEND_MESSAGES_WITH=Envoyer les messages avec : plugin.generalconfig.BRING_WINDOW_TO_FRONT=Fenêtre de conversation au premier plan -plugin.generalconfig.ERROR_PERMISSION=Vous n'avez pas les droits requis pour désactiver le démarrage automatique -plugin.generalconfig.TRANSPARENCY=Transparence -plugin.generalconfig.ENABLE_TRANSPARENCY=Activer la transparence plugin.generalconfig.DEFAULT_LANGUAGE=Langue plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Les modifications prendront effet au prochain démarrage de l'application. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% traduit @@ -1000,6 +924,7 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Enlever les symboles spéciaux plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Convertir les lettres en chiffres plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=Ex. +1-800-MONTEL-> +1-800-666895 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Taux d'échantillonnage plugin.generalconfig.OPUS_BITRATE=Taux de transfert moyen (kbps): @@ -1043,13 +968,18 @@ plugin.ircaccregwizz.EXAMPLE_SERVER=Ex. : chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Utiliser une connexion sécurisée plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Présence contacts activé plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Présence salon de discussion activé +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=Authentification SASL +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=Activer l'authentification SASL +plugin.ircaccregwizz.SASL_USERNAME=Nom d'utilisateur +plugin.ircaccregwizz.SASL_AUTHZ_ROLE=Rôle +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=Le mot de passe ci-dessus est utilisé pour l'authentification SASL +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Toujours résoudre les noms DNS au travers du proxy # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Protocole XMPP plugin.jabberaccregwizz.USERNAME=Nom d'utilisateur XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmer le mot de passe -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID et mot de passe plugin.jabberaccregwizz.CSERVER=Serveur plugin.jabberaccregwizz.SERVER=Serveur plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Activer keep alive @@ -1065,13 +995,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Commentaire plugin.jabberaccregwizz.RESOURCE=Ressource plugin.jabberaccregwizz.AUTORESOURCE=Ressource auto-générée plugin.jabberaccregwizz.PRIORITY=Priorité -plugin.jabberaccregwizz.XMPP_ERROR=Erreur XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Erreur XMPP inconnue ({0}). Vérifiez que le nom du serveur est correct. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Les mots de passe ne correspondent pas. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Passer outre les paramètres par défaut du serveur -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Options avancées plugin.jabberaccregwizz.USE_ICE=Utiliser ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Utiliser ICE/Jingle Google (Expérimental !) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Découverte automatique des serveurs STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=Support TURN plugin.jabberaccregwizz.TURN_USERNAME=Nom d'utilisateur TURN @@ -1099,11 +1025,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Désactiver les messages en copie cachée plugin.jabberaccregwizz.DTMF_AUTO=Choix automatique entre RTP et l'intrabande plugin.jabberaccregwizz.SERVER_OPTIONS=Options du serveur plugin.jabberaccregwizz.CHANGE_PASSWORD=Modifier le mot de passe du compte -plugin.jabberaccregwizz.NEW_PASSWORD=nouveau mot de passe -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirmer le mot de passe plugin.jabberaccregwizz.PORT_FIELD_INVALID=Prière de saisir un numéro de port valide pour continuer. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Le compte doit être connecté pour modifier le mot de passe. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Le mot de passe est vide plugin.jabberaccregwizz.TLS_REQUIRED=La connexion n'utilise aucun SSL/TLS, une modification du mot de passe n'est pas pris en charge. plugin.jabberaccregwizz.PASSWORD_CHANGED=Le mot de passe a été modifié avec succès plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Le serveur ne prend aucune modification de mot de passe en charge. @@ -1117,25 +1040,9 @@ plugin.jabberaccregwizz.RESET=Réinitialiser plugin.jabberaccregwizz.RESET_DESCRIPTION=Réinitialiser les paramètres globaux plugin.jabberaccregwizz.DISABLE_JINGLE=Désactiver Jingle ( Son et appel visio avec XMPP) -# mailbox -plugin.mailbox.OUTGOING=Message sortant : -plugin.mailbox.INCOMING=Messages entrants : -plugin.mailbox.WAIT_TIME=Délai avant de rediriger l'appel sur la messagerie vocale -plugin.mailbox.MAX_MESSAGE_TIME=Durée maximum pour les messages entrants -plugin.mailbox.CONFIRM=Confirmer -plugin.mailbox.DEFAULTS=Par défaut -plugin.mailbox.MAILBOX=Boîte aux lettres - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Un protocole pour se connecter et discuter sur le service MSN. -plugin.msnaccregwizz.USERNAME=Email : -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Nom d'utilisateur et mot de passe - # plugin manager plugin.pluginmanager.INSTALL=Installer plugin.pluginmanager.UNINSTALL=Désinstaller -plugin.pluginmanager.UPDATE=Mise à jour plugin.pluginmanager.PLUGINS=Plug-ins plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Sélectionner un fichier @@ -1160,9 +1067,9 @@ plugin.sipaccregwizz.SERVER_PORT=Port du serveur plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Port du proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Transport privilégié -plugin.sipaccregwizz.ADVANCED_OPTIONS=Options avancées plugin.sipaccregwizz.PROXY_OPTIONS=Options du proxy plugin.sipaccregwizz.PROXY_AUTO=Configuration automatique du proxy +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Outrepasser la vérification de sécurité du proxy en cas de scénario de haute disponibilité (à utiliser si nécessaire) plugin.sipaccregwizz.ENABLE_PRESENCE=Activer la présence (SIMPLE) plugin.sipaccregwizz.FORCE_P2P_PRESENCE=Forcer le mode de présence peer-to-peer plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=Période d'interrogation des contacts déconnectés (en s.) @@ -1180,8 +1087,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Choix automatique entre RTP et l'intrabande (pas plugin.sipaccregwizz.DTMF_RTP=RTP (RFC2833 / RFC4733) plugin.sipaccregwizz.DTMF_SIP_INFO=INFO SIP plugin.sipaccregwizz.DTMF_INBAND=Intrabande -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Passer outre les paramètres par défaut du serveur plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Activer le support pour les appels chiffrés plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Montrez le soutien de ZRTP dans le protocole de signalisation plugin.sipaccregwizz.AUTH_NAME=Nom d'autorisation @@ -1202,10 +1107,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Récupération du répondeur URI plugin.sipaccregwizz.NOT_SAME_PASSWORD=Les mots de passe ne correspondent pas. plugin.sipaccregwizz.NO_CERTIFICATE= (utiliser l'enregistrement régulier) plugin.sipaccregwizz.SAVP_OPTION=Indication RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Á partir de (proposer seulement RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Obligatoire (proposer et offrir seulement RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=En option (d'abord proposer RTP/SAVP puis RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Activer le cryptage S-Descriptor ( aussi connu comme SDES ou SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Protocole de décryptage activé et priorité: plugin.sipaccregwizz.CIPHER_SUITES=Suite de cryptage activée plugin.sipaccregwizz.SECURITY_WARNING=
    {0} tente automatiquement de crypter toutes les communications avec ZRTP. Les deux interlocuteurs entendent et voient une alerte lorsqu''une connexion sécurisée est établie. Les paramètres avancés sur cette page ne ​​doivent pas être modifiées sans expertise.
    @@ -1219,15 +1124,6 @@ plugin.skinmanager.DEFAULT_SKIN=Thème par défaut plugin.skinmanager.ADD_NEW_SKIN=Ajouter un nouveau thème... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Le thème par défaut pour l'application. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Un protocole pour se connecter à des machines distantes avec SSH. -plugin.sshaccregwizz.USERNAME=Identifiant du compte : -plugin.sshaccregwizz.IDENTITY_FILE=Fichier d'identité : -plugin.sshaccregwizz.KNOWN_HOSTS=Hôtes connus : -plugin.sshaccregwizz.OPTIONAL=Optionnel -plugin.sshaccregwizz.ACCOUNT_DETAILS=Détails du compte - # status update plugin.autoaway.AUTO_STATUS=Statut d'absence automatique plugin.autoaway.ENABLE_CHANGE_STATUS=Changer le statut en cas d'absence @@ -1275,22 +1171,6 @@ plugin.whiteboard.DESELECT=Dé-sélectionner plugin.whiteboard.DELETE=Supprimer plugin.whiteboard.PROPERTIES=Propriétés -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Un protocole pour se connecter et discuter sur le service Yahoo! -plugin.yahooaccregwizz.USERNAME=Nom d'utilisateur : -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID et mot de passe - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Protocole Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Prénom : -plugin.zeroaccregwizz.LAST_NAME=Nom : -plugin.zeroaccregwizz.EMAIL=Email : -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Se rappeler des contacts Bonjour ? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID et mot de passe -plugin.zeroaccregwizz.USERID=Identifiant utilisateur - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Protocole Google Talk @@ -1304,19 +1184,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, le portail de télécommu plugin.iptelaccregwizz.USERNAME=Nom d'utilisateur plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=S'enregistrer à iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP et messagerie instantanée +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Nom d'utilisateur plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Entrez à nouveau votre mot de passe plugin.sip2sipaccregwizz.EMAIL=Adresse email -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Pour une aide concernant ce service rendez-vous sur
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=L'adresse email est utilisée pour les envois de messages audio,
    de notifications d'appels manqués et pour la récupération de mots de passe perdus -plugin.sip2sipaccregwizz.INFO_NOTE=Pour une aide concernant ce service rendez-vous sur http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Compte sip2sip.info existant -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Créer une compte sip2sip.info gratuit - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Messagerie Instantanée plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Pour une aide concernant ce service rendez-vous sur
    http://ippi.fr @@ -1325,6 +1197,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Compte SIP existant plugin.ippiaccregwizz.CREATE_ACCOUNT=Créer un compte ippi gratuit # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Fermer la fenêtre de conversation plugin.keybindings.CHAT_COPY=Copier plugin.keybindings.CHAT_CUT=Couper @@ -1347,10 +1220,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Action plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Raccourci primaire plugin.keybindings.globalchooser.SHORTCUT_SECOND=Raccourci secondaire plugin.keybindings.globalchooser.PRESS_BTN=Appuyez sur le bouton pour régler le lien -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=en attente plugin.keybindings.globalchooser.PUSH_TO_TALK=Bouton interphone plugin.keybindings.globalchooser.ENABLE_SPECIAL=Activer la reconnaissance des touches spéciales plugin.keybindings.PLUGIN_NAME=Raccourcis +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Fenêtre principal plugin.keybindings.GLOBAL=Raccourcis globaux @@ -1378,6 +1251,7 @@ plugin.notificationconfig.tableheader.SOUND=Jouer un son à travers le dispositi plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Jouer un son à travers le dispositif de reproduction plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Jouer un son à travers les haut-parleurs de l'ordinateur plugin.notificationconfig.tableheader.DESCRIPTION=Description de la norification +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Appel entrant plugin.notificationconfig.event.SecurityMessage=Message de sécurité plugin.notificationconfig.event.IncomingFile=Fichier entrant @@ -1479,6 +1353,7 @@ impl.neomedia.configform.VIDEO=Vidéo impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Utiliser les images intra périodique pour le rafraîchissement impl.neomedia.configform.H264.defaultProfile=Profile d'encodage par défaut à utiliser : +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Ligne de base impl.neomedia.configform.H264.defaultProfile.high=Haute impl.neomedia.configform.H264.defaultProfile.main=Principal @@ -1509,7 +1384,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Mot de passe actuel : plugin.securityconfig.masterpassword.ENTER_PASSWORD=Entrez le nouveau mot de passe : plugin.securityconfig.masterpassword.REENTER_PASSWORD=Retaper le nouveau mot de passe : plugin.securityconfig.masterpassword.MP_TITLE=Mot de passe principal -plugin.securityconfig.masterpassword.MP_NOT_SET=(non défini) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Vous n'avez pas entré le bon mot de passe principal. Veuillez réessayer. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Le mot de passe principal est incorrect ! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Échec du changement de mot de passe @@ -1525,7 +1399,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Mot de passe plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(inconnu) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(impossible de déchiffrer) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Mot de passe enregistré -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Supprimer plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Tout supprimer plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Êtes-vous certain de supprimer tous les mots de passe ? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Supprimer tous les mots de passe @@ -1621,7 +1494,6 @@ plugin.globalproxy.PROXY_PORT=Port du proxy plugin.globalproxy.PROXY_USERNAME=Utilisateur du proxy plugin.globalproxy.PROXY_PASSWORD=Mot de passe proxy plugin.globalproxy.DESCRIPTION={0} utilisera les paramètres de proxy ci-dessus pour tous les réseaux auxquels vous vous connectez ou vous reconnecterez à partir de maintenant. La prise en charge du proxy est encore expérimentale et ne fonctionne qu''avec certains protocoles. Reportez-vous au tableau ci-dessous pour plus de détails : -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Utiliser le proxy aussi pour DNS plugin.globalproxy.FWD_DNS_NOTE=Utile lorsque vous utilisez Tor. Évite la divulgation de données DNS en filtrant tout, le trafic DNS est redirigée par le proxy Tor. Ne prendra effet qu'après le redémarrage. @@ -1659,7 +1531,6 @@ plugin.provisioning.RESTART_WARNING=Veuillez noter que les changements prendront plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Copier l'UUID dans le presse-papiers plugin.provisioning.CLIPBOARD_FAILED=Échec de la copie de l'UUID dans le presse-papiers -plugin.provisioning.EXIT_ON_FAIL=Fermer le programme lors de l'échec de l'approvisionnement plugin.provisioning.CREDENTIALS=Dernières informations d'identification stockées plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Êtes-vous sûr de vouloir supprimer le mot de passe approvisioné? plugin.provisioning.PROV_FAILED=Échec de l'approvisionnement @@ -1726,8 +1597,6 @@ util.dns.DNSSEC_WARNING=
    a essayé de contacter le serveu #plugin spellcheck plugin.spellcheck.TITLE=Grammaire et Orthographe plugin.spellcheck.MENU=Afficher Grammaire et Orthographe -plugin.spellcheck.LANG=Langue -plugin.spellcheck.EDIT_PERSONAL_DICT=Éditer plugin.spellcheck.ENABLE_SPELL_CHECK=Activer la vérification d'orthographe plugin.spellcheck.dialog.FIND=Chercher Suivant plugin.spellcheck.dialog.REPLACE=Remplacer -- cgit v1.1 From c7140966cdaa8e0474373e14516a0efff5fc88c2 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:51:56 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 923 of 1505 strings translated (99 fuzzy). --- resources/languages/resources_ja.properties | 743 +++++++++++++++++++++++----- 1 file changed, 625 insertions(+), 118 deletions(-) diff --git a/resources/languages/resources_ja.properties b/resources/languages/resources_ja.properties index 2d45a75..fe2adb9 100644 --- a/resources/languages/resources_ja.properties +++ b/resources/languages/resources_ja.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -31,43 +42,36 @@ service.gui.ACCOUNT=アカウント service.gui.ACCOUNT_ME=私 service.gui.ACCOUNT_REGISTRATION_WIZARD=アカウント登録ウィザード service.gui.ACCOUNTS=アカウント -service.gui.ADD=追加 (&A) -service.gui.ADD_ACCOUNT=アカウントを追加 +service.gui.ADD=追加(&A) service.gui.ADD_CONTACT=コンタクトを追加 (&A) service.gui.ADD_AUTHORIZED_CONTACT={0} をコンタクトリストに追加します service.gui.ADD_CONTACT_TO_CONTACTLIST=このコンタクトをコンタクトリストに追加 -service.gui.ADD_CONTACT_TO=コンタクトを追加 (&A) +service.gui.ADD_CONTACT_TO=コンタクトを追加する (&A) service.gui.ADD_CONTACT_ERROR={0} というコンタクトを追加できませんでした。 service.gui.ADD_CONTACT_ERROR_TITLE=コンタクト追加エラー service.gui.ADD_CONTACT_EXIST_ERROR=ID: {0} はすでにコンタクトリストに存在します。 -service.gui.ADD_CONTACT_NETWORK_ERROR=コンタクトIDを追加要求に対し、サーバーが応答しませんでした。:{0} -service.gui.ADD_CONTACT_NOT_SUPPORTED=コンタクトID:{0} を追加できませんでした。操作がサポート外です。 -service.gui.ADD_CONTACT_IDENTIFIER=下のフィールドに追加したいコンタクトのIDを入力して下さい。 -service.gui.ADD_CONTACT_WIZARD=コンタクト追加ウィザード +service.gui.ADD_CONTACT_NETWORK_ERROR=コンタクト ID: {0} の追加リクエストに対し、サーバーが応答しませんでした。 +service.gui.ADD_CONTACT_NOT_SUPPORTED=コンタクトID:{0} を追加できませんでした。この操作に対応していません。 service.gui.ADD_CONTACT_NOT_CONNECTED=コンタクト追加するには、サーバー接続が必要です。指定のサービスプロバイダーへ再度ログインしてください。 service.gui.ADD_GROUP_LOCAL_ERROR={0} というグループを追加できませんでした。ローカルI/Oを操作中に問題が起こりました。 service.gui.ADD_GROUP_EXIST_ERROR={0} というグループはすでにコンタクトリストに存在します。ほかの名前を選択してください。 service.gui.ADD_GROUP_NET_ERROR={0}というグループを追加できませんでした。ネットワーク障害のために問題が起こりました。ネットワーク接続を確認のうえ、再度お試しください。 service.gui.ADD_GROUP_ERROR={0} というグループを追加できませんでした。 service.gui.ADD_GROUP_EMPTY_NAME=グループ名を空にする事はできません。 -service.gui.ADD_GROUP=グループを追加 -service.gui.ADD_SUBCONTACT=サブコンタクトを追加 (&A) service.gui.ADDRESS=アドレス service.gui.ADMINISTRATOR=管理者 service.gui.ADVANCED=アドバンスド (&A) -service.gui.ALL=すべて (&A) service.gui.ALL_CONTACTS=すべてのコンタクト (&A) service.gui.ALTERNATE_ADDRESS=代用アドレス service.gui.APPLY=適用 (&A) -service.gui.ARE_CALLING=がコールしています... +service.gui.ARE_CALLING={0}がコールしています... service.gui.ARE_NOW=現在 {0} です service.gui.AT=で service.gui.AUTHORIZE=承認 (&A) -service.gui.AUTHORIZATION_ACCEPTED=コンタクトはあなたの承認申請を受け入れました。 +service.gui.AUTHORIZATION_ACCEPTED={0}はあなたの承認申請を受け入れました。 service.gui.AUTHENTICATION_FAILED={0}の認証に失敗しました。入力されたパスワードが間違っています。 -service.gui.AUTHENTICATION_REQUESTED=認証が求められています service.gui.AUTHENTICATION_REQUESTED_SERVER=サーバ: {0} は認証を要求しました。 -service.gui.AUTHENTICATION_REJECTED=コンタクトはあなたの承認申請を拒否しました。 +service.gui.AUTHENTICATION_REJECTED={0}はあなたの承認申請を拒否しました。 service.gui.AUTHENTICATION_WINDOW_TITLE={0} 認証 service.gui.AUTHORIZATION_REQUESTED=承認が求められています service.gui.AUTHORIZATION_REQUESTED_INFO=コンタクト {0} があなたの承認を求めています。 @@ -75,10 +79,10 @@ service.gui.AUTHORIZATION_RESPONSE=承認の応答 service.gui.AWAY_STATUS=不在 service.gui.EXTENDED_AWAY_STATUS=長期不在 service.gui.BAN=禁止 (&B) -service.gui.BANNED=退出させられました -service.gui.BAN_FAILED=禁止に失敗 -service.gui.BAN_FAILED_GENERAL_ERROR=コンタクト: {0} を禁止できませんでした。一般サーバエラーが発生しました。 -service.gui.BAN_FAILED_NOT_ALLOWED=コンタクト: {0} を禁止できませんでした。ルームのオーナーと管理者は禁止できません。 +service.gui.BANNED=強制退出完了 +service.gui.BAN_FAILED=強制退出できません。 +service.gui.BAN_FAILED_GENERAL_ERROR={0}を強制退出できません。サーバエラーが発生しました。 +service.gui.BAN_FAILED_NOT_ALLOWED=コンタクト: {0} はルームのオーナーまたは管理者のため、強制退出できません。 service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS=コンタクト: {0} を禁止できませんでした。権限がありません。 service.gui.BRB_MESSAGE=ただいま退席中ですが、すぐに戻ります。 service.gui.BROWSE=ブラウズ @@ -87,7 +91,7 @@ service.gui.BUSY_STATUS=取り込み中 service.gui.CALL=コール service.gui.CALL_CONTACT=コンタクトにコールする service.gui.CALL_FAILED=コールに失敗しました -service.gui.CALL_HISTORY_TOOL_TIP=コール履歴を表示するにはここをクリックしてください +service.gui.CALL_HISTORY_TOOL_TIP=通話履歴を表示するにはここをクリックしてください service.gui.CALL_HISTORY_GROUP_NAME=着信履歴 service.gui.CALL_VIA=次のアカウントでコール: service.gui.CALL_NAME_OR_NUMBER=名前か番号で呼び出し @@ -106,11 +110,11 @@ service.gui.CHANGE_NICKNAME_LABEL=新しいニックネームを下のフィー service.gui.CHANGE_NICKNAME_ERROR=ニックネーム変更エラー service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=ニックネームは既に存在します service.gui.CHANGE_VIDEO_QUALITY=相手側の映像品質を変更 -service.gui.CHAT_CONFERENCE_LABEL=会議 -service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}''の会議 +service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}の会議 service.gui.CHAT_ROOM_ALREADY_JOINED=チャットルーム: {0} に既に参加しています。 service.gui.CHAT_ROOM_CONFIGURATION=チャットルーム: {0} 設定 service.gui.CHAT_ROOM_CONFIGURATION_FAILED=チャットルーム: {0} 設定フォームが取得できませんでした。 +service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=チャットルーム {0} の設定を取得できませんでした。チャットルームのオーナーのみが設定画面を見たり、設定を変更することができます。 service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=チャットルーム: {0} の設定を反映中にエラーが発生しました。 service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=メンバーリストを編集 service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=右のリストは、このチャットルームにいるメンバー権限がある人を含んでいます。チャットルームが"メンバーのみ"の場合、このユーザーのみが参加できます。 @@ -119,18 +123,14 @@ service.gui.CHAT_ROOM_USER_LEFT={0} から退室しました service.gui.CHAT_ROOM_USER_KICKED={0} から強制退室されました service.gui.CHAT_ROOM_USER_QUIT={0} が終了しました service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=メッセージ送信が禁止されています(音声は削除されました) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=今後の為にチャットルームを保存 -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=保存済チャットルームのリストから選択したルームを削除 service.gui.CHAT_ROOM_NAME=チャットルーム名 service.gui.CLEAR_CUSTOM_MESSAGES=カスタムメッセージをクリア service.gui.ROOM_NAME=チャットルーム -service.gui.AUTOJOIN=自動参加 service.gui.CHANGE_PASSWORD=パスワードを変更 service.gui.CHAT_ROOM_NAME_INFO=下のフィールドに作成したいチャットルーム名を入力して下さい。 service.gui.CHAT_ROOM_NOT_EXIST=サーバ: {1} にチャットルーム: {0} が見つかりませんでした。入力したルーム名をご確認ください。 service.gui.CHAT_ROOM_NOT_CONNECTED=チャットルーム: {0} に参加するためにはログインしている必要があります。 service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=チャットルームに去るためにはログインしている必要があります。 -service.gui.CHAT_ROOM_NOT_JOINED=チャットルームを操作するためにはそのルームに参加している必要があります。 service.gui.CHAT_ROOM_OPTIONS=チャットルームオプション service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=チャットルーム: {0} に参加するには登録が必要です。 service.gui.CHAT_ROOM_REQUIRES_PASSWORD=チャットルーム: {0} はパスワードを要求しました。 @@ -144,27 +144,24 @@ service.gui.CHOOSE_NUMBER=番号を選択 service.gui.CHOOSE_ACCOUNT=アカウント一覧から選択してください。 service.gui.CITY=市(区町村) service.gui.COUNTRY=国 -service.gui.SHOW_MORE_TOOLTIP=より詳細はクリック +service.gui.SHOW_MORE_TOOLTIP=更に詳細を表示するにはクリック service.gui.CLEAR=テキストを消去 service.gui.CLOSE=閉じる (&o) service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=2秒以内に新しいメッセージを受け取っています。本当にこのチャットを閉じますか? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=転送中のファイルがあります。これらをキャンセルしてもいいですか? -service.gui.CONFIRM=確認 service.gui.CONNECTED_STATUS=接続済み service.gui.CONNECTING=接続... service.gui.CONNECTING_STATUS=接続... service.gui.CONNECTING_EARLY_MEDIA_STATUS=接続... service.gui.CONNECTION=接続... -service.gui.CONNECTION_FAILED_MSG=次のアカウントで接続に失敗しました: ユーザ名: {0}, サーバ名: {1}. ネットワーク接続をご確認、もしくは、ネットワーク管理者に問い合わせてください。 service.gui.CONNECTION_EXPIRED_MSG=現在サーバ {0} とは接続していません。 service.gui.CONTACT_NAME=ID または番号 -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=選択した問い合わせ先 {0} は電話を受け付けていません。 +service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=選択した問い合わせ先 {0} は電話を受け付けていません。 service.gui.CONTACT_PAUSED_TYPING={0} はメッセージ入力を休止しています service.gui.CONTACT_TYPING={0} はメッセージを入力しています service.gui.CONTACT_TYPING_SEND_FAILED=おっと、今入力中なので {0} に通話できませんでした。 service.gui.CONTACT_INFO=問い合わせ情報 (&C) -service.gui.CONTACTLIST=コンタクトリスト service.gui.CONTACTS=問い合わせ service.gui.COPY=コピーする (&C) service.gui.COPY_LINK=リンクをコピーする (&l) @@ -176,43 +173,47 @@ service.gui.CREATE_CHAT_ROOM_WIZARD=チャットルーム作成ウィザード service.gui.CREATE_CONFERENCE_CALL=会議通話を開始...(&C) service.gui.CREATE_GROUP=グループを作成する (&C) service.gui.CREATE_GROUP_NAME=下のフィールドに作成したいグルームの名前を入力してください。 -service.gui.CREATE_FIRST_GROUP_WIZARD=あなたのコンタクトリストはひとつもグループを含んでいません。初めにグループを作成してください。(ファイル/グループ作成) service.gui.CREATE_VIDEO_BRIDGE=新規のビデオブリッジを作成(&v) service.gui.CREATE_VIDEO_BRIDGE_MENU=新規のビデオブリッジを作成(&v) service.gui.CREATE_JOIN_VIDEO_CONFERENCE=ビデオ会議を作成/参加 service.gui.CREATE_VIDEO_CONFERENCE=このチャットルームに新しくビデオ会議を作成 -service.gui.CONTACT_INFO_NOT_SUPPORTED=この問い合わせ先はウェブ問い合わせを受け付けていません。 +service.gui.CONTACT_INFO_NOT_SUPPORTED=この連絡先はウェブ問い合わせを受け付けていません。 service.gui.CUT=カット (&u) -service.gui.DATE=日付 service.gui.DELETE=削除する service.gui.DENY=拒否(&D) service.gui.DESKTOP_SHARING_WARNING=画面共有を開始してもよろしいですか?
    OKをクリックすると、この会議に参加中の全ての人に画面が表示されます。 -service.gui.DIALPAD=ダイアルパッド +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=画面を共有します。 +service.gui.DIALPAD=あなたの画面を共有中 service.gui.DISPLAY_NAME=表示名 +service.gui.DISPLAY_NAME_PROMPT=ジェーン ドゥ service.gui.DISCONNECTED_STATUS=未接続 service.gui.DND_STATUS=着信拒否 service.gui.DO_NOT_ASK_AGAIN=次回は聞かない -service.gui.DO_NOT_SHOW_AGAIN=次回はこのメッセージを表示しない -service.gui.DOWNLOAD_NOW=すぐにダウンロード(&D) +service.gui.DO_NOT_SHOW_AGAIN=次回よりこのメッセージを表示しない service.gui.DRAG_FOR_SHARING=なんでも共有したいものをここにドラッグ... service.gui.DURATION=期間 +service.gui.DESTROY_CHATROOM=チャットルームを削除する +service.gui.DESTROY_MESSAGE=他の参加者に通知するには、その理由と参加する代替チャットルームアドレスを入力してください。 service.gui.EDIT=編集する (&E) -service.gui.EMAIL=電子メール: -service.gui.EMAILS=電子メール: -service.gui.EMPTY_HISTORY=ヒストリを消去する (&E) +service.gui.EDITED_AT={0}で編集 +service.gui.EMAIL=Email +service.gui.EMAILS=Email +service.gui.EMPTY_HISTORY=履歴がありません +service.gui.ENABLE_DESKTOP_REMOTE_CONTROL=リモートデスクトップアプリを有効にする +service.gui.ENABLE_TYPING_NOTIFICATIONS=チャット入力中の状態を外部の人に知らせる(チャットアクティビティを送信) +service.gui.END_CONFERENCE=会議を終了する service.gui.ENTER_PHONE_NUMBER=電話番号を入力してください -service.gui.ENTER_NAME_OR_NUMBER=名前か番号で呼び出し +service.gui.ENTER_NAME_OR_NUMBER=名前もしくは番号を入力 service.gui.ERROR=エラー service.gui.ERROR_WAS=エラーです:{0} service.gui.ERROR_RECEIVED_FROM={0} からエラーを受け取りました service.gui.ESTIMATED_TIME=残り時間: service.gui.EVENTS=イベント service.gui.EXIT=終了 (&x) -service.gui.EXTENDED_CRITERIA=拡張条件 service.gui.GENERAL=一般 service.gui.GENERAL_ERROR=一般エラー service.gui.GROUP_NAME=グループ名 -service.gui.FAILED_STATUS=コールに失敗しました +service.gui.FAILED_STATUS=コール失敗 service.gui.FAILED_TO_JOIN_CHAT_ROOM={0} というチャットルームに参加できませんでした。 service.gui.FAX=Fax service.gui.FFC_STATUS=自由にチャットできます @@ -229,17 +230,19 @@ service.gui.FILE_SEND_FAILED=ファイル送信に失敗しました: {0} service.gui.FILE_TOO_BIG=このプロトコルで送信できるファイル最大サイズを越えています: {0} service.gui.FILE_SEND_REFUSED={0} からこのファイルが拒否されました。 service.gui.FILE_TRANSFER_REFUSED=ファイル転送が拒否されました。 -service.gui.FILE_TRANSFER_NOT_SUPPORTED=選択した連絡先は、ファイル転送をサポートしていません。 +service.gui.FILE_TRANSFER_NOT_SUPPORTED=選択された連絡先は、ファイル転送に対応していません。 +service.gui.FILE_TRANSFER_PREPARING={0}にファイル送信準備中。しばらくお待ちください・・・ service.gui.FILE_TRANSFER_REQUEST_RECIEVED={0}があなたとファイルを共有中 service.gui.FILE_DOES_NOT_EXIST=指定のファイルは見つかりませんでした。削除されたか、移動されました。 service.gui.FILE_OPEN_FAILED=ファイルを開けませんでした。削除されたか、移動されました。 -service.gui.FILE_OPEN_NOT_SUPPORTED=申し訳ございませんが、このプラットフォームでは、ファイルを開く操作はサポートされていません。 +service.gui.FILE_OPEN_NOT_SUPPORTED=申し訳ございません。このプラットフォームでは、ファイルを開く操作に対応していません。 service.gui.FILE_OPEN_NO_PERMISSION=このファイルを開く権限がありません。権限を確認の上、再度試してください。 service.gui.FILE_OPEN_NO_APPLICATION=このファイルタイプに関連づけられたアプリケーションが見つかりませんでした。 -service.gui.FINISH=仕上げる (&F) +service.gui.FINISH=終了する service.gui.FOLDER_DOES_NOT_EXIST=このファイルを入れたフォルダが見つかりませんでした。削除されたか、移動されています。 service.gui.FOLDER_OPEN_FAILED=フォルダーを開けませんでした service.gui.FOLDER_OPEN_NO_PERMISSION=このフォルダを開く権限がありませんでした。権限を確認の上、再度試してください。 +service.gui.FOLDER_OPEN_NO_APPLICATION=このフォルダを開くアプリケーションが見つかりませんでした。 service.gui.FONT=フォント service.gui.FONT_BOLD=ボールド service.gui.FONT_COLOR=色 @@ -247,7 +250,12 @@ service.gui.FONT_FAMILY=ファミリー service.gui.FONT_ITALIC=斜体 service.gui.FONT_SIZE=サイズ service.gui.FONT_STYLE=スタイル -service.gui.FONT_UNDERLINE=アンダーライン +service.gui.FONT_UNDERLINE=下線 +service.gui.GRANT_OWNERSHIP=所有権保有中… +service.gui.GRANT_ADMIN=管理権保有中… +service.gui.GRANT_MODERATOR=議長権保有中… +service.gui.GRANT_MEMBERSHIP=メンバー権保有中… +service.gui.GRANT_VOICE=音声を許可 service.gui.GUEST=ゲスト service.gui.HANG_UP=切断 service.gui.HD_QUALITY=HDビデオ @@ -268,7 +276,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=ローカルに保存されているメ service.gui.HISTORY_REMOVE_ERROR=ローカルに保存されているメッセージの削除に失敗しました。 service.gui.HOME=ホーム service.gui.HOME_PAGE=ホームページ -service.gui.HOUR=時間 service.gui.ICE=ICE service.gui.IDENTIFIER=識別子 service.gui.IGNORE=無視する (&I) @@ -276,53 +283,58 @@ service.gui.INSERT_SMILEY=スマイリーを挿入 service.gui.INCOMING_CALL=次のところから着信: {0} service.gui.INCOMING_SCREEN_SHARE=次のところから画面共有が着信: {0} service.gui.INCOMING_CALL_STATUS=着信中です +service.gui.INCOMING_SCREEN_SHARE_STATUS=画面共有が着信中 +service.gui.INSTANT_MESSAGINGS=インスタントメッセンジャー +service.gui.IM=インスタントメッセージ +service.gui.INITIATING_CALL_STATUS=コール開始 service.gui.INVITATION=招待文 service.gui.INVITATION_RECEIVED=招待を受けました service.gui.INVITATION_RECEIVED_MSG={0} はチャットルーム: {1} にあなたを招待しました。この招待を受け入れるか、拒否するか、無視することができます。 +service.gui.INVITATION_REJECTED={0}はあなたの招待を拒否しました。理由:{1}. service.gui.INVITE=招待 (&I) service.gui.INVITE_CONTACT_MSG=この会話に追加したいコンタクトを選択して、招待のボタンをクリックしてください。 service.gui.INVITE_CONTACT_TO_CHAT=コンタクトをチャットに招待 -service.gui.INVITE_CONTACT_TO_CALL=コンタクトをチャットに招待 +service.gui.INVITE_CONTACT_TO_CALL=連絡先を招待 service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=連絡先をビデオブリッジに招待 service.gui.INVITE_REASON=招待理由 -service.gui.IS_CALLING=コール中... +service.gui.IS_CALLING={0}がコール中... service.gui.IS_NOW={0} は現在 {1} です。 -service.gui.JITSI_WARNING=SIPコミュニケーターは、Jitsiに名称変更されました。
    今後、最新バージョンに更新する場合は、Jitsiをダウンロードするようにしてください。

    ご迷惑をお掛けして申し訳ございません。

    Jitsi開発チーム -service.gui.JITSI_WARNING_TITLE=SIPコミュニケーターは、Jitsiになりました。 service.gui.JOIN=参加する (&J) service.gui.JOIN_AS=として参加 (&o) service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=会議中のビデオ会議に参加 service.gui.JOIN_VIDEO=ビデオに参加 -service.gui.CLOSE_CHAT_ROOM_DIALOG=閉じる (&o) service.gui.JOB_TITLE=肩書き service.gui.JOIN_CHAT_ROOM=チャットに参加する... (&J) service.gui.JOIN_CHAT_ROOM_TITLE=チャットに参加 service.gui.JOIN_CHAT_ROOM_NAME=参加したいチャットルームを入力してください。 service.gui.JOIN_CHAT_ROOM_WIZARD=チャットルーム参加ウィザード service.gui.JOIN_AUTOMATICALLY=自動的に参加 +service.gui.DONT_JOIN_AUTOMATICALLY=自動的に参加しない service.gui.KICK=キック (&K) service.gui.KICK_FAILED=キックできませんでした service.gui.KICK_FAILED_GENERAL_ERROR=コンタクト: {0} をキックできませんでした。一般サーバエラーが発生しました。 service.gui.KICK_FAILED_NOT_ALLOWED=コンタクト: {0} をキックできませんでした。ルームのオーナーと管理者はキックできません。 service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=コンタクト: {0} をキックできませんでした。権限がありません。 -service.gui.LAST=最終 -service.gui.LAST_NAME=姓: +service.gui.LAST_NAME=姓 service.gui.LEAVE=去る (&L) service.gui.LIMIT_REACHED_FOR_IP=ローカルのIPアドレスから登録が多すぎるのです。サーバー: {0} は登録をオープンすることができません。 -service.gui.LIST=最終 +service.gui.LIST=リスト +service.gui.LOADING_ROOMS=部屋を読込中… +service.gui.LOADING=読込中… +service.gui.LOCALLY_ON_HOLD_STATUS=保留中 service.gui.LOGIN_NETWORK_ERROR=
    ネットワークに障害があったため、アカウント:
    ユーザ名: {0}
    サーバ名: {1}
    でログインできませんでした。ネットワーク接続性を確認してください。
    service.gui.LOGIN_GENERAL_ERROR=ユーザ名: {0}, サーバ名: {1} でログインしようとしたところエラーが発生しました。 service.gui.LOGIN_INTERNAL_ERROR=アプリケーション内部エラーのため、ユーザ名: {0}, サーバ名: {1} でログインに失敗しました。お手数ですが、問題を dev@sip-communicator.dev.java.net までご報告ください。 service.gui.LOGIN_INVALID_PROPERTIES_ERROR=アカウント設定に問題があるため、ユーザ名: {0}, サーバ名: {1} でログインできませんでした。アカウント設定をご確認ください。 service.gui.LOGOFF_NOT_SUCCEEDED=ユーザ名: {0}, サーバ名: {1} でログオフ中にエラーが発生しました。 +service.gui.LOW_QUALITY=低品質 service.gui.MEMBER=メンバー service.gui.MERGE_TO_CALL=全ての通話を統合 service.gui.MESSAGE=メッセージ service.gui.MISSED_CALLS_TOOL_TIP=次のところから不在着信: service.gui.MISSED_CALLS_MORE_TOOL_TIP= {0} からも service.gui.MODERATOR=司会者 -service.gui.MORE=もっと見る -service.gui.MORE_LABEL=移動 +service.gui.MORE_LABEL=もっと service.gui.MOVE=移動 service.gui.MOVE_SUBCONTACT=コンタクトを移動 (&o) service.gui.MOVE_SUBCONTACT_MSG=選択した連絡先を移動したい、連絡先かグループを選択してください。 @@ -330,16 +342,21 @@ service.gui.MOVE_SUBCONTACT_FAILED=選択したコンタクトは移動元のコ service.gui.MOVE_SUBCONTACT_QUESTION=
    {0} {1} に移動しますか?
    service.gui.MOVE_TO_GROUP=グループに移動する (&M) service.gui.MOVE_CONTACT=コンタクトを移動 -service.gui.MOVE_CONTACT_ERROR=このコンタクトは移動出来ません (&C) service.gui.MSG_DELIVERY_FAILURE=上記のメッセージは配送できませんでした -service.gui.MSG_DELIVERY_NOT_SUPPORTED=あなたが使っているプロトコルはオフラインメッセージをサポートしていません。他のプロトコルを使ってコンタクトするか、オンラインになるまでお待ちください。 +service.gui.MSG_DELIVERY_NOT_SUPPORTED=あなたが使っているプロトコルはオフラインメッセージに対応していません。他のプロトコルを使ってコンタクトするか、オンラインになるまでお待ちください。 service.gui.MSG_DELIVERY_INTERNAL_ERROR=内部エラーが発生しました:{0}。次のサイトにて問題を報告してください: http://www.sip-communicator.org/index.php/Development/BugsAndIssues service.gui.MSG_DELIVERY_ERROR=メッセージ送信に失敗しました。 service.gui.MSG_DELIVERY_UNKNOWN_ERROR=メッセージ送信中に不明なエラーが発生しました。 -service.gui.MSG_NOT_POSSIBLE=そのコンタクトとメッセージングができません(プロトコルによってサポートされていません) +service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION=サポートされていない操作です +service.gui.MSG_NOT_DELIVERED=ネットワーク問題が発生しました。ネットワーク状況を確認し再度行ってください。 +service.gui.MSG_NOT_POSSIBLE=この連絡先とはメッセージできません(プロトコルに対応していません) service.gui.MSG_RECEIVED={0} はあなたにメッセージを送りました service.gui.MSG_SEND_CONNECTION_PROBLEM=メッセージを送るためにはオンラインである必要があります。 service.gui.MULTIPLE_LOGINS=同じアカウントで複数回ログインしました。アカウント ユーザ名: {0}, サーバ名: {1} は現在未接続です。 +service.gui.MY_CHAT_ROOMS=チャットルームに参加 +service.gui.MY_CHAT_ROOMS_TITLE=チャットルームに参加 +service.gui.MUTUALLY_ON_HOLD_STATUS=相互保留中 +service.gui.NAME=名前 service.gui.NETWORK=ネットワーク service.gui.NETWORK_FAILURE=ネットワーク障害 service.gui.NEXT=次 (&N) @@ -352,34 +369,73 @@ service.gui.NICKNAME=ニックネーム service.gui.NO=いいえ service.gui.NONE=使用しない service.gui.NO_CAMERA_AVAILABLE=利用可能なカメラがありません。 -service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=このプロトコルでは、デスクトップ共有がサポートされていません。 +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=このプロトコルでは、デスクトップ共有に対応していません。 service.gui.NO_VIDEO_ENCODINGS=設定でビデオエンコードが選択されていません。 -service.gui.NO_VIDEO_FOR_PROTOCOL=このプロトコルでは、ビデオはサポートされていません。 +service.gui.NO_VIDEO_FOR_PROTOCOL=このプロトコルは、映像に対応していません。 service.gui.NO_AVAILABLE_ROOMS=このサーバのルームリストは現在利用出来ません。 service.gui.NO_CONTACTS_FOUND=連絡先の検索結果はありません。{0} を呼びだすには、Ctrl+Enterを押すか、下のボタンを使用してください。 service.gui.NO_CONTACTS_FOUND_SHORT=連絡先の検索結果はありません。 service.gui.NO_MESSAGE=メッセージがありません service.gui.NO_GROUP_CHAT_ACCOUNT_AVAILABLE=複数ユーザチャットが利用可能なアカウントがありません。複数ユーザチャットに対応したプロトコルについては、sip-communicator.org をご確認ください。 +service.gui.NO_ONLINE_CONFERENCING_ACCOUNT=会議通話に利用できるアカウントがありません。会議通話に使用できるプロトコルの詳細な情報を https://jitsi.org で確認してください。 +service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=音声通話するためには、少なくとも1つはオンラインの通話アカウントが必要です。通話用のアカウントにログインして、再試行してください。 +service.gui.NOT_AUTHORIZED=許可されません service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=未送信のメッセージがあるチャットを閉じようとしています。本当にこのチャットを閉じますか? service.gui.NON_EXISTING_USER_ID=サーバ {0} には指定されたユーザIDが存在しません。 +service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=コンタクトリストにありません +service.gui.SD_QUALITY=品質:通常 service.gui.OFFLINE=オフライン service.gui.OK=OK (&O) -service.gui.OLDER_CALLS=以前のコール service.gui.ONLINE=オンライン +service.gui.OPEN=開く +service.gui.OPEN_FILE_FROM_IMAGE=ダブルクリック:ファイルを開く +service.gui.OPEN_FOLDER=フォルダを開く service.gui.OPEN_IN_BROWSER=ブラウザを開く (&b) service.gui.OPTIONS=オプション +service.gui.OPEN_AUTOMATICALLY=メッセージのみ開く +service.gui.OPEN_ON_ACTIVITY=アクティビティを開く +service.gui.OPEN_ON_MESSAGE=メッセージのみ開く +service.gui.OPEN_ON_IMPORTANT_MESSAGE=重要なメッセージのみ開く +service.gui.OR=または +service.gui.ORGANIZATION=組織 +service.gui.OTHER=その他 +service.gui.chat.role.OWNER=所有者 service.gui.chat.role.ADMINISTRATOR=管理者 +service.gui.chat.role.MODERATOR=司会者 +service.gui.chat.role.MEMBER=メンバー +service.gui.chat.role.GUEST=ゲスト +service.gui.chat.role.SILENT_MEMBER=サイレントメンバー +service.gui.chat.role.OUTCAST=参加禁止 +service.gui.OWNER=部屋の所有者 +service.gui.ON_MOBILE_TOOLTIP=モバイル service.gui.PASSWORD=パスワード +service.gui.PASSWORD_CHANGE_FAILURE=パスワード変更に失敗しました +service.gui.PASSWORD_CHANGE_SUCCESS=パスワードが変更されました service.gui.PASTE=貼付け (&P) +service.gui.PERSONAL=個人的な +service.gui.PORT=ポート +service.gui.POSTAL_CODE=郵便番号 +service.gui.PREFERENCES=環境設定 +service.gui.PREFIX=プレフィックス +service.gui.PRESENCE=出席 +service.gui.PRESS_ENTER_FOR_SUGGESTIONS=提案 +service.gui.PRESS_FOR_CALL_INFO=通話情報 +service.gui.PRESS_TO_OPEN_CRM=CRMアプリを開く service.gui.PREVIOUS=前 -service.gui.PREVIOUS_TOOLTIP=過去の会話を表示する service.gui.PRINT=印刷 (&P) service.gui.PROACTIVE_NOTIFICATION=がメッセージを入力しています +service.gui.PROBLEMS_ENCOUNTERED=問題が発生しました service.gui.PROTOCOL=プロトコル +service.gui.PUT_OFF_HOLD=保留解除 +service.gui.PUT_ON_HOLD=保留 service.gui.QUIT=終了 (&Q) +service.gui.READY=準備 +service.gui.RECENT_MESSAGES=最近の会話 service.gui.REASON=理由 +service.gui.RECEIVED={0}が受け取りました service.gui.RECONNECTION_LIMIT_EXCEEDED=サーバへの再接続が切断から短すぎました。アカウント ユーザ名: {0}, サーバ名: {1} は一時的に拒否されました。しばらく間を置いて再接続してください。 service.gui.RE_REQUEST_AUTHORIZATION=承認を要求 (&R) +service.gui.REFERRED_STATUS=照会 service.gui.REJECT=拒否 (&R) service.gui.REMEMBER_PASSWORD=パスワードを記録する service.gui.REMOVE=取り除く (&R) @@ -387,77 +443,158 @@ service.gui.REMOVE_ACCOUNT=アカウントを取り除く (&R) service.gui.REMOVE_ACCOUNT_MESSAGE=本当にこのアカウントを取り除きますか? service.gui.REMOVE_CONTACT=サブコンタクトを取り除く (&R) service.gui.REMOVE_CONTACT_TEXT=
    本当に {0} をコンタクトリストから
    取り除きますか?
    +service.gui.REMOVE_CONTACT_NOT_CONNECTED=このコンタクトを取り除くにはログインが必要です。ログインしてやり直してください。 service.gui.REMOVE_GROUP=グループを取り除く (&R) +service.gui.REMOTELY_ON_HOLD_STATUS=リモートが保留中 service.gui.RENAME=名前を変更 (&R) service.gui.RENAME_CONTACT=コンタクトの名前を変更 (&n) service.gui.RENAME_CONTACT_WIZARD=指定したコンタクトに対して利用する名前を下のフィールドに入力してください。 service.gui.RENAME_GROUP=グループの名前を変更 (&n) service.gui.RENAME_GROUP_INFO=指定したグループに対して利用する名前を下のフィールドに入力してください。 +service.gui.RENAME_CLEAR_USER_DEFINED=復元 +service.gui.RINGING_STATUS=呼び出し中 service.gui.REQUEST=要求 (&R) service.gui.REQUEST_AUTHORIZATION=承認を要求 (&R) service.gui.REQUEST_AUTHORIZATION_MSG=承認が必要なため、{0} をコンタクトリストに追加できませんでした。次に承認要請を入力してください。 service.gui.RETRY=再試行 -service.gui.ROOT_GROUP=ルートグループ +service.gui.REVOKE_OWNERSHIP=所有権を取り消す +service.gui.REVOKE_ADMIN=管理者を取り消す +service.gui.REVOKE_MODERATOR=司会者を取り消す +service.gui.REVOKE_MEMBERSHIP=メンバーを取り消す +service.gui.REVOKE_VOICE=音声を取り消す service.gui.SAVE=保存 (&S) service.gui.SEARCH=検索 (&S) service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=選択したサーバに存在するチャットルームを表示するには下のボタンをクリックしてください。そして、参加したいチャットルームを選択し「参加」ボタンをクリックしてください。 -service.gui.SELECT_ACCOUNT=アカウントを選択 +service.gui.SEARCH_STRING_CONTACT_SOURCE=コンタクトをさがす +service.gui.SECURITY=セキュリティ service.gui.SELECT_COLOR=色を選択する service.gui.SELECT_GROUP=グループ選択 -service.gui.SELECT_GROUP_WIZARD_MSG=次のリストはあなたのコンタクトリストに含まれるグループのリストです。新しいコンタクトを追加したいグループを選択してください。 -service.gui.SELECT_GROUP_WIZARD=グループ指定 +service.gui.SELECT_NO_GROUP=グループがありません service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=次のリストは複数ユーザチャット機能をサポートするアカウントのリストです。チャットルームを作成に使用したいアカウントを選択してください。 -service.gui.SELECT_PROVIDERS_WIZARD_MSG=次のリストは登録しているすべてのアカウントのリストです。新しいコンタクトと通信するのに利用したいアカウントを選択してください。 -service.gui.SELECT_PROVIDERS_WIZARD=アカウント選択 +service.gui.SELECT_VIDEO_CONFERENCE=ビデオ会議を選択する +service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=リストからチャットルームを選択し、OKで追加する service.gui.SEND=送る (&S) service.gui.SEND_FILE=ファイルを送る (&f) -service.gui.SELECT_CONTACT_SUPPORTING_INFO=このコンタクトに関する情報がありません。 service.gui.SEND_MESSAGE=メッセージを送る (&S) -service.gui.SEND_AS_SMS=SMSとして送る +service.gui.SEND_PRIVATE_MESSAGE=プライベートメッセージを送信 service.gui.SEND_SMS=SMSを送る (&e) service.gui.SEND_SMS_DETAILS=国際通話の形式で番号を入力する必要があります 例えば、イギリスの場合 +44 で始まり、+447777000000 となります。 -service.gui.SEND_SMS_NOT_SUPPORTED=選択したプロトコルはSMSメッセージをサポートしていません。 +service.gui.SEND_SMS_NOT_SUPPORTED=選択したプロトコルはSMSメッセージに対応していません。 +service.gui.SMS=SMS +service.gui.SEND_VIA=経由して送る +service.gui.SENT=送信 +service.gui.SERVER_CHAT_ROOMS=チャットルームサーバー +service.gui.SET_GLOBAL_STATUS=グローバルステータスの設定 service.gui.SET_STATUS_MESSAGE=状態メッセージを設定 +service.gui.SET_SUBJECT=件名を設定 service.gui.SETTINGS=設定 (&S) +service.gui.SHARE_DESKTOP=画面共有 +service.gui.SHARE_DESKTOP_WITH_CONTACT=コンタクト先とデスクトップ共有 +service.gui.SHARE_FULL_SCREEN=フルスクリーン +service.gui.SHARE_REGION=領域共有 +service.gui.SHOW=表示 +service.gui.SHOW_CONTACT_LIST_TOOL_TIP=表示を履歴からコンタクトリストへ切り替えるにはこちらをクリック +service.gui.SHOW_MORE=更に見せる service.gui.SHOW_OFFLINE_CONTACTS=オフラインのコンタクトを表示 +service.gui.SIGN_IN=サインイン service.gui.SMS_SUCCESSFULLY_SENT=SMSメッセージが送信できました! service.gui.SMS_SEND_CONNECTION_PROBLEM=SMSメッセージを送信するにはSMSプロバイダアカウントに接続している必要があります。 service.gui.SPECIFY_REASON=下のフィールドにこの操作の理由を指定できます。 +service.gui.SPECIFY_SERVER=アカウントのサーバー部分を指定してしてください。 +service.gui.SOUND_OFF=音をオフにする +service.gui.SOUND_ON=音をオンにする +service.gui.START_SHARING=シェア開始 +service.gui.STATUS=ステータス service.gui.STATUS_CHANGED_CHAT_MESSAGE={0} になりました service.gui.STATUS_CHANGE_GENERAL_ERROR=一般エラーのため、次のアカウントの状態を変更できませんでした: ユーザ名 {0}, サーバ名 {1}. service.gui.STATUS_CHANGE_NETWORK_FAILURE=ネットワークに問題があるため、次のアカウントの状態を変更できませんでした: ユーザ名 {0}, サーバ名 {1}. service.gui.STATUS_MESSAGE_INFO=下のフィールドにあなたが使いたい新しいメッセージを指定できます。 +service.gui.STOP_SHARING=シェア停止 +service.gui.STREET=ストリート service.gui.SUBJECT=件名 service.gui.SUMMARY=概要 -service.gui.TODAY=今日 +service.gui.TELEPHONY=通話方式 service.gui.TOOLS=ツール (&T) service.gui.TRANSFER=転送 (&f) -service.gui.TO=へ: (&T) +service.gui.TO=転送したい連絡先の名前を選択、転送します。 +service.gui.TRANSFER_CALL_MSG=転送したい連絡先の名前を選択し、転送をクリックします。 service.gui.TRANSFER_CALL_TITLE=コールを転送 +service.gui.TRANSFER_CALL_TO=へ転送 service.gui.TRANSPARENCY_NOT_ENABLED=透明性を現在の構成でサポートされません。 service.gui.TYPE_YOUR_REQUEST=あなたの要求をここに入力してください +service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=この通話ではビデオの品質を変更できませんでした。 service.gui.USER_IDENTIFIER=ユーザID: service.gui.USER_EXISTS_ERROR=このユーザーは既に選択されたネットワークに存在する。ほかのユーザーまたはネットワークを選択してください。 +service.gui.USERNAME_NULL=ユーザーネームとパスワードを入力してください +service.gui.WEBPAGE=ウェブサイトを開く service.gui.ACCOUNT_CREATION_FAILED=アカウントを作成出来ませんでした: {0} service.gui.UNKNOWN=不明なユーザ +service.gui.UNKNOWN_STATUS=不明な状態 service.gui.UNREGISTERED_MESSAGE=次のアカウントに接続できませんでした: ユーザ名: {0}, サーバ名: {1}。あなたは現在オフラインです。 +service.gui.USE_PROVISIONING=オンライン設定を利用 +service.gui.VALUE=値 +service.gui.VIDEO_CALL=&ビデオ通話 +service.gui.VIA=経由 service.gui.VIEW=表示する (&V) service.gui.VIEW_HISTORY=履歴を表示 (&h) +service.gui.VIEW_SMILEYS=ビュー&スマイリー service.gui.VIEW_TOOLBAR=ツールバーを見る (&t) +service.gui.VIEW_SIMPLE_CHAT_THEME=シンプルチャットテーマビュー +service.gui.VOICEMAIL_NEW_URGENT_OLD_RECEIVED=新しい {0} (急ぎ {1}) と 古いメッセージ {2} +service.gui.VOICEMAIL_NEW_URGENT_RECEIVED=新しい {0} (急ぎ {1}) と メッセージ {2} +service.gui.VOICEMAIL_NEW_OLD_RECEIVED=新しい {0} と 古いメッセージ {1} +service.gui.VOICEMAIL_NEW_RECEIVED={0}新しいメッセージ +service.gui.VOICEMAIL_OLD_RECEIVED={0}前のメッセージ service.gui.VOICEMAIL_NO_MESSAGES=メッセージがありません +service.gui.VOICEMAIL_TITLE=音声メッセージ +service.gui.VOICEMAIL_TOOLTIP=から音声メッセージ +service.gui.VOICEMAIL_TIP=メッセージを聞くにはコールボタンを押してください +service.gui.VOICEMAIL_TIP_NO_ACCOUNT=アカウントウィザード中に ボイスメールをチェックする URI を設定してください +service.gui.VOLUME_CONTROL_TOOL_TIP=音量を調節する +service.gui.WAITING_AUTHORIZATION=承認待機中 service.gui.WARNING=警告 service.gui.YES=はい -service.gui.YESTERDAY=昨日 -service.gui.EXISTING_ACCOUNT_ERROR=入力したアカウントが既にインストールされている。 +service.gui.NEW_GMAIL_HEADER=あなたの {0} 受信箱:
    に新しいメッセージが届いています:
    +service.gui.NEW_GMAIL_MANY_HEADER=あなたの {0} 受信箱 に {2} 通のメッセージが届いています:
    +service.gui.NEW_GMAIL_FOOTER=受信箱 に未読の会話があります。
    +service.gui.NEW_GMAIL_MANY_FOOTER=受信箱 に {1}つの未読の会話があります。
    +service.gui.ACTIVATE=承認 +service.gui.DEACTIVATE=無効化 +service.gui.NEW=新 service.gui.ENTER_FULL_SCREEN_TOOL_TIP=フルスクリーン service.gui.EXIT_FULL_SCREEN_TOOL_TIP=フルスクリーン +service.gui.HOLD_BUTTON_TOOL_TIP=保留切り替え +service.gui.MUTE_BUTTON_TOOL_TIP=保留を切り替えるか、マイク音量調整ボタンを押す +service.gui.PARK=パーク保留 +service.gui.PARKING_SLOT=パーク保留枠: +service.gui.PARK_BUTTON_TOOL_TIP=呼び出しをパーク保留 +service.gui.RECORD_BUTTON_TOOL_TIP=記録を調整する +service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=映像を調節する +service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=映像の表示/非表示 +service.gui.SHOW_HIDE_PEERS_TOOL_TIP=参加者リストの表示/非表示 service.gui.TRANSFER_BUTTON_TOOL_TIP=転送電話 +service.gui.TRANSFER_TO=へ移す service.gui.SECURITY_INFO=セキュリティ情報 service.gui.SECURITY_WARNING=セキュリティ警告 service.gui.SECURITY_ERROR=セキュリティエラー -service.gui.PHONE=電話番語: -service.gui.PHONES=電話番語: - +service.gui.SPEED=スピード: +service.gui.SILENT_MEMBER=無音の参加者 +service.gui.NON_SECURE_CONNECTION=アカウント {0} では安全を確保して接続できません。暗号化されていない接続でもよい場合は、アカウント設定で "暗号化されていない接続を許可" にチェックしてください。 +service.gui.MOBILE_PHONE=モバイル +service.gui.VIDEO_PHONE=映像 +service.gui.WORK_PHONE=会社 +service.gui.PHONE=電話番語 +service.gui.PHONES=電話番号 +service.gui.EDIT_NOT_SUPPORTED=アカウント編集に対応していません。 +service.gui.SHOW_PREVIEW=(プレビュー表示) +service.gui.SHOW_PREVIEW_WARNING_DESCRIPTION=このイメージを表示し続けますか?このイメージではあなたを特定することができないため、特定可能なイメージ/映像を検討してください。 +service.gui.SHOW_PREVIEW_DIALOG_TITLE=イメージ表示/映像プレビュー + +service.gui.ZID_NAME_SET=ZRTP識別子: +service.gui.ZID_NAME_NOT_SET=ZRTP識別子が設定されていません。 +service.gui.ZID_NAME_BUTTON=クリックしてZRTP識別名を設定する。 +service.gui.ZID_NAME_DIALOG=ZRTP識別子を編集 +service.gui.ZID_NAME_UNEXPECTED=ZRTP識別子が見つかりません。
    service.gui.JANUARY=1月 service.gui.FEBRUARY=2月 @@ -472,23 +609,129 @@ service.gui.OCTOBER=10月 service.gui.NOVEMBER=11月 service.gui.DECEMBER=12月 - - - +service.gui.callinfo.TECHNICAL_CALL_INFO=技術的な通話の情報 +service.gui.callinfo.CALL_INFORMATION=通話情報 +service.gui.callinfo.CALL_IDENTITY=アイデンティティ +service.gui.callinfo.PEER_COUNT=参加者数 +service.gui.callinfo.IS_CONFERENCE_FOCUS=会議の焦点 +service.gui.callinfo.CALL_DURATION=通話時間 +service.gui.callinfo.TLS_PROTOCOL=TLS プロトコル +service.gui.callinfo.TLS_CIPHER_SUITE=TLS 暗号化方式 +service.gui.callinfo.TLS_CERTIFICATE_CONTENT=TLSサーバー証明書の内容は下記に表示しています。 +service.gui.callinfo.VIEW_CERTIFICATE=証明書を表示 +service.gui.callinfo.CODEC=コーデック / サンプリングレート +service.gui.callinfo.NA=該当なし +service.gui.callinfo.VIDEO_SIZE=映像サイズ +service.gui.callinfo.AUDIO_INFO=音声情報 +service.gui.callinfo.VIDEO_INFO=映像情報 +service.gui.callinfo.LOCAL_IP=ローカルIP / ポート +service.gui.callinfo.REMOTE_IP=リモートIP / ポート +service.gui.callinfo.BANDWITH=帯域 +service.gui.callinfo.LOSS_RATE=速度低下 +service.gui.callinfo.RTT=RTT +service.gui.callinfo.JITTER=Jitter +service.gui.callinfo.MEDIA_STREAM_TRANSPORT_PROTOCOL=メディアストリームトランスポートプロトコル +service.gui.callinfo.MEDIA_STREAM_RTP=RTP +service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP +service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Key exchangeプロトコル +service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE candidate拡張型 +service.gui.callinfo.ICE_STATE=ICE 処理状態 + +#enum values from IceProcessingState +service.gui.callinfo.ICE_STATE.WAITING=candidatesをまとめる +service.gui.callinfo.ICE_STATE.RUNNING=接続性確認 +service.gui.callinfo.ICE_STATE.COMPLETED=成功 +service.gui.callinfo.ICE_STATE.FAILED=失敗 + +service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=ローカルホストIP / ポート +service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=ローカルループバック IP/ポート +service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=ローカル中継 IP/ポート +service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=リモートホスト IP / ポート +service.gui.callinfo.ICE_REMOTE_REFLEXIVE_ADDRESS=リモートループバック IP / ポート +service.gui.callinfo.ICE_REMOTE_RELAYED_ADDRESS=リモート中継 IP / ポート +service.gui.callinfo.TOTAL_HARVESTING_TIME=合計集計時間 +service.gui.callinfo.HARVESTING_TIME=集計時間 +service.gui.callinfo.DISCARDED_PERCENT=パケットは現在廃棄されています。 +service.gui.callinfo.JITTER_BUFFER_DELAY=Jitterバッファー + +service.gui.ALWAYS_TRUST=常にこの証明書を使用する +service.gui.CERT_DIALOG_TITLE=証明書を検証 +service.gui.CERT_DIALOG_DESCRIPTION_TXT={1}への接続時に {0} でサーバー証明書を
    検証できませんでした。

    証明書が信頼されていないため、自動的にサーバー証明書を検証できません。

    接続を続けますか。

    "証明書を表示" をクリックして詳細を確認してください。 +service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST= {0} でサーバー証明書を検証できませんでした。

    証明書が信頼されていないため、自動的にサーバー証明書を検証できません。

    接続を続けますか。

    "証明書を表示" をクリックして詳細を確認してください。 +service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT= {0} で相手側 {1} の証明書を検証できませんでした。

    証明書が信頼されていないため、自動的にサーバー証明書を検証できません。

    接続を続けますか。

    "証明書を表示" をクリックして詳細を確認してください。 +service.gui.CONTINUE_ANYWAY=とにかく続行する +service.gui.CERT_INFO_CHAIN=証明書チェーン: +service.gui.CERT_INFO_ISSUED_TO=発行先 + +#service.gui.CERT_INFO_ are combined from Rdn names +service.gui.CERT_INFO_CN=一般名: +service.gui.CERT_INFO_O=団体: +service.gui.CERT_INFO_C=国名: +service.gui.CERT_INFO_ST=県名: +service.gui.CERT_INFO_L=地域名: +service.gui.CERT_INFO_ISSUED_BY=発行 +service.gui.CERT_INFO_OU=部署: +service.gui.CERT_INFO_VALIDITY=有効性 +service.gui.CERT_INFO_ISSUED_ON=より開始 +service.gui.CERT_INFO_EXPIRES_ON=に終了 +service.gui.CERT_INFO_FINGERPRINTS=指紋 +service.gui.CERT_INFO_CERT_DETAILS=証明書情報 +service.gui.CERT_INFO_SER_NUM=シリアルNo. +service.gui.CERT_INFO_VER=バージョン +service.gui.CERT_INFO_SIGN_ALG=署名アルゴリズム: +service.gui.CERT_INFO_PUB_KEY_INFO=公開鍵情報 +service.gui.CERT_INFO_ALG=アルゴリズム: +service.gui.CERT_INFO_PUB_KEY=公開鍵 +service.gui.CERT_INFO_KEY_BITS_PRINT={0} ビット +service.gui.CERT_INFO_EXP=エクスポーネント +service.gui.CERT_INFO_KEY_SIZE=鍵サイズ +service.gui.CERT_INFO_SIGN=署名 +service.gui.SHOW_CERT=証明書を表示 +service.gui.HIDE_CERT=証明書を非表示 + +service.gui.AUTO_ANSWER=自動応答、呼び出し転送 +service.gui.AUTO_ANSWER_LABEL=自動応答 +service.gui.AUTO_ANSWER_ALL_CALLS=全ての呼び出し +service.gui.AUTO_ANSWER_ALERT_INFO_FIELDS=必要な呼び出しのみ。("自動応答” に "Alert-Info" が含まれている場合) +service.gui.AUTO_ANSWER_CUSTOM_FIELDS=次の項目と値の場合の呼び出し +service.gui.AUTO_ANSWER_FIELD=項目/ヘッダー: +service.gui.AUTO_ANSWER_VALUE=値: +service.gui.AUTO_ANSWER_DESCR_VLUE=全て空欄のまま +service.gui.AUTO_ANSWER_FWD_CALLS=着信転送 +service.gui.AUTO_ANSWER_VIDEO=映像 + +service.gui.security.SECURE_AUDIO=安全な映像 +service.gui.security.AUDIO_NOT_SECURED=音声は安全ではありません +service.gui.security.SECURE_VIDEO=安全な映像 +service.gui.security.VIDEO_NOT_SECURED=安全でない映像です。 +service.gui.security.CALL_SECURED_TOOLTIP=通話は安全です。詳細確認はこちらをクリック。 +service.gui.security.CALL_NOT_SECURED_TOOLTIP=安全でない通話です。 # keep the following string short +service.gui.avatar.REMOVE_ICON=現在の画像を削除する # service.gui.avatar.imagepicker service.gui.avatar.imagepicker.CANCEL=キャンセル (&C) +service.gui.avatar.imagepicker.CHOOSE_FILE=選択 +service.gui.avatar.imagepicker.CLICK=クリックとスマイル +service.gui.avatar.imagepicker.IMAGE_FILES=イメージファイル +service.gui.avatar.imagepicker.IMAGE_PICKER=画像 +service.gui.avatar.imagepicker.IMAGE_SIZE=画像サイズ +service.gui.avatar.imagepicker.RESET=リセット +service.gui.avatar.imagepicker.SET=設定 +service.gui.avatar.imagepicker.TAKE_PHOTO=写真を撮る +service.gui.security.encryption.required=暗号化してください! +service.protocol.ICE_FAILED=接続を確立できませんでした。(ICE失敗・リレーが見つかりません) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ +impl.protocol.sip.XCAP_ERROR_UNAUTHORIZED=xcapで使用するユーザー名もしくはパスワードが間違っています。理由: {0} # systray +impl.systray.SET_STATUS=ステータスを設定する +impl.systray.FAILED_TO_OPEN_ADD_CONTACT_DIALOG=コンタクト追加ダイアログを開けません。 +impl.swingnotification.POPUP_MESSAGE_HANDLER= {0}ポップアップ +impl.growlnotification.POPUP_MESSAGE_HANDLER=Growl notification # New Account Dialog impl.gui.main.account.DEFAULT_PAGE_TITLE=ネットワークを選択する @@ -498,151 +741,401 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=ネットワークを選択す # LDAP impl.ldap.GENERAL=一般 impl.ldap.EDIT=編集する (&E) -impl.ldap.REMOVE=取り除く (&R) +impl.ldap.ENABLED=有効 +impl.ldap.SERVER_NAME=サーバー名 +impl.ldap.SERVER_NAME_EXAMPLE=LDAPサーバー +impl.ldap.SERVER_HOSTNAME=ホスト名 +impl.ldap.USE_SSL=SSLを使用する +impl.ldap.AUTH_NONE=使用しない +impl.ldap.SCOPE_ONE=ひとつ impl.ldap.SAVE=保存 (&S) impl.ldap.CANCEL=キャンセル (&C) +impl.ldap.SERVER_PORT=ポート impl.ldap.PASSWORD=パスワード +impl.ldap.MAIL_FIELD_NAME=メール入力箇所 +impl.ldap.WORKPHONE_FIELD_NAME=会社の電話番号入力箇所 +impl.ldap.MOBILEPHONE_FIELD_NAME=携帯電話番号入力箇所 +impl.ldap.HOMEPHONE_FIELD_NAME=電話番号入力箇所 impl.ldap.MAIL_FIELD_EXAMPLE=電子メール: +impl.ldap.WORKPHONE_FIELD_EXAMPLE=会社の電話番号 +impl.ldap.MOBILEPHONE_FIELD_EXAMPLE=携帯電話番号 +impl.ldap.HOMEPHONE_FIELD_EXAMPLE=電話番号 + +# SIP Protocol + +#Jabber Protocol # Address book plugin +plugin.addrbook.ADDRESS_BOOKS=アドレス帳 # Google Contacts impl.googlecontacts.EDIT=編集する (&E) -impl.googlecontacts.REMOVE=取り除く (&R) +impl.googlecontacts.ENABLED=有効 impl.googlecontacts.SAVE=保存 (&S) impl.googlecontacts.CANCEL=キャンセル (&C) impl.googlecontacts.PASSWORD=パスワード # account info +plugin.accountinfo.TITLE=アカウント情報 plugin.accountinfo.DISPLAY_NAME=表示名 plugin.accountinfo.FIRST_NAME=名前: plugin.accountinfo.MIDDLE_NAME=ミドルネーム: plugin.accountinfo.LAST_NAME=姓: +plugin.accountinfo.NICKNAME=ニックネーム plugin.accountinfo.AGE=年齢: plugin.accountinfo.BDAY=誕生日: plugin.accountinfo.GENDER=性: plugin.accountinfo.CITY=市(区町村) +plugin.accountinfo.POST=郵便番号 plugin.accountinfo.COUNTRY=国 plugin.accountinfo.EMAIL=電子メール: +plugin.accountinfo.WORK_EMAIL=メールアドレス(会社): plugin.accountinfo.PHONE=電話番語: +plugin.accountinfo.WORK_PHONE=電話番号(会社): +plugin.accountinfo.MOBILE_PHONE=電話番号(携帯): plugin.accountinfo.JOB_TITLE=肩書き +plugin.accountinfo.ABOUT_ME=わたしについて: # connection info +plugin.connectioninfo.TITLE=接続情報 # contact info +plugin.contactinfo.TITLE=コンタクト詳細 +plugin.contactinfo.USER_PICTURES=ユーザーの写真 +plugin.contactinfo.USER_STATUS_MESSAGE=メッセージステータス # aimaccregwizz +plugin.aimaccregwizz.USERNAME_AND_PASSWORD=ユーザー名とパスワード # branding plugin.branding.ABOUT_WINDOW_TITLE={0}について plugin.branding.ABOUT_MENU_ENTRY=バージョン情報 (&A) -# Dict protocol - -# facebookaccregwizz # generalconfig +plugin.generalconfig.AUTO_START=コンピュータ起動時に {0} を起動 +plugin.generalconfig.GROUP_CHAT_MESSAGES=グループチャットメッセージを1つの画面で表示 +plugin.generalconfig.LOG_HISTORY=チャット履歴のログ +plugin.generalconfig.SHOW_HISTORY=表示 +plugin.generalconfig.HISTORY_SIZE=新しいチャットの現在のメッセージ +plugin.generalconfig.SEND_MESSAGES_WITH=メッセージを送付する先: +plugin.generalconfig.BRING_WINDOW_TO_FRONT=チャットウインドウを手前に持ってくる +plugin.generalconfig.DEFAULT_LANGUAGE=言語設定 +plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=変更は次回の起動時に有効になります +plugin.generalconfig.ERROR_PORT_NUMBER=誤ったポートNo. +plugin.generalconfig.CHECK_FOR_UPDATES=起動時に更新を確認 +plugin.generalconfig.LEAVE_CHATROOM_ON_WINDOW_CLOSE=ウインドウを閉じたときにチャットルームを抜ける +plugin.generalconfig.SHOW_RECENT_MESSAGES=最近の会話を表示する(チャット履歴による) +plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=電話番号を呼び出す前に、特殊記号を削除 +plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=電話番号の文字を変換 +plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=サンプリングレート # gibberish accregwizz +plugin.gibberishaccregwizz.USERNAME=ユーザーID # icqaccregwizz # irc accregwizz +plugin.ircaccregwizz.PROTOCOL_NAME=IRC +plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=IRCプロトコル +plugin.ircaccregwizz.USERNAME_AND_PASSWORD=IDとパスワード +plugin.ircaccregwizz.USERNAME=ニックネーム +plugin.ircaccregwizz.HOST=ホスト名 +plugin.ircaccregwizz.IRC_SERVER=サーバー +plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=連絡先のプレゼンスを有効にします +plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=チャットルームでのプレゼンスを有効にします +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} 認証 +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=SASL認証を有効にします +plugin.ircaccregwizz.SASL_USERNAME=ユーザー名 # jabber accregwizz - -# mailbox -plugin.mailbox.CONFIRM=確認 - -# msn accregwizz -plugin.msnaccregwizz.USERNAME=電子メール: +plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP +plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPPプロトコル +plugin.jabberaccregwizz.USERNAME=XMPP名 +plugin.jabberaccregwizz.PASSWORD_CONFIRM=パスワードを確認 +plugin.jabberaccregwizz.CSERVER=サーバー +plugin.jabberaccregwizz.SERVER=サーバーへ接続する +plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=キープアライブ可能 +plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS=Gmailの新しいメッセージの通知を有効 +plugin.jabberaccregwizz.ENABLE_GOOGLE_CONTACTS_SOURCE=Googleの連絡先の検索を有効にします +plugin.jabberaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=フリーSIPアカウントを作成する +plugin.jabberaccregwizz.SERVER_COLUMN=サーバー +plugin.jabberaccregwizz.COMMENT_COLUMN=コメント +plugin.jabberaccregwizz.RESOURCE=リソース +plugin.jabberaccregwizz.PRIORITY=優先度 +plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=未確認のXMPPエラー({0}).サーバー名が正しいか確認してください。 +plugin.jabberaccregwizz.NOT_SAME_PASSWORD=パスワードが一致しません。 +plugin.jabberaccregwizz.USE_ICE=ICEを使用する +plugin.jabberaccregwizz.SUPPORT_TURN=TURN対応 +plugin.jabberaccregwizz.TURN_USERNAME=TURNのサーバー名 +plugin.jabberaccregwizz.IP_ADDRESS=IPアドレス +plugin.jabberaccregwizz.ADD_STUN_SERVER=STUNサーバーを追加する +plugin.jabberaccregwizz.EDIT_STUN_SERVER=STUNサーバーを編集する +plugin.jabberaccregwizz.ADDITIONAL_STUN_SERVERS=別のSTUNサーバー +plugin.jabberaccregwizz.NO_STUN_ADDRESS=続けるには有効なSTUNサーバーアドレスを埋めてください。 +plugin.jabberaccregwizz.NO_STUN_USERNAME=続けるには有効なSTUNサーバーのユーザー名を埋めてください。 +plugin.jabberaccregwizz.STUN_ALREADY_EXIST=指定されたSTUNサーバーは既に存在します。 +plugin.jabberaccregwizz.JID_ADDRESS=IPアドレス +plugin.jabberaccregwizz.SERVER_OPTIONS=サーバーオプション +plugin.jabberaccregwizz.PORT_FIELD_INVALID=続けるには有効なポートNo.を埋めてください。 +plugin.jabberaccregwizz.TLS_REQUIRED=この接続はパスワードを変更しないTLSを使用しません。 +plugin.jabberaccregwizz.PASSWORD_CHANGED=パスワードは正常に変更されました。 +plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=そのXMPPサーバーはパスワード変更に対応していません。 +plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=全てに新しいパスワードを入力してください: +plugin.jabberaccregwizz.ENCODINGS=エンコーディング +plugin.jabberaccregwizz.AUDIO=音声 +plugin.jabberaccregwizz.VIDEO=映像 +plugin.jabberaccregwizz.RESET=リセット # plugin manager +plugin.pluginmanager.INSTALL=インストール +plugin.pluginmanager.PLUGINS=プラグイン +plugin.pluginmanager.URL=URL +plugin.pluginmanager.CHOOSE_FILE=選択したファイル +plugin.pluginmanager.SHOW_SYSTEM_BUNDLES=プラグインを表示 +plugin.pluginmanager.SYSTEM=システム +plugin.pluginmanager.NEW=新 # simple accregwizz +plugin.simpleaccregwizz.LOGIN_USERNAME=ユーザー名 +plugin.simpleaccregwizz.SIGNUP=登録はお済みですか? +plugin.simpleaccregwizz.SPECIAL_SIGNUP=登録はお済みですか?登録はこちらをクリック # sipaccregwizz +plugin.sipaccregwizz.PROTOCOL_NAME=SIP +plugin.sipaccregwizz.PROTOCOL_DESCRIPTION=SIPプロトコル +plugin.sipaccregwizz.USERNAME=SIP id +plugin.sipaccregwizz.USERNAME_AND_PASSWORD=ユーザー名とパスワード +plugin.sipaccregwizz.CLIENT_CERTIFICATE=クライアントTLS証明書 +plugin.sipaccregwizz.REGISTRAR=登録 +plugin.sipaccregwizz.SERVER_PORT=サーバーポート +plugin.sipaccregwizz.PROXY=プロキシ +plugin.sipaccregwizz.PROXY_PORT=プロキシポート +plugin.sipaccregwizz.PROXY_OPTIONS=プロキシオプション +plugin.sipaccregwizz.ENABLE_PRESENCE=プレゼンスを有効にします(SIMPLE) +plugin.sipaccregwizz.KEEP_ALIVE=キープアライブ機能 +plugin.sipaccregwizz.KEEP_ALIVE_METHOD=キープアライブメソッド +plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=キープアライブの間隔 +plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=1〜3600秒の間 +plugin.sipaccregwizz.DTMF=DTMF +plugin.sipaccregwizz.DTMF_METHOD=DTMFメソッド +plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) +plugin.sipaccregwizz.DTMF_SIP_INFO=SIP情報 +plugin.sipaccregwizz.DTMF_INBAND=インバンド通信 +plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=通話を暗号化するためのサポートを有効にします +plugin.sipaccregwizz.AUTH_NAME=承認名 plugin.sipaccregwizz.DISPLAY_NAME=表示名 +plugin.sipaccregwizz.CREATE_ACCOUNT=フリーSIPアカウントを作成する +plugin.sipaccregwizz.CREATE_ACCOUNT_TITLE=アカウントを作成する +plugin.sipaccregwizz.XCAP_OPTIONS=コンタクトリストのオプション +plugin.sipaccregwizz.XCAP_USER=ユーザー plugin.sipaccregwizz.XCAP_PASSWORD=パスワード +plugin.sipaccregwizz.VOICEMAIL=ボイスメール +plugin.sipaccregwizz.NOT_SAME_PASSWORD=パスワードが一致しません +#used from SecurityPanel +plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=有効な暗号化プロトコルとその優先度(上のプロトコルが優先)を選択: +plugin.sipaccregwizz.CIPHER_SUITES=有効な暗号セット: +plugin.sipaccregwizz.ZRTP_OPTION=ZRTPオプション # skin manager -# ssh accregwizz -plugin.sshaccregwizz.OPTIONAL=オプション - # status update +plugin.autoaway.ENABLE_CHANGE_STATUS=離席した時に状態を変更 +plugin.autoaway.AWAY_MINUTES=離席中と表示されるまでの時間(分): # updatechecker +plugin.updatechecker.DIALOG_TITLE=アップデートする +plugin.updatechecker.BUTTON_DOWNLOAD=ダウンロード plugin.updatechecker.BUTTON_CLOSE=閉じる (&o) +plugin.updatechecker.BUTTON_INSTALL=インストール +plugin.updatechecker.UPDATE_MENU_ENTRY=アップデートを確認 +plugin.updatechecker.DIALOG_NOUPDATE_TITLE=新しいバージョンはありません。 # usersearch +plugin.usersearch.USER_SEARCH=ユーザー検索 # whiteboard +plugin.whiteboard.TITLE=ホワイトボード[β版] +plugin.whiteboard.MENU_ITEM=ホワイトボード +plugin.whiteboard.NOT_SUPPORTED=ホワイトボードに対応していません。 +plugin.whiteboard.OPEN=開く +plugin.whiteboard.SELECT=選択 +plugin.whiteboard.IMAGE=画像 +plugin.whiteboard.POLYGON=ポリゴン +plugin.whiteboard.FILLEDPOLYGON=ポリゴン失敗 plugin.whiteboard.COLOR=色 plugin.whiteboard.MODIFICATION=通知 +plugin.whiteboard.GRID=グリッド plugin.whiteboard.DELETE=削除する -# yahoo accregwizz - -# zero accregwizz -plugin.zeroaccregwizz.FIRST_NAME=名前: -plugin.zeroaccregwizz.LAST_NAME=姓: -plugin.zeroaccregwizz.EMAIL=電子メール: - # gtalk accregwizz # iptel accregwizz - -# sip2sip accregwizz -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=このサービスについては、
    http://wiki.sip2sip.info を見てください。 -plugin.sip2sipaccregwizz.INFO_NOTE=このサービスについては、http://wiki.sip2sip.infoを見てください +plugin.iptelaccregwizz.USERNAME=ユーザー名 # ippi accregwizz +plugin.sip2sipaccregwizz.USERNAME=ユーザー名 +plugin.sip2sipaccregwizz.RETYPE_PASSWORD=パスワードを再度入力してください +plugin.sip2sipaccregwizz.EMAIL=メールアドレス plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=このサービスについては、
    http://ippi.fr を見てください。 plugin.ippiaccregwizz.INFO_NOTE=このサービスについては、 http://ippi.frを見てください +plugin.ippiaccregwizz.CREATE_ACCOUNT=フリーSIPアカウントを作成する # key binding chooser +#in new ChatWindow() -> manipulated +plugin.keybindings.CHAT_CLOSE=チャットウインドウを閉じる plugin.keybindings.CHAT_COPY=コピーする (&C) plugin.keybindings.CHAT_CUT=カット (&u) +plugin.keybindings.CHAT_OPEN_HISTORY=履歴を開く +plugin.keybindings.CHAT_OPEN_SMILIES=スマイリーを開く plugin.keybindings.CHAT_PASTE=貼付け (&P) plugin.keybindings.MAIN_RENAME=コンタクトの名前を変更 (&n) +plugin.keybindings.OPEN_HISTORY=履歴表示 +plugin.keybindings.OPEN_SMILIES=スマイリー表示 +plugin.keybindings.globalchooser.ANSWER_CALL=応答する +plugin.keybindings.globalchooser.HANGUP_CALL=通話終了 +plugin.keybindings.globalchooser.ANSWER_HANGUP_CALL=応答/終了 +plugin.keybindings.globalchooser.SHOW_CONTACTLIST=コンタクトリスト表示 +plugin.keybindings.globalchooser.MUTE_CALLS=消音 +plugin.keybindings.globalchooser.SHORTCUT_NAME=名前 +plugin.keybindings.globalchooser.ENABLE_SPECIAL=特殊キーの検出を有効にします +#Enum KeybindingSet.Category plugin.keybindings.CHAT=チャット # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=有効 +plugin.notificationconfig.TURN_ON_ALL=全て有効にする +plugin.notificationconfig.TURN_OFF_ALL=全て無効にする +plugin.notificationconfig.POPUP_NOTIF_HANDLER=ポップアップ通知の種類 +plugin.notificationconfig.SOUND_FILE=次のファイル: +plugin.notificationconfig.PROGRAM_FILE=プログラムファイル: +plugin.notificationconfig.tableheader.ENABLE=この機能を有効・無効にする +plugin.notificationconfig.tableheader.POPUP=メッセージボックスを表示する +#NotificationsTable constants +plugin.notificationconfig.event.IncomingCall=着信中です +plugin.notificationconfig.event.IncomingFile=着信中です +plugin.notificationconfig.event.Dialing=ダイヤル中 +plugin.notificationconfig.event.BusyCall=話し中 plugin.notificationconfig.event.HangUp=切断 +plugin.notificationconfig.event.DTMFTone.A=DTMFトーンA +plugin.notificationconfig.event.DTMFTone.B=DTMFトーンB +plugin.notificationconfig.event.DTMFTone.C=DTMFトーンC +plugin.notificationconfig.event.DTMFTone.D=DTMFトーンD +plugin.notificationconfig.event.DTMFTone.0=DTMFトーン0 +plugin.notificationconfig.event.DTMFTone.1=DTMFトーン1 +plugin.notificationconfig.event.DTMFTone.2=DTMFトーン2 +plugin.notificationconfig.event.DTMFTone.3=DTMFトーン3 +plugin.notificationconfig.event.DTMFTone.4=DTMFトーン4 +plugin.notificationconfig.event.DTMFTone.5=DTMFトーン5 +plugin.notificationconfig.event.DTMFTone.6=DTMFトーン6 +plugin.notificationconfig.event.DTMFTone.7=DTMFトーン7 +plugin.notificationconfig.event.DTMFTone.8=DTMFトーン8 +plugin.notificationconfig.event.DTMFTone.9=DTMFトーン9 +plugin.notificationconfig.event.DTMFTone.*=DTMFトーン* +plugin.notificationconfig.event.DTMFTone.#=DTMFトーン# +plugin.notificationconfig.event.NewSelectedDevice=新たに選択された機器 # ZRTP Securing # ZRTP Configuration impl.media.security.zrtp.TITLE=コール +impl.media.security.zrtp.PUB_KEYS=公開鍵 +impl.media.security.zrtp.HASHES=ハッシュ +impl.media.security.zrtp.SAS_TYPES=SASタイプ +impl.media.security.zrtp.STANDARD=標準 +impl.media.security.zrtp.ZRTP_NINJA=ZRTP Ninja # Profiler4J +impl.media.configform.AUDIO=オーディオ機器(&A): +impl.media.configform.AUDIO_IN=マイク入力(&I): impl.media.configform.AUDIO_NOTIFY=通知 - - +impl.media.configform.AUDIO_OUT=スピーカー出力(&O): +impl.media.configform.AUTOMATICGAINCONTROL=自動マイク調整 +impl.media.configform.DENOISE=ノイズ抑制を有効にする +impl.media.configform.DEVICES=端末 +impl.media.configform.ECHOCANCEL=エコーキャンセレーションを有効にする +impl.media.configform.ENCODINGS=エンコーディング +impl.media.configform.NO_AVAILABLE_AUDIO_DEVICE=音声用機器がありません。何か接続してください。 +impl.media.configform.NO_PREVIEW=プレビュー +impl.media.configform.VIDEO_MORE_SETTINGS=セッティング詳細 +impl.media.configform.VIDEO_RESOLUTION=映像の解像度 +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_IN=マイク用に新しい機器が選択されました: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_OUT=スピーカー用の新しい機器が選択されました: +impl.media.configform.AUDIO_DEVICE_SELECTED_AUDIO_NOTIFICATIONS=通知用の新しい機器が選択されました: +impl.media.configform.VIDEO_DEVICE_SELECTED=ビデオ用の新しい機器が選択されました: + +impl.neomedia.configform.AUDIO=オーディオ +impl.neomedia.configform.VIDEO=映像 + +#in JNIEncoder +impl.neomedia.configform.H264.defaultProfile.high=高い +impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTCP +impl.neomedia.configform.H264.preferredKeyFrameRequester.signaling=シグナリング # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. +plugin.callrecordingconfig.CALL_RECORDING_CONFIG=通話を記録する +plugin.callrecordingconfig.CALL_SAVED=通話の保存に成功 # Security configuration form title +plugin.securityconfig.TITLE=セキュリティ plugin.securityconfig.masterpassword.TITLE=パスワード +plugin.securityconfig.masterpassword.SAVED_PASSWORDS=パスワードを保存しました +plugin.securityconfig.masterpassword.CURRENT_PASSWORD=現在のパスワード plugin.securityconfig.masterpassword.REENTER_PASSWORD=パスワードを記録する +plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=パスワードが一致しません。やり直してください。 +plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=パスワード変更に失敗しました +plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS_MSG=マスターパスワードを正常に削除しました。 +plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS_MSG=マスターパスワードを正常に削除しました。 +plugin.securityconfig.masterpassword.COL_NAME=名前 plugin.securityconfig.masterpassword.COL_PASSWORD=パスワード -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=取り除く (&R) +plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=保存されたパスワード +plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=全削除 +plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=本当に全てのパスワードを削除して宜しいですか? +plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=全パスワードを削除 +plugin.securityconfig.masterpassword.SHOW_PASSWORDS_BUTTON=パスワードを表示する +plugin.securityconfig.masterpassword.HIDE_PASSWORDS_BUTTON=パスワードを隠す # otr plugin +plugin.otr.menu.TITLE=安全性の高いチャット +plugin.otr.menu.CB_ENABLE=プライベートメッセージを有効にする +plugin.otr.menu.CB_REQUIRE=プライベートメッセージを有効にする +plugin.otr.menu.CB_RESET=リセット +plugin.otr.menu.OTR_TOOLTIP=OTRで暗号化されたチャット +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD=どのように認証しますか? +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_QUESTION=認証の質問 plugin.otr.authbuddydialog.CANCEL=キャンセル (&C) plugin.otr.authbuddydialog.HELP=ヘルプ (&H) +plugin.otr.authbuddydialog.I_HAVE=あります +plugin.otr.authbuddydialog.I_HAVE_NOT=ありません +plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS=認証成功! +plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL=認証に失敗しました。 +plugin.otr.configform.CB_ENABLE=プライベートメッセージを有効にする +plugin.otr.configform.CB_REQUIRE=プライベートメッセージを有効にする plugin.otr.configform.GENERATE=生成 plugin.otr.configform.REGENERATE=再生成 +plugin.otr.configform.FINGERPRINT=指紋 +plugin.otr.configform.VERIFY_FINGERPRINT=指紋認証 +plugin.otr.configform.FORGET_FINGERPRINT=指紋を忘れました plugin.otr.configform.COLUMN_NAME_CONTACT=問い合わせ +plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=証明 plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=はい plugin.otr.configform.COLUMN_VALUE_VERIFIED_FALSE=いいえ +plugin.otr.activator.unencryptedmsgreceived=メッセージ暗号化されずに受け取られました。 +plugin.otr.activator.requireencryption=メッセージ [{0}]は送信されませんでした。プライベートメッセージの送信が要求されました。 # global proxy plugin +plugin.globalproxy.GLOBAL_PROXY_CONFIG=グローバルプロキシ +plugin.globalproxy.PROXY_TYPE=プロキシタイプ +plugin.globalproxy.PROXY_ADDRESS=プロキシサーバー +plugin.globalproxy.PROXY_PORT=プロキシポート +plugin.globalproxy.PROXY_USERNAME=プロキシ名 +plugin.globalproxy.PROXY_PASSWORD=プロキシパスワード #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -652,25 +1145,39 @@ plugin.reconnectplugin.CONNECTION_FAILED_MSG=次のアカウントで接続に #plugin chat config plugin.chatconfig.TITLE=チャット +plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=絵文字置換を有効にする +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=有効 #provisioning plugin +plugin.provisioning.ENABLE_DISABLE=プロビジョニングを有効にする # packet logging service +plugin.loggingutils.ENABLE_DISABLE=パケットのログ記録を有効にする +plugin.loggingutils.PACKET_LOGGING_RTP=RTP # dns config plugin +plugin.dnsconfig.chkBackupDnsEnabled.text=DNS正引きの並列化を有効にする +plugin.dnsconfig.lblBackupResolver.text=ホスト名 +plugin.dnsconfig.lblBackupPort.text=ポート +plugin.dnsconfig.dnssec.chkEnabled=DNSSEC正引きを有効にする +plugin.dnsconfig.dnssec.ENABLE_FAILED_MSG=DNSSECを使用可能な状態に変更できませんでした。 net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=無視する (&I) net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=拒否(&D) #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=編集する (&E) +plugin.spellcheck.ENABLE_SPELL_CHECK=スペルチェックを有効にする +plugin.spellcheck.DICT_ERROR_TITLE=辞書切り替えエラー #Certificate configuration plugin plugin.certconfig.KEYSTORE=ファイル (&F) plugin.certconfig.KEYSTORE_PASSWORD=パスワード +plugin.certconfig.REVOCATION_CHECK_ENABLED=CRL (証明書排除リスト) チェックが有効 +plugin.certconfig.REVOCATION_OCSP_ENABLED=OCSP (オンライン証明書ステータスプロトコル) チェックが有効 # Phone number contact source plugin # properties editor #Thunderbird address book plugin +plugin.thunderbird.ENABLED=有効 -- cgit v1.1 From a074b36dc419cfe53971eb34f62d45d411777d5f Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:03 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1371 of 1505 strings translated (13 fuzzy). --- resources/languages/resources_cs.properties | 231 ++++++---------------------- 1 file changed, 49 insertions(+), 182 deletions(-) diff --git a/resources/languages/resources_cs.properties b/resources/languages/resources_cs.properties index 1a3390f..b2c4347 100644 --- a/resources/languages/resources_cs.properties +++ b/resources/languages/resources_cs.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Já service.gui.ACCOUNT_REGISTRATION_WIZARD=Průvodce registrací účtu service.gui.ACCOUNTS=Účty service.gui.ADD=&Přidat -service.gui.ADD_ACCOUNT=Přidat účet service.gui.ADD_CONTACT=&Přidat kontakt service.gui.ADD_AUTHORIZED_CONTACT=Přidat {0} do seznamu kontaktů service.gui.ADD_CONTACT_TO=&Přidat kontakt do @@ -41,20 +51,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Chyba při přidávání kontaktu service.gui.ADD_CONTACT_EXIST_ERROR=Kontakt {0} již existuje ve vašem seznamu kontaktů. service.gui.ADD_CONTACT_NETWORK_ERROR=Server neodpověděl na požadavek o přidání kontaktu s id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Neúspěšné přidání kontaktu s id: {0}. Operace není podporována. -service.gui.ADD_CONTACT_IDENTIFIER=Do pole níže zadejte identifikátor kontaktu, který chcete přidat. -service.gui.ADD_CONTACT_WIZARD=Průvodce přidáním kontaktu service.gui.ADD_CONTACT_NOT_CONNECTED=Pro přidání kontaktu musíte být připojeni. Přihlašte se prosím k vybranému poskytovateli a opakujte akci. service.gui.ADD_GROUP_LOCAL_ERROR=Nepodařilo se přidat skupinu se jménem: {0}. Chyba při lokální IO operaci. service.gui.ADD_GROUP_EXIST_ERROR=Skupina jménem {0} již existuje ve vašem seznamu kontaktů. Zvolte prosím jiný název. service.gui.ADD_GROUP_NET_ERROR=Nepodařilo se přidat skupinu: {0}. Problém byl způsoben chybou sítě. Zkontrolujte prosím síťové připojení a opakujte akci. service.gui.ADD_GROUP_ERROR=Nepodařilo se přidat skupinu s jménem {0}. service.gui.ADD_GROUP_EMPTY_NAME=Jméno skupiny musí být zadáno -service.gui.ADD_GROUP=Přidat skupinu -service.gui.ADD_SUBCONTACT=&Přidat subkontakt service.gui.ADDRESS=Adresa service.gui.ADMINISTRATOR=administrátor service.gui.ADVANCED=&Pokročilé -service.gui.ALL=&Vše service.gui.ALL_CONTACTS=&Všechny kontakty service.gui.APPLY=&Použij service.gui.ARE_CALLING={0} volá... @@ -63,7 +68,6 @@ service.gui.AT=at service.gui.AUTHORIZE=Autorizovat service.gui.AUTHORIZATION_ACCEPTED={0} přijal požadavek na autorizaci. service.gui.AUTHENTICATION_FAILED=Neúspěšné přihlášení ({0}). Zadali jste nesprávné heslo. -service.gui.AUTHENTICATION_REQUESTED=Požadavek na přihlášení service.gui.AUTHENTICATION_REQUESTED_SERVER=Server {0} vyžaduje vaši autentifikaci. service.gui.AUTHENTICATION_REJECTED={0} odmítl váš požadavek na autorizaci. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autorizace @@ -103,7 +107,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Do políčka níže zadejte novou přezdívku. service.gui.CHANGE_NICKNAME_ERROR=Chyba při změně jména service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Přezdívka již existuje service.gui.CHANGE_VIDEO_QUALITY=Změnit kvalitu vzdáleného videa -service.gui.CHAT_CONFERENCE_LABEL=Konference service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} konferencí service.gui.CHAT_ROOM_ALREADY_JOINED=Místnost {0} je již připojena. service.gui.CHAT_ROOM_CONFIGURATION=Konfigurace místnosti {0} @@ -114,18 +117,14 @@ service.gui.CHAT_ROOM_USER_JOINED=se připojil(a) do {0} service.gui.CHAT_ROOM_USER_LEFT=opustil(a) {0} service.gui.CHAT_ROOM_USER_KICKED=byl(a) vyhozen(a) od {0} service.gui.CHAT_ROOM_USER_QUIT=ukončil(a) {0} -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Uloží místnost pro budoucí použití -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Odstranit zvolenou místnost ze seznamu uložených místností service.gui.CHAT_ROOM_NAME=Jméno místnosti service.gui.CLEAR_CUSTOM_MESSAGES=Vymazat vlastní zprávy service.gui.ROOM_NAME=Místnost -service.gui.AUTOJOIN=Automatické připojení service.gui.CHANGE_PASSWORD=Změnit heslo service.gui.CHAT_ROOM_NAME_INFO=Do pole níže zadejte jmého místnosti kterou chcete vytvořit. service.gui.CHAT_ROOM_NOT_EXIST=Místnost {0} nebyla nalezena na serveru {1}. Přesvědčte se jestli jste zadali správné jméno. service.gui.CHAT_ROOM_NOT_CONNECTED=Pro připojení k místnosti {0} musíte být přihlášeni. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Pro opuštění místnosti k ní musíte být přihlášeni. -service.gui.CHAT_ROOM_NOT_JOINED=Pro provádění akcí v místnosti k ní musíty být přihlášeni. service.gui.CHAT_ROOM_OPTIONS=Možnosti místnosti service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Místnost {0} vyžaduje abyste se před připojením registrovali. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Místnost {0} požaduje heslo. @@ -142,22 +141,18 @@ service.gui.CLEAR=Vymazat service.gui.CLOSE=&Zavřít service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Před méně než 2 ma sekundami jste přijali novou zprávu. Opravdu chcete zavřít chat? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Právě probíhá přenos souboru. Přejete si jej přerušit? -service.gui.CONFIRM=Potvrdit service.gui.CONNECTED_STATUS=Spojeno service.gui.CONNECTING=Připojuji... service.gui.CONNECTING_STATUS=Připojuji service.gui.CONNECTING_EARLY_MEDIA_STATUS=Připojuji... service.gui.CONNECTION=Spojení -service.gui.CONNECTION_FAILED_MSG=Nepodařilo se připojit účet {0} k serveru {1}. Zkontrolujte nastavení síťového spojení nebo kontaktujte správce sítě. service.gui.CONNECTION_EXPIRED_MSG=Nyní jste odpojeni od serveru {0}. service.gui.CONTACT_NAME=ID nebo Číslo -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Zvolený kontakt {0} nepodporuje telefonování. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Zvolený kontakt {0} nepodporuje konferenční chat. service.gui.CONTACT_PAUSED_TYPING={0} přestal(a) psát... service.gui.CONTACT_TYPING={0} píše zprávu... service.gui.CONTACT_TYPING_SEND_FAILED=nemohli jsme {0} informovat že jste mu psali service.gui.CONTACT_INFO=&Informace o kontaktech -service.gui.CONTACTLIST=Seznam kontaktů service.gui.CONTACTS=Kontakty service.gui.COPY=&Kopírovat service.gui.COPY_LINK=Kopírovat &odkaz @@ -167,16 +162,13 @@ service.gui.CREATE_CHAT_ROOM=&Vytvořit místnost... service.gui.CREATE_CHAT_ROOM_ERROR=Chyba při vytváření místnosti {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Průvodce vytvořením místnosti service.gui.CREATE_CONFERENCE_CALL=&Vytvořit konferenční hovor... -service.gui.CREATE_CONFERENCE_CHAT=&ytvořit konferenční chat... service.gui.CREATE_GROUP=&Vytvořit skupinu service.gui.CREATE_GROUP_NAME=Do políčka níže zadejte název skupiny kterou chcete vytvořit. -service.gui.CREATE_FIRST_GROUP_WIZARD=Váš seznam kontaktů neobsahuje žádnou skupinu. Prosím nejprve skupinu vytvořte (Soubor/Vytvořit skupinu). service.gui.CREATE_VIDEO_BRIDGE=Vytvořit &video bridge... service.gui.CREATE_VIDEO_BRIDGE_MENU=Vytvořit &video bridge service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Vytvořit / Připojit se do video konference service.gui.CONTACT_INFO_NOT_SUPPORTED=Tento kontakt nepodporuje informace z webu service.gui.CUT=&Vyjmout -service.gui.DATE=Datum service.gui.DELETE=Smazat service.gui.DENY=&Odmítnout service.gui.DESKTOP_SHARING_WARNING=Opravdu si přejete sdílet obrazovku?
    Stlačením OK dovolíte ostatním vidět vaši obrazovku @@ -186,7 +178,6 @@ service.gui.DISCONNECTED_STATUS=Odpojeno service.gui.DND_STATUS=Nerušit service.gui.DO_NOT_ASK_AGAIN=Příště se neptat service.gui.DO_NOT_SHOW_AGAIN=Tuto zprávu víckrát nezobrazovat -service.gui.DOWNLOAD_NOW=&Stáhnout nyní service.gui.DRAG_FOR_SHARING=Přetáhněte sem objekty ke sdílení... service.gui.DURATION=Doba trvání service.gui.EDIT=&Editovat @@ -205,7 +196,6 @@ service.gui.ERROR_RECEIVED_FROM=Nelze přijmout zprávu od {0} service.gui.ESTIMATED_TIME=Odhadovaný čas: service.gui.EVENTS=Notifikace service.gui.EXIT=U&končit -service.gui.EXTENDED_CRITERIA=Rozšířené hledání service.gui.GENERAL=Obecné service.gui.GENERAL_ERROR=Obecná chyba service.gui.GROUP_NAME=Jméno skupiny @@ -247,7 +237,6 @@ service.gui.FONT_ITALIC=Kurzíva service.gui.FONT_SIZE=Velikost service.gui.FONT_STYLE=Styl service.gui.FONT_UNDERLINE=Podtržené -service.gui.FROM={0} z {1} service.gui.GRANT_OWNERSHIP=Přidělit vlastnictví... service.gui.GRANT_ADMIN=Přidělit práva administrátora... service.gui.GRANT_MODERATOR=Přidělit práva moderátora @@ -273,12 +262,12 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Jste si jisti, že chcete trvale odstrani service.gui.HISTORY_REMOVE_ERROR=Chyba při odstraňování lokálně uložených zpráv. service.gui.HOME=Domov service.gui.HOME_PAGE=Domovská stránka -service.gui.HOUR=Hodin(a) service.gui.ICE=ICE service.gui.IDENTIFIER=Identifikátor service.gui.IGNORE=&Ignorovat service.gui.INSERT_SMILEY=Vložit smajlíka service.gui.INCOMING_CALL=Příchozí hovor od: {0} +service.gui.INCOMING_SCREEN_SHARE=Příchozí hovor od: {0} service.gui.INCOMING_CALL_STATUS=Příchozí hovor service.gui.INSTANT_MESSAGINGS=IM service.gui.INITIATING_CALL_STATUS=Inicializace spojení @@ -294,12 +283,9 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Pozvat kontakty do video bridge service.gui.INVITE_REASON=Důvod pozvání service.gui.IS_CALLING={0} volá... service.gui.IS_NOW={0} je nyní {1} -service.gui.JITSI_WARNING=SIP Communicator byl před časem přejmenovaný na Jitsi.
    Jestliže si přejete aby vaše verze zůstala aktuální, potom prosím stáhněte aplikaci Jitsi.

    Omlouváme se za jakékoli způsobené nepřijemnosti.

    Vývojový tým Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator se přejmenuje na Jitsi service.gui.JOIN=&Připojit service.gui.JOIN_AS=Př&ipojen jako service.gui.JOIN_VIDEO=Připojit video -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Zavřít service.gui.JOB_TITLE=Pozice service.gui.JOIN_CHAT_ROOM=&Připojit místnost... service.gui.JOIN_CHAT_ROOM_TITLE=Připojit místnost @@ -312,7 +298,6 @@ service.gui.KICK_FAILED=Vyhození selhalo service.gui.KICK_FAILED_GENERAL_ERROR=Nepodařilo se vyhodit uživatele {0}. Nastala obecná chyba serveru. service.gui.KICK_FAILED_NOT_ALLOWED=Nepodařilo se vyhodit uživatele {0}. Vlastník ani správce místnosti nemůžou být vyhozeni. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Nepodařilo se vyhodit uživatele {0}. Nemáte dostatečná oprávnění. -service.gui.LAST=Poslední service.gui.LAST_NAME=Příjmení service.gui.LEAVE=&Odejít service.gui.LIMIT_REACHED_FOR_IP=Máte otevřeno příliš mnoho spojení z lokální IP adresy a server {0} odmítl z této adresy otevřít další spojení. @@ -332,7 +317,6 @@ service.gui.MESSAGE=Zprávy service.gui.MISSED_CALLS_TOOL_TIP=Ztracená volání od: service.gui.MISSED_CALLS_MORE_TOOL_TIP= a {0} další(ch) service.gui.MODERATOR=moderátor -service.gui.MORE=Více (See more) service.gui.MORE_LABEL=Více service.gui.MOVE=Přesunout service.gui.MOVE_SUBCONTACT=Pře&místit kontakt @@ -341,7 +325,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Vybraný kontakt je stejný jako ten,\nkterý service.gui.MOVE_SUBCONTACT_QUESTION=Opravdu si přejete přesunout kontakt {0} do {1}? service.gui.MOVE_TO_GROUP=&Přesunout do skupiny service.gui.MOVE_CONTACT=Přesunout kontakt -service.gui.MOVE_CONTACT_ERROR=&Kontakt nelze přesunout service.gui.MSG_DELIVERY_FAILURE=Zprávu nelze doručit service.gui.MSG_DELIVERY_NOT_SUPPORTED=Protokol nepodporuje offline doručování zpráv. Můžete se zkusit s {0} spojit pomocí jiného protokolu, nebo počkat až bude kontakt online. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Vnitřní chyba programu. Prosím oznamte chybu zde: https://jitsi.org/Development/BugsAndIssues. @@ -354,7 +337,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Abyste mohli zprávu odeslat, musít bá service.gui.MULTIPLE_LOGINS=Jste přihlášeni víckrát pod stejným účtem. Tento účet: Jméno: {0}, server: {1} je nyní odpojen. service.gui.MY_CHAT_ROOMS=Přidat chatovací místnost service.gui.MY_CHAT_ROOMS_TITLE=Přidat chatovací místnost -service.gui.MUTE=Ztlumit service.gui.MUTUALLY_ON_HOLD_STATUS=Navzájem drženo service.gui.NAME=Jméno service.gui.NETWORK=Síť @@ -365,6 +347,7 @@ service.gui.NEW_MESSAGE=Nová zpráva service.gui.NEW_NAME=Moje jméno service.gui.NEW_STATUS_MESSAGE=Nová stavová zpráva service.gui.NEW_STATUS_MESSAGE_SAVE=Uložit jako vlastní zprávu +service.gui.NICKNAME=Přezdívka service.gui.NO=Ne service.gui.NONE=Žádný service.gui.NO_CAMERA_AVAILABLE=Kamera není k dispozici @@ -385,7 +368,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Není v seznamu kontaktů service.gui.SD_QUALITY=Standardní kvalita service.gui.OFFLINE=Odpojen service.gui.OK=&OK -service.gui.OLDER_CALLS=Starší volání service.gui.ONLINE=Připojen service.gui.OPEN=Otevřít service.gui.OPEN_FILE_FROM_IMAGE=Dvojklikněte pro otevření souboru. @@ -393,9 +375,12 @@ service.gui.OPEN_FOLDER=Otevřít složku service.gui.OPEN_IN_BROWSER=Otevřít v &prohlížeči service.gui.OPTIONS=Volby service.gui.OR=nebo -service.gui.OR_ENTER_PHONE_NUMBER=Nebo zde zadejte telefonní číslo... service.gui.ORGANIZATION=Organizace service.gui.OTHER=Ostatní +service.gui.chat.role.ADMINISTRATOR=administrátor +service.gui.chat.role.MODERATOR=moderátor +service.gui.chat.role.MEMBER=člen +service.gui.chat.role.SILENT_MEMBER=tichý společník service.gui.OWNER=vlastník místnosti service.gui.ON_MOBILE_TOOLTIP=(Na mobilu) service.gui.PASSWORD=Heslo @@ -411,7 +396,6 @@ service.gui.PRESENCE=Přítomnost service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' pro návrhy service.gui.PRESS_FOR_CALL_INFO=Zobrazit detaily o hovoru service.gui.PREVIOUS=Předchozí -service.gui.PREVIOUS_TOOLTIP=Procházet starší konverzaci service.gui.PRINT=&Tisk service.gui.PROACTIVE_NOTIFICATION=píše zprávu service.gui.PROBLEMS_ENCOUNTERED=Nalezeny problémy @@ -420,13 +404,13 @@ service.gui.PUT_OFF_HOLD=Uvolnit (Put off hold) service.gui.PUT_ON_HOLD=Podržet (Put on hold) service.gui.QUIT=&Ukončit service.gui.READY=Připraven +service.gui.RECENT_MESSAGES=Poslední konverzace service.gui.REASON=Důvod service.gui.RECEIVED={0} přijatých zpráv service.gui.RECONNECTION_LIMIT_EXCEEDED=Odpojili a znovu připojili jste se k serveru příliš rychle. Účet {0} na serveru {1} je dočasně zakázaný. Před dalším přihlášením budete muset chvíli počkat. service.gui.RE_REQUEST_AUTHORIZATION=Znovu požádat o autorizaci service.gui.REFERRED_STATUS=Odkazováno service.gui.REJECT=&Zamítnout -service.gui.REMIND_ME_LATER=Připomenout později service.gui.REMEMBER_PASSWORD=Zapamatovat si heslo service.gui.REMOVE=&Odebrat service.gui.REMOVE_ACCOUNT=&Odebrat účet @@ -452,29 +436,20 @@ service.gui.REVOKE_ADMIN=Zrušit práva admina service.gui.REVOKE_MODERATOR=Odejmout moderování service.gui.REVOKE_MEMBERSHIP=Zrušit členství service.gui.REVOKE_VOICE=Odebrat hlas -service.gui.ROOT_GROUP=Hlavní skupina (Root group) service.gui.SAVE=&Uložit -service.gui.SAVE_AS_DEFAULT=Uložit jako výchozí service.gui.SEARCH=&Hledat service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Pro zobrazení všech místností na vybraném serveru klikněte na tlačítko. Pak vyberte místnost ke které se chcete připojit a klikněte na Připojit. service.gui.SEARCH_STRING_CONTACT_SOURCE=Hledaný kontakt service.gui.SECURITY=Zabezpečení -service.gui.SELECT_ACCOUNT=Vybrat účet service.gui.SELECT_COLOR=Volba barvy service.gui.SELECT_GROUP=Vybrat skupinu -service.gui.SELECT_GROUP_WIZARD_MSG=seznam níže obsahuje všechny skupiny vašeho seznamu kontaktú. Vyberte skupinu do které chcete přidat kontakt. service.gui.SELECT_NO_GROUP=Žádná skupina -service.gui.SELECT_GROUP_WIZARD=Zadejte skupinu service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Seznam níže obsahuje všechny účty které podporují víceuživatelský chat. Vyberte účet který chcete použít pro vytvoření chatovací místnosti. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Seznam níže obsahuje všechny registrované účty. Vyberte účet který chcete použít pro komunikaci s novým kontaktem. -service.gui.SELECT_PROVIDERS_WIZARD=Výběr účtu service.gui.SELECT_VIDEO_CONFERENCE=Zvolte video hovor service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Vyberte chatovací místnost ze seznamu a klikněte na tlačítko OK pro přidání. service.gui.SEND=&Odeslat service.gui.SEND_FILE=Odeslat &soubor -service.gui.SELECT_CONTACT_SUPPORTING_INFO=K tomuto kontaktu neexistují žádné informace. service.gui.SEND_MESSAGE=&Odeslat zprávu -service.gui.SEND_AS_SMS=Odeslat jako SMS service.gui.SEND_PRIVATE_MESSAGE=Odeslat soukromou zprávu service.gui.SEND_SMS=O&deslat SMS service.gui.SEND_SMS_DETAILS=Nezapomeňte, že musíte zadat číslo v mezinárodním formátu t.j. začínající na +420 v Česku a +421 na Slovensku - např. +420777000000 @@ -482,6 +457,7 @@ service.gui.SEND_SMS_NOT_SUPPORTED=Zvolený protokol nepodporuje SMS zprávy. service.gui.SMS=SMS service.gui.SEND_VIA=Odeslat přes service.gui.SENT=odesláno +service.gui.SERVER_CHAT_ROOMS=Serverové chatovací místnosti service.gui.SET_GLOBAL_STATUS=Nastavit globální stav service.gui.SET_STATUS_MESSAGE=Nastavit stavovou zprávu service.gui.SET_SUBJECT=Nastavit předmět @@ -512,7 +488,6 @@ service.gui.STREET=Ulice service.gui.SUBJECT=Předmět service.gui.SUMMARY=Základní service.gui.TELEPHONY=Telefonování -service.gui.TODAY=Dnes service.gui.TOOLS=&Nástroje service.gui.TRANSFER=&Přenos service.gui.TO=&Komu: @@ -522,7 +497,6 @@ service.gui.TRANSFER_CALL_TO=Kam přenést: service.gui.TRANSPARENCY_NOT_ENABLED=Vaše současná konfigurace nepodporuje průhlednost. service.gui.TYPE_YOUR_REQUEST=Zadejte váš požadavek service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Kvalita videa tohoto hovoru nemůže být změněna. -service.gui.UNMUTE=Zapnout zvuk service.gui.USER_IDENTIFIER=Uživatelská identifikace: service.gui.USER_EXISTS_ERROR=Tento uživatel již existuje ve zvolené síti. Vyberte prosím vyberte jiného uživatele nebo síť. service.gui.USERNAME_NULL=Prosím zadejte jméno a heslo. @@ -535,7 +509,6 @@ service.gui.USE_PROVISIONING=Použít online autokonfiguraci service.gui.VALUE=Hodnota service.gui.VIDEO_CALL=Videohovor service.gui.VIA=přes -service.gui.VIA_SMS=Přes SMS service.gui.VIEW=&Prohlížet (View) service.gui.VIEW_HISTORY=Zobrazit &historii service.gui.VIEW_SMILEYS=Prohlížet &smajlíky @@ -555,9 +528,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Nastavení hlasitosti service.gui.WAITING_AUTHORIZATION=Čeká se na autorizaci service.gui.WARNING=Varování service.gui.YES=Ano -service.gui.YESTERDAY=Včera -service.gui.EXISTING_ACCOUNT_ERROR=Účet který jste zadali již existuje. -service.gui.NEW_MAIL=Máte novou poštu!
    Od: {0} {1}
    Subject: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Máte novou poštu ve vaší schránce {0}:
    service.gui.NEW_GMAIL_MANY_HEADER=Máte {2} nových mailových zpráv ve vaší schránce {0}:
    service.gui.NEW_GMAIL_FOOTER=jedna nebo více nepřečtených konverzací ve vaší schránce.
    @@ -580,7 +550,6 @@ service.gui.SECURITY_ERROR=Chyba zabezpečení service.gui.SPEED=Rychlost: service.gui.SILENT_MEMBER=tichý společník service.gui.NON_SECURE_CONNECTION=Pro účet {0} není možné vytvořit bezpečné připojení. Pokud se chceš připojit k nezabezpečenému serveru, prosím odklikni "Povolit nezabezpečené připojení" v nastavení účtu -service.gui.UPDATE=Aktualizovat service.gui.MOBILE_PHONE=Mobil service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Práce @@ -588,6 +557,7 @@ service.gui.PHONE=Telefonní číslo service.gui.PHONES=Telefony service.gui.EDIT_NOT_SUPPORTED=Upravování tohoto účtu není podporováno service.gui.SHOW_PREVIEW=(Zobrazit náhled) +service.gui.SHOW_PREVIEW_DIALOG_TITLE=Zobrazit náhled obrázku / videa service.gui.ZID_NAME_SET=Identifikátor jména ZRTP: service.gui.ZID_NAME_NOT_SET=Identifikátor jména ZRTP není nastaven. @@ -613,7 +583,6 @@ service.gui.callinfo.CALL_INFORMATION=Informace o hovoru service.gui.callinfo.CALL_IDENTITY=Identita service.gui.callinfo.PEER_COUNT=Počet účastníků service.gui.callinfo.IS_CONFERENCE_FOCUS=Téma rozhovoru -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Šifrování zapnuto service.gui.callinfo.CALL_TRANSPORT=Signalizace průběhu hovoru service.gui.callinfo.CALL_DURATION=Doba hovoru service.gui.callinfo.VIEW_CERTIFICATE=Zobrazit certifikát @@ -634,10 +603,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Klíčový protokol o výměně service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE kandidát rozšířeného typu service.gui.callinfo.ICE_STATE=ICE Zpracování Stavu + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Shromáždění kandidáti service.gui.callinfo.ICE_STATE.RUNNING=Ověření připojení service.gui.callinfo.ICE_STATE.COMPLETED=Hotovo service.gui.callinfo.ICE_STATE.FAILED=Selhalo + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Lokální IP hostitele / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Místní reflexivní IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Místní "relayed" IP / Port @@ -658,9 +630,10 @@ service.gui.ALWAYS_TRUST=Přijmout certifikát trvale service.gui.CERT_DIALOG_TITLE=Ověřit certifikát service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} nemůže ověřit identitu serveru při připojování k
    {1}.

    Certifikát serveru není podepsán důvěryhodnou autoritou, identita serveru proto nemůže být automaticky ověřena.

    Chcete pokračovat v připojování?
    Pro více informací klikněte na "Zobrazit certifikát". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} nemůže ověřit certifikát serveru.

    Certifikát není podepsán důvěryhodnou autoritou, identita serveru proto nemůže být automaticky ověřena.

    Chcete pokračovat v připojování?
    Pro více informací klikněte na "Zobrazit certifikát". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} nemůže ověřit identitu připojovaného klienta.

    Certifikát není podepsán důvěryhodnou autoritou, identita klienta proto nemůže být
    automaticky ověřena. Chcete pokračovat v připojování?

    Pro více informací klikněte na "Zobrazit certifikát". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} nemůže ověřit identitu uživatele {1}.

    Certifikát není podepsán důvěryhodnou autoritou, identita uživatele proto nemůže být automaticky ověřena.

    Chcete pokračovat v připojování?

    Pro více informací, klikněte na "Zobrazit certifikát". service.gui.CONTINUE_ANYWAY=Přesto pokračovat + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Jméno nositele: service.gui.CERT_INFO_O=Organizace: service.gui.CERT_INFO_C=Země: @@ -669,17 +642,16 @@ service.gui.CERT_INFO_L=Lokalita: service.gui.CERT_INFO_OU=Organizační jednotka service.gui.CERT_INFO_ISSUED_ON=Vydán dne: service.gui.CERT_INFO_EXPIRES_ON=Expiruje dne: +service.gui.CERT_INFO_FINGERPRINTS=Otisk service.gui.CERT_INFO_SER_NUM=Seriové číslo: service.gui.CERT_INFO_VER=Verze: service.gui.CERT_INFO_SIGN_ALG=Algorytmus podpisu: service.gui.CERT_INFO_ALG=Algorytmus: service.gui.CERT_INFO_PUB_KEY=Veřejný klíč: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytů: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bitů service.gui.CERT_INFO_EXP=Exponent: service.gui.CERT_INFO_KEY_SIZE=Velikost klíče service.gui.CERT_INFO_SIGN=Podpis: -service.gui.CONTINUE=Pokračovat service.gui.SHOW_CERT=Zobrazit certifikát service.gui.HIDE_CERT=Skrýt certifikát @@ -702,11 +674,9 @@ service.gui.security.SECURE_AUDIO=Zabezpečený zvuk service.gui.security.AUDIO_NOT_SECURED=Nezabezpečený zvuk service.gui.security.SECURE_VIDEO=Zabezpečené video service.gui.security.VIDEO_NOT_SECURED=Nezabezpečené video -service.gui.security.NO_VIDEO=Bez videa -service.gui.security.CIPHER=Šifra: {0} +service.gui.security.CALL_SECURED_TOOLTIP=Hovor je zabezpečen. Pro více informací klikni zde. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Nezabezpečený hovor. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Pro sdílení bezpečnostního kódu se svým protějškem, klikni zde. -service.gui.security.COMPARE_WITH_PARTNER=Prověřte s údaji od partnera a pak klikněte na "zámek" pro potvrzení. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Porovnání s partnerem: service.gui.security.STRING_COMPARED=Řetězce porovnány! @@ -724,19 +694,13 @@ service.gui.avatar.imagepicker.CLICK=Klik a úsměv service.gui.avatar.imagepicker.IMAGE_FILES=Soubor s obrázkem service.gui.avatar.imagepicker.IMAGE_PICKER=Obrázek service.gui.avatar.imagepicker.IMAGE_SIZE=Velikost obrázku -service.gui.avatar.imagepicker.INITIALIZING=Inicializuji service.gui.avatar.imagepicker.RESET=Resetovat service.gui.avatar.imagepicker.SET=Nastavení service.gui.avatar.imagepicker.TAKE_PHOTO=Vyfotit -service.gui.avatar.imagepicker.WEBCAM_ERROR=Chyba webkamery service.gui.security.encryption.required=Je nutné šifrování! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Chyba SIP v seznamu kontaktů impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Nezle přečíst zdroj {0}. Pro {1} @@ -759,9 +723,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=výběr sítě # LDAP impl.ldap.CONFIG_FORM_TITLE=LDAP impl.ldap.GENERAL=Obecné -impl.ldap.NEW=Nový impl.ldap.EDIT=upravit -impl.ldap.REMOVE=Odstranit impl.ldap.ENABLED=Povoleno impl.ldap.SERVER_NAME=Název připojení impl.ldap.SERVER_NAME_EXAMPLE=Můj LDAP server @@ -794,6 +756,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=Pevná Linka impl.ldap.PHONE_PREFIX=Prefix telefonů impl.ldap.PHONE_PREFIX_EXAMPLE=Např. 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Adresář plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Povolit prohledávání v adresáři Mac OS X @@ -804,9 +770,7 @@ plugin.addrbook.PREFIX_EXAMPLE=Např.: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google kontakty -impl.googlecontacts.NEW=Nový impl.googlecontacts.EDIT=upravit -impl.googlecontacts.REMOVE=Odebrat impl.googlecontacts.ENABLED=Povoleno impl.googlecontacts.ACCOUNT_NAME=Název účtu impl.googlecontacts.SAVE=Uložit @@ -845,13 +809,11 @@ plugin.accountinfo.ORGANIZATION=Organizace: plugin.accountinfo.JOB_TITLE=Pracovní zařazení: plugin.accountinfo.ABOUT_ME=O mě: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Obrázek plugin.accountinfo.GLOBAL_ICON=Použít obrázek účtu plugin.accountinfo.LOCAL_ICON=Použít tuto ikonu: -plugin.accountinfo.CHANGE=Změnit -plugin.accountinfo.ONLY_MESSAGE=Pouze zprávy # connection info +plugin.connectioninfo.TITLE=Informace o spojení # contact info plugin.contactinfo.TITLE=Detaily kontaktu @@ -868,49 +830,12 @@ plugin.aimaccregwizz.USERNAME=Jméno obrazovky AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Jméno obrazovky a heslo plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Zaregistrovat nový účet plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Pokud nemáte založen AIM účet, klikněte na toto tlačítko a účet založte. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Změnit výchozí nastavení serveru # branding plugin.branding.ABOUT_WINDOW_TITLE=O {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP a Rýchle správy -plugin.branding.LOADING=Načítám plugin.branding.ABOUT_MENU_ENTRY=&O programu -plugin.branding.WELCOME_MESSAGE=
    {1} je nyní intenzívně vyvíjen. Verze kterou máte spuštěnu je experimentální a NEMUSÍ PRACOVAT podle očekávání. Pro další informace prosím prohlédněte {2}.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Všechna práva vyhrazena. Více na https://jitsi.org.
    -plugin.branding.LICENSE=
    The Jitsi je šířen pod LGPL licencí (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Slovníky -plugin.dictaccregwizz.ANY_DICTIONARY=Libovolný slovník -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Libovolný slovník z {0} -plugin.dictaccregwizz.FIRST_MATCH=První výskyt -plugin.dictaccregwizz.NO_MATCH=Nenalezeno -plugin.dictaccregwizz.MATCH_RESULT=Definice "{0}" nebyla nalezena, neměli jste na mysli:\n -plugin.dictaccregwizz.INVALID_DATABASE=Slovník "{0}" již na serveru neexistuje. -plugin.dictaccregwizz.INVALID_STRATEGY=Současná strategie není na serveru dostupná. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Protokol služby -plugin.dictaccregwizz.HOST=Hostitel -plugin.dictaccregwizz.SERVER_INFO=Informace serveru -plugin.dictaccregwizz.STRATEGY_SELECTION=Výběr strategie -plugin.dictaccregwizz.STRATEGY_LIST=Seznam strategií: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Hledat strategii -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategie, díky rozdílnému přístupu, hledají podobná slova, pokud není nalezen přesný překlad. Například Prefix strategie bude hledatslova která začínají stejně jako slovo překládané. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informace o Dict účtu -plugin.dictaccregwizz.FIRST_ACCOUNT=Průvodce vytvoří váš první Dict účet na dict.org.\n\nPřechodem na "Průvodce registrací účtu" můžete přidat nový slovník. Do pole "host" vyplňte slovník, který chcete přidat. -plugin.dictaccregwizz.THREAD_CONNECT=Pokouším se připojit k serveru -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Pokus o spojení selhal, toto není Dict server nebo je offline -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Zjišťuji dostupné strategie -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Na serveru nebyla nalezena žádná strategie -plugin.dictaccregwizz.POPULATE_LIST=Zveřejňuji seznam -plugin.dictaccregwizz.CLOSING_CONNECTION=Zavírám spojení - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Pokud se chcete připojit k chatu na Facebook, musíte vytvořit/zadat "Uživatelské jméno"
    na stránce "Účet", "Nastavení účtu" na Facebooku.


    Poznámka: Po zadání uživatelského jména se musíte odhlásit z webovské stránky.
    and Může to nějakou dobu trvat, než se budete moci přihlísit pod nuvým uživatelským jménem!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protokol chatu Facebooku -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Jméno uživatele: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Jméno uživatele a heslo + # generalconfig plugin.generalconfig.AUTO_START=Automaticky spouštět {0} při spuštění PC @@ -921,9 +846,6 @@ plugin.generalconfig.SHOW_HISTORY=Zobrazit plugin.generalconfig.HISTORY_SIZE=posledních zpráv u nových konverzací plugin.generalconfig.SEND_MESSAGES_WITH=Odesílat zprávy pomocí stisku: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Přenést okno do popředí -plugin.generalconfig.ERROR_PERMISSION=Nemáte oprávnění zakázat automatické spouštění -plugin.generalconfig.TRANSPARENCY=Průhlednost -plugin.generalconfig.ENABLE_TRANSPARENCY=Povolit průhlednost plugin.generalconfig.DEFAULT_LANGUAGE=Jazyk uživatelského rozhraní plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Změny se projeví po restartu aplikace. plugin.generalconfig.SIP_CLIENT_PORT=Port SIP klienta @@ -937,6 +859,7 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Odstranit speciální znaky p plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Převést písmena na čísla plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=např. +420 800 VOLANI -> +420 800 865264 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Vzorkovací frekvence: plugin.generalconfig.OPUS_BITRATE=Průměrný datový tok enkodéru (v kbs): @@ -968,19 +891,21 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Zaregistrovat nový účet plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=IRC protocol. plugin.ircaccregwizz.USERNAME_AND_PASSWORD=UIN a heslo +plugin.ircaccregwizz.USERNAME=Přezdívka plugin.ircaccregwizz.INFO_PASSWORD=Většina IRC serverů nevyžaduje heslo. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Automaticky změnit přezdívku, pokud je již použita plugin.ircaccregwizz.USE_DEFAULT_PORT=Použít výchozí port plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=Moje přezdívka nevyžaduje identifikaci plugin.ircaccregwizz.HOST=Jméno serveru: plugin.ircaccregwizz.IRC_SERVER=Server +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autorizace +plugin.ircaccregwizz.SASL_USERNAME=Uživatelské Jméno # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Protokol XMPP plugin.jabberaccregwizz.USERNAME=Uživatelské jméno pro XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Heslo pro kontrolu -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID a heslo plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Připojit server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Povolit udržování sppojení @@ -996,13 +921,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Poznámka plugin.jabberaccregwizz.RESOURCE=Zdroj plugin.jabberaccregwizz.AUTORESOURCE=Automaticky vygenerované prostředky plugin.jabberaccregwizz.PRIORITY=Priorita -plugin.jabberaccregwizz.XMPP_ERROR=Chyba XMPP protokolu plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Neznámá chyba v XMPP ({0}). Ověřte jestli jste zadali správné jméno serveru. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Hesla se neshodují. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Změnit výchozí nastavení serveru -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Pokročilé možnosti plugin.jabberaccregwizz.USE_ICE=Použít ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Použít technologii Google Jingle/ICE (Experimentální) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Automaticky nalézt STUN/TURN servery plugin.jabberaccregwizz.SUPPORT_TURN=Podpora TURN plugin.jabberaccregwizz.TURN_USERNAME=Zvolte si uživatelské jméno @@ -1029,11 +950,8 @@ plugin.jabberaccregwizz.ALLOW_NON_SECURE=Povolit nezabezpečené připojení plugin.jabberaccregwizz.DTMF_AUTO=Auto: Automatický výběr mezi RTP a Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Volby serveru plugin.jabberaccregwizz.CHANGE_PASSWORD=Změnit heslo účtu -plugin.jabberaccregwizz.NEW_PASSWORD=Nové heslo -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Potvrzení hesla plugin.jabberaccregwizz.PORT_FIELD_INVALID=Vyplňte prosím správné číslo portu, aby jste mohl pokračovat. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Účet musí být přihlášen, před změnou hesla. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Není vyplněno heslo. plugin.jabberaccregwizz.TLS_REQUIRED=Připojení nepoužívá protokol TLS, proto nelze změnit vaše heslo. plugin.jabberaccregwizz.PASSWORD_CHANGED=Heslo bylo úspěšně změněno plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Váš XMPP server nepodporuje změnu vašeho hesla. @@ -1047,25 +965,9 @@ plugin.jabberaccregwizz.RESET=Vymazat plugin.jabberaccregwizz.RESET_DESCRIPTION=Obnovit globální nastavení plugin.jabberaccregwizz.DISABLE_JINGLE=Vypnout Jingle (hovory a video hovory s XMPP protokolem). -# mailbox -plugin.mailbox.OUTGOING=Odchozí zprávy: -plugin.mailbox.INCOMING=Příchozí zprávy: -plugin.mailbox.WAIT_TIME=Počkejte dokud nebude volání přesměrováno na hlasovou poštu -plugin.mailbox.MAX_MESSAGE_TIME=Maximální doba trvání příchozí zprávy -plugin.mailbox.CONFIRM=Potvrdit -plugin.mailbox.DEFAULTS=Výchozí nastavení -plugin.mailbox.MAILBOX=Poštovní schránka - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protokol pro připojení ke službě MSN. -plugin.msnaccregwizz.USERNAME=Email: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID a heslo - # plugin manager plugin.pluginmanager.INSTALL=Instalovat plugin.pluginmanager.UNINSTALL=Odinstalovat -plugin.pluginmanager.UPDATE=Aktualizovat plugin.pluginmanager.PLUGINS=Zásuvné moduly plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Výběr souboru @@ -1090,7 +992,6 @@ plugin.sipaccregwizz.SERVER_PORT=Port na serveru plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxy port plugin.sipaccregwizz.PREFERRED_TRANSPORT=Preferovaný transport -plugin.sipaccregwizz.ADVANCED_OPTIONS=Pokročilé možnosti plugin.sipaccregwizz.PROXY_OPTIONS=Nastavení proxy plugin.sipaccregwizz.PROXY_AUTO=Automatická konfigurace proxy serveru plugin.sipaccregwizz.ENABLE_PRESENCE=Povolit přítomnost (SIMPLE) @@ -1110,8 +1011,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Automaticky: Zvolí automaticky mezi RTP a Inband plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP informace plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Změnit defaultní nastavení serveru plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Povolit podporu šifrovaného spojení plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Uveďte podporu ZRTP v protokolu zabezpečení plugin.sipaccregwizz.AUTH_NAME=Jméno pro autorizaci @@ -1132,10 +1031,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI pro kontrolu hlasové schránky plugin.sipaccregwizz.NOT_SAME_PASSWORD=Hesla se neshodují. plugin.sipaccregwizz.NO_CERTIFICATE=(Použít běžné ověření.) plugin.sipaccregwizz.SAVP_OPTION=Indikace RTP / SVAP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Vypnout (pouze indikace RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Povinné (nabídnout a přijmout jen RTP / SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Volitelně (první nabídnout RTP / SAVP, pak RTP / AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Povolit S-Descriptor (znám taky jako SDES nebo SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Zvolte povolené šifrování protokolů a jejich priority (horní protokol jako první): plugin.sipaccregwizz.CIPHER_SUITES=Povolené šifrování: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} se automaticky pokusí zabezpečit všechny své hovory pomocí ZRTP a oba uvidíte a uslyšíte oznámení jen jednou, že zabezpečené spojení bylo navázáno. Pokud jste si dobře vědomi toho, co děláte mohli byste změnit upřesňující nastavení níže.
    @@ -1149,15 +1048,6 @@ plugin.skinmanager.DEFAULT_SKIN=Výchozí skin plugin.skinmanager.ADD_NEW_SKIN=Přidat nový skin plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Výchozí skin aplikace -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Protokol k připojení vzdáleného počítače přes SSH. -plugin.sshaccregwizz.USERNAME=ID účtu: -plugin.sshaccregwizz.IDENTITY_FILE=Soubor s indentitou: -plugin.sshaccregwizz.KNOWN_HOSTS=Známí hosté: -plugin.sshaccregwizz.OPTIONAL=Volitelné -plugin.sshaccregwizz.ACCOUNT_DETAILS=Detaily účtu - # status update plugin.autoaway.AUTO_STATUS=Automaticky pryč plugin.autoaway.ENABLE_CHANGE_STATUS=Nastavit stav při nepřítomnosti @@ -1204,22 +1094,6 @@ plugin.whiteboard.DESELECT=Odznačit plugin.whiteboard.DELETE=Smazat plugin.whiteboard.PROPERTIES=Vlastnosti -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protokol pro připojení ke službě Yahoo!. -plugin.yahooaccregwizz.USERNAME=Jméno uživatele: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID a heslo - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Protokol služby Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Jméno: -plugin.zeroaccregwizz.LAST_NAME=Příjmení: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Zapamatovat si Bonjour kontakty? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID a heslo -plugin.zeroaccregwizz.USERID=ID uživatele - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Protokol služby Google Talk @@ -1233,19 +1107,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, portál o IP telefonii plugin.iptelaccregwizz.USERNAME=Jméno uživatele plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Zaregistrovat na iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP a Chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Uživatelské jméno plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Opakování hesla plugin.sip2sipaccregwizz.EMAIL=E-mailová adresa -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Pro nápovědu k této službě prosím navštivte
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=e-mailová adresa pro odeslání hlasové zprávy,
    informacím o nepřijatých voláních a pro obnovení zapomenutého hesla -plugin.sip2sipaccregwizz.INFO_NOTE=Pro nápovědu k této službě navštivte prosím http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Existující "sip2sip.info" účet -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Vytvořit nový volný účet na "sip2sip.info" - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP a Rychlé zprávy plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Pro nápovědu k této službě prosím navštivte stránky:
    http://www.ippi.com/ @@ -1254,6 +1120,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Existující IPPI účet plugin.ippiaccregwizz.CREATE_ACCOUNT=Vytvořit zdarma nový IPPI účet # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Zavřít okno chatu plugin.keybindings.CHAT_COPY=Kopírovat plugin.keybindings.CHAT_CUT=Vyjmout @@ -1276,15 +1143,16 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Akce plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primární zkratka plugin.keybindings.globalchooser.SHORTCUT_SECOND=Sekundární zkratka plugin.keybindings.globalchooser.PRESS_BTN=Stiskněte pro nastavení zkratky -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Čeká se plugin.keybindings.globalchooser.PUSH_TO_TALK=Funkce Push to talk plugin.keybindings.globalchooser.ENABLE_SPECIAL=Povolit speciální detekci klávesy plugin.keybindings.PLUGIN_NAME=Klávesové zkratky +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Konverzace plugin.keybindings.MAIN=Hlavní plugin.keybindings.GLOBAL=Globální zkratky # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=Povolit plugin.notificationconfig.DESCRIPTION=Popis plugin.notificationconfig.TURN_ON_ALL=Všechno zapnout plugin.notificationconfig.TURN_OFF_ALL=Všechno vypnout @@ -1306,6 +1174,7 @@ plugin.notificationconfig.tableheader.SOUND=Přehrát zvuk na výstupu pro notif plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Přehrát zvuk plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Přehrát zvuk na PC speakeru plugin.notificationconfig.tableheader.DESCRIPTION=Popis akce +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Příchozí hovor plugin.notificationconfig.event.SecurityMessage=Bezpečnostní zpráva plugin.notificationconfig.event.IncomingFile=Příchozí soubor @@ -1407,6 +1276,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Pravidelné vnitřní načítání impl.neomedia.configform.H264.defaultProfile=Výchozí profil pro kódování do: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Základní osnova impl.neomedia.configform.H264.defaultProfile.high=Vysoká kvalita impl.neomedia.configform.H264.defaultProfile.main=Hlavní @@ -1437,7 +1307,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Současné heslo: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Zadejte nové heslo: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Znovu zadejte heslo: plugin.securityconfig.masterpassword.MP_TITLE=Hlavní heslo -plugin.securityconfig.masterpassword.MP_NOT_SET=(není nastaveno) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Nezadali jste správné (a platné) hlavní heslo. Zkuste to prosím znovu. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Hlavní heslo není správné! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Změna hesla se nezdařila @@ -1453,7 +1322,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Heslo plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(neznámý) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nelze dešifrovat) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Uložená hesla -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Odebrat plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Odebrat vše plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Opravdu si přejete odebrat všechna hesla? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Odebrání všech hesel @@ -1466,6 +1334,7 @@ plugin.securityconfig.masterpassword.MP_INPUT=Prosím zadejte hlavní heslo:\n\n plugin.otr.menu.TITLE=Zabezpečený chat plugin.otr.menu.START_OTR=Zahájit soukromou komunikaci plugin.otr.menu.END_OTR=Ukončit soukromou komunikaci +plugin.otr.menu.VERIFIED=Vaše soukromá konverzace je ověřena plugin.otr.menu.LOADING_OTR=Zahajuje se soukromá konverzace... plugin.otr.menu.TIMED_OUT=Čas pro zahájení konverzace vypršel. plugin.otr.menu.REFRESH_OTR=Občerstvit soukromou kominukaci @@ -1519,7 +1388,6 @@ plugin.globalproxy.PROXY_PORT=Proxy port plugin.globalproxy.PROXY_USERNAME=Uživatelské jméno pro proxy plugin.globalproxy.PROXY_PASSWORD=Heslo pro proxy plugin.globalproxy.DESCRIPTION={0} bude používat toto nastavení proxy pro veškerá nová nebo obnovená spojení. \nPodpora proxy je experimentální a nemusí pracovat správně se všemi protokoly. Pro více detailů srovnejte s tabulkou níže. -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Autorizace HTTP HTTP+Autorizace
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Také proxy DNS plugin.globalproxy.FWD_DNS_NOTE=Použitelné u Tor. Pomáhá se vyhnout DNS netěsnostem při přesměrovávaní veškerého provozu DNS na Tor proxy. Vyžaduje restart. @@ -1536,6 +1404,8 @@ plugin.reconnectplugin.NETWORK_DOWN=Síťové spojení bylo ztraceno! plugin.chatconfig.TITLE=Konverzace plugin.chatconfig.replacement.TITLE=Obrázek/Video plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Povolit v chatu smajlíky +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Povolit výměnu obrázku/videa +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Povolit plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Zdroje: plugin.chatconfig.spellcheck.TITLE=Kontrola pravopisu @@ -1552,7 +1422,6 @@ plugin.provisioning.RESTART_WARNING=Upozorňujeme, že změny se projeví až p plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Kopírovat UUID do schránky plugin.provisioning.CLIPBOARD_FAILED=Kopírování UUID do schránky selhalo -plugin.provisioning.EXIT_ON_FAIL=Vypnout aplikaci v případě chyby autokonfigurace plugin.provisioning.CREDENTIALS=Uložené přihlašovací údaje plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Skutečně si přejete z nastavení autokonfigurace vymazat uložené heslo? plugin.provisioning.PROV_FAILED=Autokonfigurace selhala @@ -1619,8 +1488,6 @@ util.dns.DNSSEC_WARNING=
    {0} se pokusil připojit k server #plugin spellcheck plugin.spellcheck.TITLE=Kontrola překlepů a gramatiky plugin.spellcheck.MENU=Zobrazit kontrolu pravopisu a gramatiky -plugin.spellcheck.LANG=Jazyk -plugin.spellcheck.EDIT_PERSONAL_DICT=Upravit plugin.spellcheck.ENABLE_SPELL_CHECK=Aktivovat kontrolu pravopisu plugin.spellcheck.dialog.FIND=Najít další plugin.spellcheck.dialog.REPLACE=Nahradit -- cgit v1.1 From 0a0acb7c9dc1b1a12753cec58ab86aeffc9ddfbe Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:10 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1494 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_zh_CN.properties | 469 ++++++++++--------------- 1 file changed, 187 insertions(+), 282 deletions(-) diff --git a/resources/languages/resources_zh_CN.properties b/resources/languages/resources_zh_CN.properties index ebd3026..ad854c2 100644 --- a/resources/languages/resources_zh_CN.properties +++ b/resources/languages/resources_zh_CN.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -25,92 +36,84 @@ # from your system's language, pass the language code to ant: # ant -Duser.language=xx run -service.gui.ABOUT=关于 -service.gui.ACCEPT=接受 +service.gui.ABOUT=关于 (&A) +service.gui.ACCEPT=接受 (&A) service.gui.ACCOUNT=帐户 service.gui.ACCOUNT_ME=自己 service.gui.ACCOUNT_REGISTRATION_WIZARD=帐号注册向导 service.gui.ACCOUNTS=帐号 service.gui.ADD=添加 -service.gui.ADD_ACCOUNT=添加帐号 service.gui.ADD_CONTACT=添加联系人 -service.gui.ADD_AUTHORIZED_CONTACT=添加{0}到你的通讯簿上 +service.gui.ADD_AUTHORIZED_CONTACT=将{0}添加到通讯录 service.gui.ADD_CONTACT_TO_CONTACTLIST=将此联系人添加到您的联系人列表中 service.gui.ADD_CONTACT_TO=添加联系人到 -service.gui.ADD_CONTACT_ERROR=添加联系人:{0}失败 +service.gui.ADD_CONTACT_ERROR=添加以下联系人是失败:{0} service.gui.ADD_CONTACT_ERROR_TITLE=添加联系人错误 -service.gui.ADD_CONTACT_EXIST_ERROR=联系人{0}已经存在于您的联系人名单中了。 -service.gui.ADD_CONTACT_NETWORK_ERROR=服务器未能响应你添加联系人ID为{0}的联系人的请求。 -service.gui.ADD_CONTACT_NOT_SUPPORTED=无法添加联系人Id为{0}的联系人。不支持此操作。 -service.gui.ADD_CONTACT_IDENTIFIER=请在下面输入栏中输入您想要添加的联系人的称呼。 -service.gui.ADD_CONTACT_WIZARD=添加联系人向导 -service.gui.ADD_CONTACT_NOT_CONNECTED=你需要连接以便添加联系人。请选择一个连接类型并重试。 -service.gui.ADD_GROUP_LOCAL_ERROR=添加组:{0} 失败。错误出自本地IO操作。 +service.gui.ADD_CONTACT_EXIST_ERROR=联系人{0}在通讯录中已存在。 +service.gui.ADD_CONTACT_NETWORK_ERROR=服务器未响应您添加以下联系人的请求:{0} +service.gui.ADD_CONTACT_NOT_SUPPORTED=添加联系人{0}失败。不支持的操作。 +service.gui.ADD_CONTACT_NOT_CONNECTED=添加联系人时您必须处于连接状态。请登录到选择的服务提供商并重试。 +service.gui.ADD_GROUP_LOCAL_ERROR=添加组:{0} 失败。本地IO时发生错误。 service.gui.ADD_GROUP_EXIST_ERROR=组 {0} 已经存在于您的联系人名单中了。请选择另一个名称。 service.gui.ADD_GROUP_NET_ERROR=添加组:{0} 失败。网络错误。请检查您的网络连接然后重试。 service.gui.ADD_GROUP_ERROR=添加组:{0}失败。 service.gui.ADD_GROUP_EMPTY_NAME=组名称不能为空。 -service.gui.ADD_GROUP=创建组 -service.gui.ADD_SUBCONTACT=添加紧急联络人 service.gui.ADDRESS=地址 service.gui.ADMINISTRATOR=管理员 service.gui.ADVANCED=高级 -service.gui.ALL=所有 service.gui.ALL_CONTACTS=所有联系人 service.gui.ALTERNATE_ADDRESS=备用地址 service.gui.APPLY=应用 -service.gui.ARE_CALLING={0}正被呼叫。。。 +service.gui.ARE_CALLING={0}正在呼叫。。。 service.gui.ARE_NOW=你现在是{0} service.gui.AT=位于 -service.gui.AUTHORIZE=认证 -service.gui.AUTHORIZATION_ACCEPTED={0}已经接受您的身份验证请求。 +service.gui.AUTHORIZE=身份验证 +service.gui.AUTHORIZATION_ACCEPTED={0}已接受您的身份验证请求。 service.gui.AUTHENTICATION_FAILED=帐号{0}身份验证失败。您输入的密码错误。 -service.gui.AUTHENTICATION_REQUESTED=认证请求已被响应 -service.gui.AUTHENTICATION_REQUESTED_SERVER=服务器 {0} 已响应您的验证请求。 -service.gui.AUTHENTICATION_REJECTED={0}已经拒绝您的身份验证请求。 -service.gui.AUTHENTICATION_WINDOW_TITLE={0}验证 -service.gui.AUTHORIZATION_REQUESTED=请求验证已被响应 -service.gui.AUTHORIZATION_REQUESTED_INFO=联系人 {0} 需要您提供验证信息。 -service.gui.AUTHORIZATION_RESPONSE=认证响应 +service.gui.AUTHENTICATION_REQUESTED_SERVER=服务器 {0} 已发送了您的身份验证请求。 +service.gui.AUTHENTICATION_REJECTED={0 }已拒绝了您的身份验证请求。 +service.gui.AUTHENTICATION_WINDOW_TITLE={0} 身份验证 +service.gui.AUTHORIZATION_REQUESTED=请求身份验证 +service.gui.AUTHORIZATION_REQUESTED_INFO=联系人 {0} 请求您通过身份验证。 +service.gui.AUTHORIZATION_RESPONSE=身份验证回复 service.gui.AWAY_STATUS=离开 -service.gui.EXTENDED_AWAY_STATUS=离开 +service.gui.EXTENDED_AWAY_STATUS=远远离开 service.gui.BAN=禁止 -service.gui.BANNED=禁止 +service.gui.BANNED=已禁止 service.gui.BAN_FAILED=禁止操作失败 -service.gui.BAN_FAILED_GENERAL_ERROR=阻止 {0} 失败。服务器一般性错误。 -service.gui.BAN_FAILED_NOT_ALLOWED=禁止{0} 失败。聊天室的创建人或管理员不能被禁止。 +service.gui.BAN_FAILED_GENERAL_ERROR=禁止 {0} 失败。发生一般性服务器错误。 +service.gui.BAN_FAILED_NOT_ALLOWED=禁止{0} 失败。聊天室的所有人和管理员不能被禁止。 service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS=禁止{0}失败。您没有相关权限。 -service.gui.BRB_MESSAGE=本人不在,稍后回来。 +service.gui.BRB_MESSAGE=我现在不在,稍后回来。 service.gui.BROWSE=浏览 -service.gui.BUSY_MESSAGE=抱歉,业务正忙。 -service.gui.BUSY_STATUS=忙 +service.gui.BUSY_MESSAGE=抱歉,我现在有点忙。 +service.gui.BUSY_STATUS=占线 service.gui.CALL=呼叫 service.gui.CALL_CONTACT=呼叫联系人 service.gui.CALL_FAILED=呼叫失败 -service.gui.CALL_HISTORY_TOOL_TIP=点击这里显示呼叫历史 -service.gui.CALL_HISTORY_GROUP_NAME=呼叫记录 -service.gui.CALL_VIA=转接呼叫: -service.gui.CALL_NAME_OR_NUMBER=呼叫名称或号码 -service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=本次呼叫仅允许来自{0}网络的您的联系人帐号{1}。{2}不属于该网络或此帐户不存在。 -service.gui.CALL_WITH=呼叫对话 -service.gui.CALL_NO_AUDIO_DEVICE=无音频设备,请设置。 -service.gui.CALL_NO_AUDIO_CODEC=无可用的音频编码方案,请添加或启用。 -service.gui.CALL_NO_DEVICE_CODECS_Q=您需要继续此呼叫么? +service.gui.CALL_HISTORY_TOOL_TIP=点击这里显示通话记录 +service.gui.CALL_HISTORY_GROUP_NAME=通话记录 +service.gui.CALL_VIA=通话方式: +service.gui.CALL_NAME_OR_NUMBER=通话名称或号码 +service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=此通话仅支持来自网络{0}以及您的账户{1}的参与者。{2}不属于这个网络或账户。 +service.gui.CALL_WITH=通话 +service.gui.CALL_NO_AUDIO_DEVICE=您没有配置音频设备。 +service.gui.CALL_NO_AUDIO_CODEC=您没有启用任何音频编码器。 +service.gui.CALL_NO_DEVICE_CODECS_Q=您要继续进行呼叫吗? service.gui.CANCEL=取消 service.gui.CHAT=聊天 service.gui.CHANGE_FONT=更改字体 -service.gui.CHANGE_ROOM_SUBJECT=修改聊天室标题... -service.gui.CHANGE_ROOM_SUBJECT_LABEL=请在下面的输入框内,您可以输入聊天室的新名称。 +service.gui.CHANGE_ROOM_SUBJECT=修改聊天室主题... +service.gui.CHANGE_ROOM_SUBJECT_LABEL=您可以在下方输入本聊天室的新主题。 service.gui.CHANGE_NICK=更改昵称 -service.gui.CHANGE_NICKNAME=修改昵称... -service.gui.CHANGE_NICKNAME_LABEL=请在下面的输入框内,您可以输入您的新昵称。 +service.gui.CHANGE_NICKNAME=更改昵称... +service.gui.CHANGE_NICKNAME_LABEL=您可以在下方输入新的昵称。 service.gui.CHANGE_NICKNAME_ERROR=更改昵称时出错 -service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=昵称存在重复 -service.gui.CHANGE_VIDEO_QUALITY=改变远端视频质量 -service.gui.CHAT_CONFERENCE_LABEL=会议 -service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}的会议 -service.gui.CHAT_ROOM_ALREADY_JOINED={0}已加入聊天室。 -service.gui.CHAT_ROOM_CONFIGURATION={0}聊天室的配置信息 +service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=昵称已存在 +service.gui.CHANGE_VIDEO_QUALITY=更改远程视频质量 +service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} 的会议 +service.gui.CHAT_ROOM_ALREADY_JOINED=聊天室 {0} 您已经加入。 +service.gui.CHAT_ROOM_CONFIGURATION=聊天室 {0} 配置 service.gui.CHAT_ROOM_CONFIGURATION_FAILED=获取聊天室 {0} 配置失败。 service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=不能获取{0}聊天室配置信息。只有聊天室拥有者可以浏览变更此配置信息。 service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=当提交聊天室{0}的配置时发生错误。 @@ -118,31 +121,28 @@ service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=编辑成员列表 service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=列在右侧的用户将拥有此聊天室成员角色。当聊天室被设置为“仅成员”模式时仅这些用户被允许加入。 service.gui.CHAT_ROOM_USER_JOINED=已加入 {0} service.gui.CHAT_ROOM_USER_LEFT=已离开 {0} -service.gui.CHAT_ROOM_USER_KICKED=被逐出 {0} +service.gui.CHAT_ROOM_USER_KICKED=已被踢出 {0} service.gui.CHAT_ROOM_USER_QUIT=已退出 {0} -service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=消息发送被拒(语音被撤销) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=收藏聊天室,以便将来使用 -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=从聊天室收藏目录移除选择的聊天室 +service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=消息发送被拒绝 (语音被撤销) service.gui.CHAT_ROOM_NAME=聊天室名 service.gui.CLEAR_CUSTOM_MESSAGES=清除临时消息 service.gui.ROOM_NAME=聊天室 -service.gui.AUTOJOIN=自动加入 service.gui.CHANGE_PASSWORD=修改密码 service.gui.CHAT_ROOM_NAME_INFO=请在下面输入栏中输入您想要创建的聊天室名称。 service.gui.CHAT_ROOM_NOT_EXIST=在服务器{1}上找不到聊天室 {0}。请检查你的输入是否正确。 service.gui.CHAT_ROOM_NOT_CONNECTED=您必须先登录服务器才能加入{0}聊天室。 service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=您必须先登录上服务器才能退出聊天室。 -service.gui.CHAT_ROOM_NOT_JOINED=您需要先进入聊天室, 然后才能做进一步操作。 service.gui.CHAT_ROOM_OPTIONS=聊天室选项 service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=需要注册才能加入聊天室{0}。 -service.gui.CHAT_ROOM_REQUIRES_PASSWORD=聊天室{0}需凭密码登入。 +service.gui.CHAT_ROOM_REQUIRES_PASSWORD=聊天室 {0} 要求输入密码。 service.gui.CHAT_ROOMS=聊天室 service.gui.CHAT_ROOM=聊天室 -service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} 已经更换了新主题 {1} -service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=您可在下列聊天室:{0}继续您的会话 +service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} 已将聊天室主题更改为 {1} +service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=您可下列聊天室继续您的会话:{0} +service.gui.CHAT_NICKNAME_CHANGE={0} 现在是 {1} service.gui.CHOOSE_CONTACT=选择联系人 service.gui.CHOOSE_NUMBER=选择号码 -service.gui.CHOOSE_ACCOUNT=请从帐号列表选择一个帐号。 +service.gui.CHOOSE_ACCOUNT=请从列表中选择一个帐号。 service.gui.CITY=城市 service.gui.COUNTRY=国家 service.gui.SHOW_MORE_TOOLTIP=点击查看更多结果 @@ -150,22 +150,20 @@ service.gui.CLEAR=清除 service.gui.CLOSE=关闭 service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=您2秒前刚收到新消息。是否要结束本次聊天? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=有进行中的文件传输。你要取消它们吗? -service.gui.CONFIRM=确认 service.gui.CONNECTED_STATUS=已连接 service.gui.CONNECTING=连接中... service.gui.CONNECTING_STATUS=连接中 service.gui.CONNECTING_EARLY_MEDIA_STATUS=连接中* service.gui.CONNECTION=连接 -service.gui.CONNECTION_FAILED_MSG=账号登录失败:用户名:{0};服务器名:{1}。请检查您的网络连接或联系管理员寻求更多信息。 service.gui.CONNECTION_EXPIRED_MSG=您已经断开与服务器 {0} 的连接。 service.gui.CONTACT_NAME=ID或号码 -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=您选择的联系人{0}不支持通话。 +service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com +service.gui.CONTACT_NAME_INFO=添加一个及时通讯地址 (比如 jane.doe@example.com)或者 VoIP 号码 service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=您选择的联系人{0}不支持群聊。 service.gui.CONTACT_PAUSED_TYPING={0} 暂停输入 service.gui.CONTACT_TYPING={0} 正在输入消息 -service.gui.CONTACT_TYPING_SEND_FAILED=啊-哦...我们不能向{0}宣告你正在书写 +service.gui.CONTACT_TYPING_SEND_FAILED=啊-哦...我们不能向 {0} 宣告你正在键入 service.gui.CONTACT_INFO=联系人信息 -service.gui.CONTACTLIST=联系人目录 service.gui.CONTACTS=联系人 service.gui.COPY=复制(&C) service.gui.COPY_LINK=复制链接(&L) @@ -175,33 +173,32 @@ service.gui.CREATE_CHAT_ROOM=创建聊天室(&C)... service.gui.CREATE_CHAT_ROOM_ERROR=创建聊天室 {0} 失败. service.gui.CREATE_CHAT_ROOM_WIZARD=聊天室新建向导 service.gui.CREATE_CONFERENCE_CALL=创建聊天室(&C) -service.gui.CREATE_CONFERENCE_CHAT=创建聊天室(&C) service.gui.CREATE_GROUP=新建组(&C) service.gui.CREATE_GROUP_NAME=请在下面输入栏中输入您想要创建的组名. -service.gui.CREATE_FIRST_GROUP_WIZARD=您的联系人名单中没有任何组. 请创建一个组 (文件/新建组). service.gui.CREATE_VIDEO_BRIDGE=创建视频桥接中... service.gui.CREATE_VIDEO_BRIDGE_MENU=创建视频桥接 service.gui.CREATE_JOIN_VIDEO_CONFERENCE=创建/加入视频会议 service.gui.CREATE_VIDEO_CONFERENCE=为此聊天室创建一个新的视频会议 service.gui.CONTACT_INFO_NOT_SUPPORTED=该联系人不支持网络名片 service.gui.CUT=剪切(&U) -service.gui.DATE=日期 service.gui.DELETE=删除 service.gui.DENY=拒绝(&D) service.gui.DESKTOP_SHARING_WARNING=您确定要开始屏幕共享?
    点击确定将允许对方查看您的屏幕. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=您正在共享屏幕 service.gui.DIALPAD=拨号面板 service.gui.DISPLAY_NAME=显示名称 +service.gui.DISPLAY_NAME_PROMPT=Jane Doe +service.gui.DISPLAY_NAME_INFO=为这个联系人添加一个名称。如果留空的话,将会使用及时通讯地址或 VoIP 填补。(可选) service.gui.DISCONNECTED_STATUS=已断开 service.gui.DND_STATUS=请别打扰 service.gui.DO_NOT_ASK_AGAIN=请不要重复询问 service.gui.DO_NOT_SHOW_AGAIN=请不要重复此消息 -service.gui.DOWNLOAD_NOW=马上下载(&D) service.gui.DRAG_FOR_SHARING=将任何你想共享的东西拖动到这里... service.gui.DURATION=持续时间 service.gui.DESTROY_CHATROOM=撤销聊天室 service.gui.DESTROY_MESSAGE=告知其他参与者,请输入一个理由和加入替代聊天室地址。 service.gui.EDIT=编辑(&E) -service.gui.EDITED_AT={0}正在录入 +service.gui.EDITED_AT=编辑于 {0} service.gui.EMAIL=Email service.gui.EMAILS=电子邮件 service.gui.EMPTY_HISTORY=清空历史(&E) @@ -216,7 +213,6 @@ service.gui.ERROR_RECEIVED_FROM=从{0}处收到错误信息 service.gui.ESTIMATED_TIME=估计时间: service.gui.EVENTS=事件 service.gui.EXIT=退出(&E) -service.gui.EXTENDED_CRITERIA=延时标准 service.gui.GENERAL=通用 service.gui.GENERAL_ERROR=一般错误 service.gui.GROUP_NAME=组名 @@ -253,24 +249,23 @@ service.gui.FOLDER_OPEN_NO_APPLICATION=无法找到应用程序打开这个文 service.gui.FONT=字体 service.gui.FONT_BOLD=粗体 service.gui.FONT_COLOR=颜色 -service.gui.FONT_FAMILY=类型 +service.gui.FONT_FAMILY=家族 service.gui.FONT_ITALIC=斜体 service.gui.FONT_SIZE=大小 -service.gui.FONT_STYLE=风格 +service.gui.FONT_STYLE=样式 service.gui.FONT_UNDERLINE=下划线 -service.gui.FROM=从{1}到{0} service.gui.GRANT_OWNERSHIP=授予所有权 service.gui.GRANT_ADMIN=授予管理权 -service.gui.GRANT_MODERATOR=授予群主权限 +service.gui.GRANT_MODERATOR=授予主持人权限 service.gui.GRANT_MEMBERSHIP=授予成员权限 -service.gui.GRANT_VOICE=允许发言 -service.gui.GUEST=访问者 +service.gui.GRANT_VOICE=授予语音权限 +service.gui.GUEST=访客 service.gui.HANG_UP=挂断 service.gui.HD_QUALITY=HD视频 service.gui.HELP=帮助(&H) service.gui.HIDE=隐藏 service.gui.HIDE_OFFLINE_CONTACTS=隐藏离线联系人 -service.gui.HIDE_MAIN_WINDOW=
    点击快捷键 X 隐藏窗口。
    如果需要退出,请选择 文件/退出。
    +service.gui.HIDE_MAIN_WINDOW=
    单击窗口上的X只会隐藏窗口,而不会真正退出程序。
    如果您要退出程序,请选择”文件/退出“命令。
    service.gui.HISTORY=历史(&H) service.gui.HISTORY_CONTACT=历史记录 - {0} service.gui.HISTORY_TOGGLE_PER_CONTACT=关闭此联系人操作历史 @@ -284,20 +279,21 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=您确认想要永久删除本地存储 service.gui.HISTORY_REMOVE_ERROR=删除本地存储消息时出错。 service.gui.HOME=首页 service.gui.HOME_PAGE=主页 -service.gui.HOUR=时 service.gui.ICE=ICE service.gui.IDENTIFIER=称呼 service.gui.IGNORE=忽略(&I) service.gui.INSERT_SMILEY=表情 -service.gui.INCOMING_CALL=来自{0}的呼叫请求 +service.gui.INCOMING_CALL=来自{0}的通话请求 +service.gui.INCOMING_SCREEN_SHARE=收到屏幕共享请求,来自:{0} service.gui.INCOMING_CALL_STATUS=来电 -service.gui.INSTANT_MESSAGINGS=短信 -service.gui.IM=即時聊天 -service.gui.INITIATING_CALL_STATUS=初始化呼叫 -service.gui.INVITATION=邀请 +service.gui.INCOMING_SCREEN_SHARE_STATUS=传入的屏幕共享请求 +service.gui.INSTANT_MESSAGINGS=即时聊天 +service.gui.IM=即时聊天 +service.gui.INITIATING_CALL_STATUS=正在初始化呼叫 +service.gui.INVITATION=邀请文本 service.gui.INVITATION_RECEIVED=收到邀请 -service.gui.INVITATION_RECEIVED_MSG={0} 邀请 {1} 加入聊天室. 您可以选择同意, 拒绝或者忽略这个邀请. -service.gui.INVITATION_REJECTED={0}已经拒绝您的加入聊天室邀请。原因:{1}。 +service.gui.INVITATION_RECEIVED_MSG={0} 邀请您加入聊天室{1}。您可以选择同意,拒绝或忽略此邀请。 +service.gui.INVITATION_REJECTED={0} 已经拒绝您的加入聊天室邀请。原因:{1}。 service.gui.INVITE=邀请(&I) service.gui.INVITE_CONTACT_MSG=如果想进行精确查找, 请输入该用户的名称. service.gui.INVITE_CONTACT_TO_CHAT=邀请其他联系人加入聊天 @@ -306,13 +302,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=邀请联系人视频桥接 service.gui.INVITE_REASON=邀请理由 service.gui.IS_CALLING={0}正在呼叫... service.gui.IS_NOW={0}已更名为{1} -service.gui.JITSI_WARNING=SIP Communicator 最近已经更名为 Jitsi.
    如果您想保持您的版本最新,请下载Jitsi.

    给您带来的不便敬请谅解.

    Jitsi 开发小组 -service.gui.JITSI_WARNING_TITLE=SIP Communicator 已更名为 Jitsi service.gui.JOIN=加入(&J) -service.gui.JOIN_AS=选择名称加入(&O) -service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=加入一个就绪的视频会议 +service.gui.JOIN_AS=加入为(&O) +service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=加入现有的视频会议 service.gui.JOIN_VIDEO=加入视频会话 -service.gui.CLOSE_CHAT_ROOM_DIALOG=关闭(&L) service.gui.JOB_TITLE=职位 service.gui.JOIN_CHAT_ROOM=加入聊天室(&J)... service.gui.JOIN_CHAT_ROOM_TITLE=加入聊天室 @@ -325,14 +318,13 @@ service.gui.KICK_FAILED=踢出操作失败 service.gui.KICK_FAILED_GENERAL_ERROR=踢出 {0} 失败, 服务器出错. service.gui.KICK_FAILED_NOT_ALLOWED=踢出 {0} 失败, 聊天室的创建人或管理员不能被踢出。 service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=踢出 {0} 失败, 您没有权限。 -service.gui.LAST=上一个 -service.gui.LAST_NAME=姓 +service.gui.LAST_NAME=您的姓氏 service.gui.LEAVE=离开(&L) service.gui.LIMIT_REACHED_FOR_IP=本地IP地址注册账户过多, 服务器 {0} 不能接受更多注册. service.gui.LIST=所有聊天室 service.gui.LOADING_ROOMS=载入中... service.gui.LOADING=正在加载... -service.gui.LOCALLY_ON_HOLD_STATUS=本地挂起 +service.gui.LOCALLY_ON_HOLD_STATUS=本地正呼叫等待中 service.gui.LOGIN_NETWORK_ERROR=由于网络连接原因,登录失败:用户名:{0},服务器:{1}.请检查网络连接. service.gui.LOGIN_GENERAL_ERROR=登录账户出错: 用户名: {0}, 服务器名: {1}. service.gui.LOGIN_INTERNAL_ERROR=登录错误,用户名:{0},服务器:{1}。这应该是一个应用程序内部错误。请通过开发者邮件列表将问题报告给我们(dev@jitsi.java.net)。 @@ -340,12 +332,11 @@ service.gui.LOGIN_INVALID_PROPERTIES_ERROR=由于帐号配置问题,登录失 service.gui.LOGOFF_NOT_SUCCEEDED=退出账户出错: 用户名: {0}, 服务器名: {1}. service.gui.LOW_QUALITY=低品质 service.gui.MEMBER=成员 -service.gui.MERGE_TO_CALL=合并呼叫 +service.gui.MERGE_TO_CALL=合并所有通话 service.gui.MESSAGE=消息 service.gui.MISSED_CALLS_TOOL_TIP=未接来电来自: service.gui.MISSED_CALLS_MORE_TOOL_TIP= 还有{0}条 -service.gui.MODERATOR=群主 -service.gui.MORE=查看更多 +service.gui.MODERATOR=主持人 service.gui.MORE_LABEL=展开 service.gui.MOVE=移动 service.gui.MOVE_SUBCONTACT=移动联系人 @@ -354,12 +345,12 @@ service.gui.MOVE_SUBCONTACT_FAILED=您选择的联系人已经存在。\n请重 service.gui.MOVE_SUBCONTACT_QUESTION=您确认要将{0}移动到{1}? service.gui.MOVE_TO_GROUP=移动到组(&M) service.gui.MOVE_CONTACT=移动联系人 -service.gui.MOVE_CONTACT_ERROR=联系人不能被移动(&C) service.gui.MSG_DELIVERY_FAILURE=上面消息发送失败 service.gui.MSG_DELIVERY_NOT_SUPPORTED=您正在使用的协议不支持离线消息。 请尝试其他协议联系{0}或者等待他/她上线。 service.gui.MSG_DELIVERY_INTERNAL_ERROR=内部出错。可能是程序自身错误。请提交您的错误报告到:http://www.jitsi.org/index.php/Development/BugsAndIssues。 service.gui.MSG_DELIVERY_ERROR=发送消息失败。 service.gui.MSG_DELIVERY_UNKNOWN_ERROR=发送消息失败, 未知错误. +service.gui.MSG_DELIVERY_UNSUPPORTED_OPERATION=不支持的操作。 service.gui.MSG_NOT_DELIVERED=网络错误。请检查网络配置然后重试。 service.gui.MSG_NOT_POSSIBLE=无法给该联系人发消息(协议不支持) service.gui.MSG_RECEIVED={0} 发送消息给你了 @@ -367,9 +358,8 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=请先登录服务器, 然后发送消 service.gui.MULTIPLE_LOGINS=账号在其他地方登录, 本地连接断开: 用户名: {0}, 服务器: {1}. service.gui.MY_CHAT_ROOMS=聊天室 service.gui.MY_CHAT_ROOMS_TITLE=聊天室 -service.gui.MUTE=静音 -service.gui.MUTUALLY_ON_HOLD_STATUS=挂起(双方) -service.gui.NAME=姓名 +service.gui.MUTUALLY_ON_HOLD_STATUS=呼叫等待静音 +service.gui.NAME=名称 service.gui.NETWORK=网络 service.gui.NETWORK_FAILURE=网络错误 service.gui.NEXT=下一个(&N) @@ -378,13 +368,14 @@ service.gui.NEW_MESSAGE=新消息... service.gui.NEW_NAME=新名称: service.gui.NEW_STATUS_MESSAGE=添加状态信息 service.gui.NEW_STATUS_MESSAGE_SAVE=存为自定义信息 +service.gui.NICKNAME=昵称 service.gui.NO=否 -service.gui.NONE=沒有 -service.gui.NO_CAMERA_AVAILABLE=找不到摄像头设备 -service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=桌面共享不受此协议支持 -service.gui.NO_VIDEO_ENCODINGS=配置中无视频编码方式被选中 -service.gui.NO_VIDEO_FOR_PROTOCOL=视频不被此协议支持 -service.gui.NO_AVAILABLE_ROOMS=该服务器上的聊天室清单暂时不可获得. +service.gui.NONE=无 +service.gui.NO_CAMERA_AVAILABLE=没有可用的摄像头 +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=此通信协议不支持桌面共享。 +service.gui.NO_VIDEO_ENCODINGS=在配置中没有启用任何视频解码器 +service.gui.NO_VIDEO_FOR_PROTOCOL=此通信协议不支持视频通话 +service.gui.NO_AVAILABLE_ROOMS=服务器上的聊天室列表暂时不可用。 service.gui.NO_CONTACTS_FOUND=找不到匹配的联系人。按下 Ctrl+Enter 或使用以下按钮 呼叫 {0}。 service.gui.NO_CONTACTS_FOUND_SHORT=未找到匹配的联系人 service.gui.NO_MESSAGE=没有消息 @@ -392,27 +383,32 @@ service.gui.NO_GROUP_CHAT_ACCOUNT_AVAILABLE=不支持群聊。 进入 jitsi.org service.gui.NO_ONLINE_CONFERENCING_ACCOUNT=无可用的会议账户。哪些协议支持会议,请查阅https://jitsi.org。 service.gui.NO_ONLINE_TELEPHONY_ACCOUNT=呼叫前必须确保至少一个电话帐号在线。请登录您的一个电话帐号然后重试。 service.gui.NOT_AUTHORIZED=未认证 -service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=消息还没有发送出去, 是否一定退出? -service.gui.NON_EXISTING_USER_ID=服务器 {0} 不能识别用户身份. +service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=您正在尝试关闭会话,但是还有未发送的消息。您确定要关闭会话吗? +service.gui.NON_EXISTING_USER_ID=服务器 {0} 不能识别指定的用户id。 service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=不在联系人列表中 service.gui.SD_QUALITY=标准质量 service.gui.OFFLINE=离线 -service.gui.OK=OK -service.gui.OLDER_CALLS=之前的通话 +service.gui.OK=确定 service.gui.ONLINE=在线 service.gui.OPEN=打开 -service.gui.OPEN_FILE_FROM_IMAGE=双击来打开文件 +service.gui.OPEN_FILE_FROM_IMAGE=双击以打开文件 service.gui.OPEN_FOLDER=打开文件夹 service.gui.OPEN_IN_BROWSER=在浏览器中打开(&B) service.gui.OPTIONS=选项 -service.gui.OPEN_AUTOMATICALLY=自动开启聊天室 -service.gui.OPEN_ON_ACTIVITY=活动开启 -service.gui.OPEN_ON_MESSAGE=仅消息开启 -service.gui.OPEN_ON_IMPORTANT_MESSAGE=仅重要消息开启 -service.gui.OR=或 -service.gui.OR_ENTER_PHONE_NUMBER=或者在此输入电话号码... +service.gui.OPEN_AUTOMATICALLY=在以下情况下自动打开本聊天室 +service.gui.OPEN_ON_ACTIVITY=有活动时打开 +service.gui.OPEN_ON_MESSAGE=仅在有消息时打开 +service.gui.OPEN_ON_IMPORTANT_MESSAGE=仅在有重要消息时打开 +service.gui.OR=或者 service.gui.ORGANIZATION=组织 service.gui.OTHER=其他 +service.gui.chat.role.OWNER=所有者 +service.gui.chat.role.ADMINISTRATOR=管理员 +service.gui.chat.role.MODERATOR=主持人 +service.gui.chat.role.MEMBER=成员 +service.gui.chat.role.GUEST=游客 +service.gui.chat.role.SILENT_MEMBER=静音成员 +service.gui.chat.role.OUTCAST=被禁止加入 service.gui.OWNER=房间所有者 service.gui.ON_MOBILE_TOOLTIP=(手机通话中) service.gui.PASSWORD=密码 @@ -424,28 +420,26 @@ service.gui.PORT=端口 service.gui.POSTAL_CODE=邮政编码 service.gui.PREFERENCES=首选项 service.gui.PREFIX=前缀 -service.gui.PRESENCE=出席 -service.gui.PRESS_ENTER_FOR_SUGGESTIONS=按'回车'查看建议 -service.gui.PRESS_FOR_CALL_INFO=点击查看呼叫信息 +service.gui.PRESENCE=在线状态 +service.gui.PRESS_ENTER_FOR_SUGGESTIONS=按'Enter'键查看建议 +service.gui.PRESS_FOR_CALL_INFO=点击查看通话信息 service.gui.PRESS_TO_OPEN_CRM=点击打开CRM程序 service.gui.PREVIOUS=上一个 -service.gui.PREVIOUS_TOOLTIP=查看更早对话 service.gui.PRINT=打印(&P) service.gui.PROACTIVE_NOTIFICATION=正在输入消息 service.gui.PROBLEMS_ENCOUNTERED=遭遇问题 service.gui.PROTOCOL=协议 -service.gui.PUT_OFF_HOLD=取消挂起 -service.gui.PUT_ON_HOLD=挂起 +service.gui.PUT_OFF_HOLD=撤销呼叫等待 +service.gui.PUT_ON_HOLD=呼叫等待 service.gui.QUIT=退出(&Q) service.gui.READY=就绪 -service.gui.RECENT_MESSAGES=最近的對话 +service.gui.RECENT_MESSAGES=最近的对话 service.gui.REASON=原因 service.gui.RECEIVED=收到{0} service.gui.RECONNECTION_LIMIT_EXCEEDED=该账户多次重复登录服务器: 用户名: {0}, 服务器名: {1} 目前已经被禁止, 请等待一段时间后再试. service.gui.RE_REQUEST_AUTHORIZATION=重新请求认证 service.gui.REFERRED_STATUS=转接 service.gui.REJECT=拒绝(&R) -service.gui.REMIND_ME_LATER=以后提醒我 service.gui.REMEMBER_PASSWORD=记住密码 service.gui.REMOVE=删除(&R) service.gui.REMOVE_ACCOUNT=删除账户(&R) @@ -461,39 +455,32 @@ service.gui.RENAME_CONTACT_WIZARD=请在下面的输入栏中输入您对该联 service.gui.RENAME_GROUP=重命名组(&N) service.gui.RENAME_GROUP_INFO=请在下面的输入栏中输入您对该组的新名称. service.gui.RENAME_CLEAR_USER_DEFINED=还原 -service.gui.RINGING_STATUS=响铃中 +service.gui.RINGING_STATUS=振铃中 service.gui.REQUEST=请求(&R) service.gui.REQUEST_AUTHORIZATION=请求加为好友(&R) service.gui.REQUEST_AUTHORIZATION_MSG=不能添加 {0} 到您的联系人名单. 必须等待 {0} 加您为他/她的好友. 请输入您的请求信息. service.gui.RETRY=重试 service.gui.REVOKE_OWNERSHIP=取消所有者权限 service.gui.REVOKE_ADMIN=取消管理员权限 -service.gui.REVOKE_MODERATOR=取消群主权限 +service.gui.REVOKE_MODERATOR=取消主持人权限 service.gui.REVOKE_MEMBERSHIP=取消成员权限 -service.gui.REVOKE_VOICE=取消发言权 -service.gui.ROOT_GROUP=最上级组 +service.gui.REVOKE_VOICE=撤回语音权限 service.gui.SAVE=保存(&S) -service.gui.SAVE_AS_DEFAULT=保存为默认值 service.gui.SEARCH=搜索(&S) service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=点击按键显示服务器上所有聊天室, 然后选择您感兴趣的聊天室, 点击加入. service.gui.SEARCH_STRING_CONTACT_SOURCE=搜索到的联系人 service.gui.SECURITY=安全 -service.gui.SELECT_ACCOUNT=选择账户 +service.gui.SELECT_ACCOUNT_INFO=您想使用哪个帐号与这个联系人进行通讯? service.gui.SELECT_COLOR=选择颜色 service.gui.SELECT_GROUP=选择组 -service.gui.SELECT_GROUP_WIZARD_MSG=下面的名单中包含您所有联系人组, 请选择一个, 然后加入新的联系人. +service.gui.SELECT_GROUP_INFO=您想将此联系人放置在哪个群组下显示?(可选) service.gui.SELECT_NO_GROUP=未分组 -service.gui.SELECT_GROUP_WIZARD=指示组名 service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=下面的名单中包含所有支持群聊的账户. 请选择一个, 然后创建您的聊天室. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=下面的名单中包含您所有的注册账户. 请选择一个和新联系人对话. -service.gui.SELECT_PROVIDERS_WIZARD=选择账户 service.gui.SELECT_VIDEO_CONFERENCE=选择视频会议 service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=聊天室 service.gui.SEND=发送(&S) service.gui.SEND_FILE=发送文件(&F) -service.gui.SELECT_CONTACT_SUPPORTING_INFO=没有该联系人信息. service.gui.SEND_MESSAGE=发送消息(&S) -service.gui.SEND_AS_SMS=作为手机短信, 发送消息 service.gui.SEND_PRIVATE_MESSAGE=发送私信 service.gui.SEND_SMS=发送手机短信(&E) service.gui.SEND_SMS_DETAILS=请记住你必须以国际电话号码格式输入,例如 以 +44 打头的英国号码 +447777000000。 @@ -532,7 +519,6 @@ service.gui.STREET=街道 service.gui.SUBJECT=主题 service.gui.SUMMARY=概要 service.gui.TELEPHONY=电话 -service.gui.TODAY=今天 service.gui.TOOLS=工具(&T) service.gui.TRANSFER=转接(&F) service.gui.TO=到(&T) @@ -542,7 +528,6 @@ service.gui.TRANSFER_CALL_TO=转接给: service.gui.TRANSPARENCY_NOT_ENABLED=您当前设置不支持透明。 service.gui.TYPE_YOUR_REQUEST=请在这里输入您的请求 service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=我们无法改变此呼叫的视频质量。 -service.gui.UNMUTE=取消静音 service.gui.USER_IDENTIFIER=用户ID: service.gui.USER_EXISTS_ERROR=该网络上已存在该用户。请选择其他用户或网络服务。 service.gui.USERNAME_NULL=请输入用户名和密码。 @@ -555,7 +540,6 @@ service.gui.USE_PROVISIONING=使用在线条款 service.gui.VALUE=值 service.gui.VIDEO_CALL=视频通话(&V) service.gui.VIA=通过 -service.gui.VIA_SMS=通过短信 service.gui.VIEW=查看(&V) service.gui.VIEW_HISTORY=查看历史(&H) service.gui.VIEW_SMILEYS=查看表情(&S) @@ -575,9 +559,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=调整音量 service.gui.WAITING_AUTHORIZATION=正在等待验证 service.gui.WARNING=警告 service.gui.YES=是 -service.gui.YESTERDAY=昨天 -service.gui.EXISTING_ACCOUNT_ERROR=您输入的帐号已加入。 -service.gui.NEW_MAIL=你有一封新邮件!
    来自: {0} {1}
    标题: {2}
    {3}; service.gui.NEW_GMAIL_HEADER={0}收件箱:
    有一封新邮件 service.gui.NEW_GMAIL_MANY_HEADER={0}收件箱:
    有{2}封新邮件 service.gui.NEW_GMAIL_FOOTER=多条未读留言在您的收件箱
    @@ -589,6 +570,9 @@ service.gui.ENTER_FULL_SCREEN_TOOL_TIP=全屏 service.gui.EXIT_FULL_SCREEN_TOOL_TIP=退出全屏 service.gui.HOLD_BUTTON_TOOL_TIP=粗体切换 service.gui.MUTE_BUTTON_TOOL_TIP=切换静音或者按住按钮以调整麦克风音量 +service.gui.PARK=保持 +service.gui.PARKING_SLOT=呼叫保持通道: +service.gui.PARK_BUTTON_TOOL_TIP=呼叫保持 service.gui.RECORD_BUTTON_TOOL_TIP=开启/停止录音 service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=视频切换 service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=显示/隐藏本地视频 @@ -601,7 +585,6 @@ service.gui.SECURITY_ERROR=安全错误 service.gui.SPEED=速率: service.gui.SILENT_MEMBER=静音成员 service.gui.NON_SECURE_CONNECTION=无法为账户{0}建立安全连接。如果你想连接到一个非安全服务器,请在您的账户配置中选中 "允许非安全连接" 选项 -service.gui.UPDATE=更新 service.gui.MOBILE_PHONE=手机 service.gui.VIDEO_PHONE=视频 service.gui.WORK_PHONE=工作 @@ -636,12 +619,10 @@ service.gui.callinfo.CALL_INFORMATION=呼叫信息 service.gui.callinfo.CALL_IDENTITY=标识 service.gui.callinfo.PEER_COUNT=参与者计数 service.gui.callinfo.IS_CONFERENCE_FOCUS=会议焦点 -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=启用加密 service.gui.callinfo.CALL_TRANSPORT=信号呼叫传输 service.gui.callinfo.CALL_DURATION=呼叫周期 service.gui.callinfo.TLS_PROTOCOL=TLS 安全协议 service.gui.callinfo.TLS_CIPHER_SUITE=TLS加密算法套件 -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=TLS服务器证书链 service.gui.callinfo.TLS_CERTIFICATE_CONTENT=TLS服务器证书的内容显示在下面。 service.gui.callinfo.VIEW_CERTIFICATE=查看证书 service.gui.callinfo.CODEC=编解码器/频率 @@ -661,10 +642,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=RTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=密钥交换协议 service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE候选者拓展类型 service.gui.callinfo.ICE_STATE=ICE作业处理状态 + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=搜集候选者 service.gui.callinfo.ICE_STATE.RUNNING=连通性检查 service.gui.callinfo.ICE_STATE.COMPLETED=已完成 service.gui.callinfo.ICE_STATE.FAILED=失败 + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=本地主机IP/端口 service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=本地自反IP/端口 service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=本地中继IP/端口 @@ -685,28 +669,34 @@ service.gui.ALWAYS_TRUST=总是信任这个证书 service.gui.CERT_DIALOG_TITLE=验证证书 service.gui.CERT_DIALOG_DESCRIPTION_TXT=当{0}连接到服务器
    {1}时无法确认服务器身份。

    该服务器证书不可信,这意味着无法自动验证服务器身份。

    您确认要继续连接?
    更多信息,点击 “显示证书”。 service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0}无法确认服务器证书身份。

    该服务器证书不可信,这意味着无法
    自动验证服务器身份。您确认要继续连接吗?

    更多信息,点击“查看证书”获取详细信息。 -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} 无法验证正在连接的客户端。

    该客户端证书不可信任,
    这意味着无法自动验证其身份。您确认要接受该连接?/

    点击"查看证书"获取详细信息。 -service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} 无法确认{1}端的身份。

    该证书不可信, 这意味着无法自动验证其身份。您确认要继续连接吗?

    更多详情,点击“显示证书”。 +service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} 无法确认 {1} 端的身份。

    该证书不可信, 这意味着无法自动验证其身份。您确认要继续连接吗?

    更多详情,请点击“显示证书”。 service.gui.CONTINUE_ANYWAY=仍然继续 +service.gui.CERT_INFO_CHAIN=证书链: +service.gui.CERT_INFO_ISSUED_TO=颁发给 + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=通用名: service.gui.CERT_INFO_O=组织: service.gui.CERT_INFO_C=国家: service.gui.CERT_INFO_ST=州/省: service.gui.CERT_INFO_L=地址: +service.gui.CERT_INFO_ISSUED_BY=颁发者 service.gui.CERT_INFO_OU=单位: +service.gui.CERT_INFO_VALIDITY=有效性 service.gui.CERT_INFO_ISSUED_ON=授权时间: service.gui.CERT_INFO_EXPIRES_ON=失效时间: +service.gui.CERT_INFO_FINGERPRINTS=指纹 +service.gui.CERT_INFO_CERT_DETAILS=证书信息 service.gui.CERT_INFO_SER_NUM=序列号: service.gui.CERT_INFO_VER=版本: service.gui.CERT_INFO_SIGN_ALG=签名算法: +service.gui.CERT_INFO_PUB_KEY_INFO=公钥信息 service.gui.CERT_INFO_ALG=算法: service.gui.CERT_INFO_PUB_KEY=公钥: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes:{1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=指数: service.gui.CERT_INFO_KEY_SIZE=密钥长度: service.gui.CERT_INFO_SIGN=签名: -service.gui.CONTINUE=继续 service.gui.SHOW_CERT=显示证书 service.gui.HIDE_CERT=隐藏证书 @@ -729,15 +719,13 @@ service.gui.security.SECURE_AUDIO=加密音频 service.gui.security.AUDIO_NOT_SECURED=音频未加密 service.gui.security.SECURE_VIDEO=加密视频 service.gui.security.VIDEO_NOT_SECURED=未加密视频 -service.gui.security.NO_VIDEO=无视频 -service.gui.security.CIPHER=暗码:{0} +service.gui.security.CALL_SECURED_TOOLTIP=呼叫已加密。更多详情请点击这里。 service.gui.security.CALL_NOT_SECURED_TOOLTIP=呼叫未加密 service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=点此同您的伙伴校验安全密码。 -service.gui.security.COMPARE_WITH_PARTNER=核对参与者然后点击挂锁图标确认。 # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=请核对参与者: service.gui.security.STRING_COMPARED=字符串校验通过! -service.gui.security.SAS_INFO_TOOLTIP=为了完成加密你
    需要口头校验联系人提供的一小段验证
    字段并当此字段被验证通过后点击确认。

    如果你清除了此确认信息,当下次呼叫此联系人时
    你将被要求再次验证。 +service.gui.security.SAS_INFO_TOOLTIP= 为了完成加密你
    需要口头 校验 联系人提供的一小段验证
    字段并仅当此字段被验证通过后才能点击确认。

    如果你清除了此确认信息,当下次呼叫此联系人时
    你将被要求再次验证。 service.gui.security.SECURITY_ALERT=尝试加密呼叫。会断开接入 service.gui.avatar.CHOOSE_ICON=选择图片 @@ -751,20 +739,14 @@ service.gui.avatar.imagepicker.CLICK=微笑然后单击 service.gui.avatar.imagepicker.IMAGE_FILES=图片文件 service.gui.avatar.imagepicker.IMAGE_PICKER=图片 service.gui.avatar.imagepicker.IMAGE_SIZE=图片大小 -service.gui.avatar.imagepicker.INITIALIZING=初始化中 service.gui.avatar.imagepicker.RESET=重置 service.gui.avatar.imagepicker.SET=设置 service.gui.avatar.imagepicker.TAKE_PHOTO=拍照 -service.gui.avatar.imagepicker.WEBCAM_ERROR=摄像头错误 service.gui.security.encryption.required=必须加密! service.protocol.ICE_FAILED=无法建立连接(ICE失败,并没有发现中继器) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=SIP联系人列表存储错误 impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=源不能被读为{0}。对象{1} @@ -794,9 +776,7 @@ impl.ldap.QUERY_CUSTOM=自定义查询 impl.ldap.QUERY_CUSTOM_HINT=使用 {0} 作为占位符用于搜索术语。 impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=在查询术语中自动增加通配符 impl.ldap.QUERY_PHOTO_INLINE=通过其他属性获取图片 -impl.ldap.NEW=新建 impl.ldap.EDIT=编辑 -impl.ldap.REMOVE=删除 impl.ldap.ENABLED=启用 impl.ldap.SERVER_NAME=服务器名 impl.ldap.SERVER_NAME_EXAMPLE=我的LDAP服务器 @@ -829,6 +809,12 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=家庭电话 impl.ldap.PHONE_PREFIX=电话号码前缀 impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol +impl.protocol.sip.INVALID_ADDRESS="{0}" 不是一个有效的 SIP 地址。 + +#Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS="{0}" 不是一个有效的 XMPP JID。 + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=地址簿 plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=允许搜索MaxOSX地址簿 @@ -843,9 +829,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=使用Outlook为默认邮件用 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google 联系人 -impl.googlecontacts.NEW=新建 impl.googlecontacts.EDIT=编辑 -impl.googlecontacts.REMOVE=删除 impl.googlecontacts.ENABLED=启用 impl.googlecontacts.ACCOUNT_NAME=帐户名 impl.googlecontacts.SAVE=保存 @@ -854,6 +838,10 @@ impl.googlecontacts.USERNAME=帐户名 impl.googlecontacts.PASSWORD=密码 impl.googlecontacts.PREFIX=电话前缀 impl.googlecontacts.WRONG_CREDENTIALS=Google账户{0}证书错误 +impl.googlecontacts.OAUTH_DIALOG_TITLE=Google 通讯录授权认证 +impl.googlecontacts.INSTRUCTIONS=

    点击下面链接以授权 Google 通讯录插件访问您的账户。

    点击此链接后,您的浏览器就会打开。请您登录指定的账户并授权。在成功授权后,Google 会显示一条代码。请复制这条代码并粘贴到下面的文本框,然后点击 '保存'。

    这是一次性操作。授权令牌将会留作后用。 +impl.googlecontacts.CODE=代码: +impl.googlecontacts.HYPERLINK_TEXT=点击这里以允许访问 {0} 的授权请求 # account info plugin.accountinfo.TITLE=帐号信息 @@ -884,13 +872,11 @@ plugin.accountinfo.ORGANIZATION=组织名称: plugin.accountinfo.JOB_TITLE=职位: plugin.accountinfo.ABOUT_ME=关于我们: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=头像 plugin.accountinfo.GLOBAL_ICON=使用全局图标 plugin.accountinfo.LOCAL_ICON=使用此图标: -plugin.accountinfo.CHANGE=更改 -plugin.accountinfo.ONLY_MESSAGE=只允许短消息 # connection info +plugin.connectioninfo.TITLE=连接信息 # contact info plugin.contactinfo.TITLE=联系人详细信息 @@ -907,49 +893,13 @@ plugin.aimaccregwizz.USERNAME=AIM用户名: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=用户名和密码 plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=注册新帐号 plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=如果你没有AIM帐号,点击这个按钮进行注册。 -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=覆盖服务器默认设置 # branding plugin.branding.ABOUT_WINDOW_TITLE=关于 {0} plugin.branding.LOGO_MESSAGE=开源VoIP&&即时消息 -plugin.branding.LOADING=加载中 plugin.branding.ABOUT_MENU_ENTRY=关于(&A) -plugin.branding.WELCOME_MESSAGE=

    {1} 目前处于活跃开发中。 您目前运行的版本是测试版,可能不适合实际工作中使用。请访问 {2} 获取更多信息。
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org。All rights reserved。详情访问 https://jitsi.org
    -plugin.branding.LICENSE=
    Jitsi 以LGPL(http://www.gnu.org)协议发布。
    - -# Dict protocol -service.protocol.DICTIONARIES=字典 -plugin.dictaccregwizz.ANY_DICTIONARY=任意字典 -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=来自 {0} 的任意字典 -plugin.dictaccregwizz.FIRST_MATCH=首次匹配 -plugin.dictaccregwizz.NO_MATCH=没有匹配结果 -plugin.dictaccregwizz.MATCH_RESULT=没有匹配 "{0}" 的结果, 您是不是要找:\n -plugin.dictaccregwizz.INVALID_DATABASE=当前使用的字典 "{0}" 在服务器上不存在。 -plugin.dictaccregwizz.INVALID_STRATEGY=服务器不支持当前使用的规则 "{0}"。 -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=字典服务 -plugin.dictaccregwizz.HOST=主机 -plugin.dictaccregwizz.SERVER_INFO=服务器信息 -plugin.dictaccregwizz.STRATEGY_SELECTION=选择规则 -plugin.dictaccregwizz.STRATEGY_LIST=规则列表: -plugin.dictaccregwizz.SEARCH_STRATEGIES=搜索规则 -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=如果没有找到合适的翻译,匹配规则用来查找近似词语。例如前缀规则将查找以您的关键词开头的词语。 -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict帐号信息 -plugin.dictaccregwizz.FIRST_ACCOUNT=这个向导将为您创建dict.org上的Dict帐号。\n\n您可以通过帐号注册向导添加新字典。 填写您要添加字典的主机字段。 -plugin.dictaccregwizz.THREAD_CONNECT=尝试连接服务器 -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=尝试连接失败, 这不是一个字典服务器或者服务器不在线 -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=获取规则列表 -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=服务器上找不到规则策略 -plugin.dictaccregwizz.POPULATE_LIST=组成列表 -plugin.dictaccregwizz.CLOSING_CONNECTION=正在关闭连接 - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    使用Facebook聊天之前你必须在Facebook的
    "帐号设置" 页面上先创建一个用户名


    注意: 创建完用户名你需要先从该网页登出,
    并且在你可以使用该用户名登录之前可能需要等待一段时间!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Facebook聊天协议 -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=用户名: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=用户名和密码 + +plugin.busylampfield.PICKUP=接听通话 # generalconfig plugin.generalconfig.AUTO_START=开机或重启时自动运行 {0} @@ -960,9 +910,6 @@ plugin.generalconfig.SHOW_HISTORY=显示 plugin.generalconfig.HISTORY_SIZE=最近的聊天信息 plugin.generalconfig.SEND_MESSAGES_WITH=发送消息经由: plugin.generalconfig.BRING_WINDOW_TO_FRONT=聊天窗口前置 -plugin.generalconfig.ERROR_PERMISSION=您没有权限取消自动启动 -plugin.generalconfig.TRANSPARENCY=透明度 -plugin.generalconfig.ENABLE_TRANSPARENCY=启用透明 plugin.generalconfig.DEFAULT_LANGUAGE=界面语言 plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=您的设置将在下次启动时生效。 plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}%已翻译 @@ -978,6 +925,8 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=呼叫电话号码前删除特 plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=转化电话号码中的字符 plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=e.g. +1-800-MYPHONE -> +1-800-694663 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=在检测联系人的特性时使用所有资源 plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=采样率: plugin.generalconfig.OPUS_BITRATE=编码器平均比特率(kbps): @@ -1009,19 +958,30 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=创建新帐号 plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=IRC协议 plugin.ircaccregwizz.USERNAME_AND_PASSWORD=用户名和密码 +plugin.ircaccregwizz.USERNAME=昵称 +plugin.ircaccregwizz.EXAMPLE_USERNAME=例如:ircuser plugin.ircaccregwizz.INFO_PASSWORD=大部分IRC服务器不需要密码。 plugin.ircaccregwizz.AUTO_NICK_CHANGE=当该昵称已被占用时自动选择昵称 plugin.ircaccregwizz.USE_DEFAULT_PORT=使用默认端口 plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=我的昵称不需要身份校验 plugin.ircaccregwizz.HOST=主机名: plugin.ircaccregwizz.IRC_SERVER=服务器 +plugin.ircaccregwizz.EXAMPLE_SERVER=例如:chat.freenode.net +plugin.ircaccregwizz.USE_SECURE_CONNECTION=使用安全连接 +plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=启用联系人在线状态 +plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=启用聊天室在线状态 +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=SASL验证 +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=启用SASL验证 +plugin.ircaccregwizz.SASL_USERNAME=用户名 +plugin.ircaccregwizz.SASL_AUTHZ_ROLE=角色 +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=以上的IRC密码用于SASL验证 +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=总是使用代理进行DNS解析 # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPP协议 plugin.jabberaccregwizz.USERNAME=XMPP用户名 plugin.jabberaccregwizz.PASSWORD_CONFIRM=确认密码 -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=帐号和密码 plugin.jabberaccregwizz.CSERVER=服务器 plugin.jabberaccregwizz.SERVER=连接服务器 plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=允许保持连接 @@ -1037,13 +997,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=评论 plugin.jabberaccregwizz.RESOURCE=资源 plugin.jabberaccregwizz.AUTORESOURCE=自动生成资源名 plugin.jabberaccregwizz.PRIORITY=优先级 -plugin.jabberaccregwizz.XMPP_ERROR=XMPP错误 plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=未知XMPP错误({0})。请确认服务器地址是否正确。 plugin.jabberaccregwizz.NOT_SAME_PASSWORD=密码不匹配。 -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=覆盖服务器默认设置 -plugin.jabberaccregwizz.ADVANCED_OPTIONS=高级选项 plugin.jabberaccregwizz.USE_ICE=使用ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=使用Google Jingle/ICE(实验性) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=自动检测STUN/TURN服务器 plugin.jabberaccregwizz.SUPPORT_TURN=支持TURN plugin.jabberaccregwizz.TURN_USERNAME=TURN用户名 @@ -1071,11 +1027,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=禁用消息碳 plugin.jabberaccregwizz.DTMF_AUTO=自动:自动选择RTP或Inband plugin.jabberaccregwizz.SERVER_OPTIONS=服务器选项 plugin.jabberaccregwizz.CHANGE_PASSWORD=更改账号密码 -plugin.jabberaccregwizz.NEW_PASSWORD=新密码 -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=确认新密码 plugin.jabberaccregwizz.PORT_FIELD_INVALID=请填入一个可用的端口号以便继续。 plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=账号变更密码前必须登录。 -plugin.jabberaccregwizz.PASSWORD_EMPTY=密码为空。 plugin.jabberaccregwizz.TLS_REQUIRED=连接未使用TLS,不会尝试密码变更。 plugin.jabberaccregwizz.PASSWORD_CHANGED=密码已变更成功 plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=您的XMPP服务器不支持密码变更。 @@ -1089,25 +1042,9 @@ plugin.jabberaccregwizz.RESET=重置 plugin.jabberaccregwizz.RESET_DESCRIPTION=复位全局设置 plugin.jabberaccregwizz.DISABLE_JINGLE=禁用Jingle(XMPP音频和视频呼叫) -# mailbox -plugin.mailbox.OUTGOING=已发送的消息: -plugin.mailbox.INCOMING=已收到的消息: -plugin.mailbox.WAIT_TIME=转到语音信箱之前等待时间 -plugin.mailbox.MAX_MESSAGE_TIME=最长留言 -plugin.mailbox.CONFIRM=确认 -plugin.mailbox.DEFAULTS=默认 -plugin.mailbox.MAILBOX=邮箱 - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=连接和使用MSN聊天协议。 -plugin.msnaccregwizz.USERNAME=Email: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=帐号和密码 - # plugin manager plugin.pluginmanager.INSTALL=安装 plugin.pluginmanager.UNINSTALL=卸载 -plugin.pluginmanager.UPDATE=更新 plugin.pluginmanager.PLUGINS=插件 plugin.pluginmanager.URL=地址 plugin.pluginmanager.CHOOSE_FILE=选择文件 @@ -1132,9 +1069,9 @@ plugin.sipaccregwizz.SERVER_PORT=服务器端口 plugin.sipaccregwizz.PROXY=代理服务器 plugin.sipaccregwizz.PROXY_PORT=代理端口 plugin.sipaccregwizz.PREFERRED_TRANSPORT=首选 -plugin.sipaccregwizz.ADVANCED_OPTIONS=高级选项 plugin.sipaccregwizz.PROXY_OPTIONS=代理选项 plugin.sipaccregwizz.PROXY_AUTO=自动配置代理服务器 +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=在 HA 的情况下跳过代理安全检查(请仅在需要时使用) plugin.sipaccregwizz.ENABLE_PRESENCE=允许出席(SIMPLE) plugin.sipaccregwizz.FORCE_P2P_PRESENCE=强制使用P2P出席模式 plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=离线联系人拉取间隔(单位:秒) @@ -1152,8 +1089,6 @@ plugin.sipaccregwizz.DTMF_AUTO=自动:从RTP和Inband(无SIP信息)自动选 plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP信息 plugin.sipaccregwizz.DTMF_INBAND=带内 -plugin.sipaccregwizz.REGISTER=注册 -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=覆盖服务器默认选项 plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=启用加密通话支持 plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=表示支持ZRTP的信令协议 plugin.sipaccregwizz.AUTH_NAME=授权名称 @@ -1174,10 +1109,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=语音邮件查阅URI plugin.sipaccregwizz.NOT_SAME_PASSWORD=您的密码不匹配。 plugin.sipaccregwizz.NO_CERTIFICATE=(使用常规验证) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP表示 +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Off(只标明RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=强制(只提供并接受RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=可选(先提供RTP/SAVP,然后RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=启用S-Descriptor(即SDES或SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=选择启用加密协议和它们的优先顺序(顶端协议优先): plugin.sipaccregwizz.CIPHER_SUITES=启用加密套件: plugin.sipaccregwizz.SECURITY_WARNING=
    {0}会自动尝试加密您的所有ZRTP呼叫并且您会听到和看到一个安全连接已就绪的提示。如果您已了解您正在做什么,您仅需改变如下高级设置
    @@ -1191,15 +1126,6 @@ plugin.skinmanager.DEFAULT_SKIN=默认皮肤 plugin.skinmanager.ADD_NEW_SKIN=添加新皮肤 plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=应用程序默认皮肤。 -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=通过SSH连接远程计算机。 -plugin.sshaccregwizz.USERNAME=帐号ID: -plugin.sshaccregwizz.IDENTITY_FILE=标识文件: -plugin.sshaccregwizz.KNOWN_HOSTS=已知主机: -plugin.sshaccregwizz.OPTIONAL=可选 -plugin.sshaccregwizz.ACCOUNT_DETAILS=详细帐号信息 - # status update plugin.autoaway.AUTO_STATUS=自动切换到离开状态 plugin.autoaway.ENABLE_CHANGE_STATUS=离开时修改状态 @@ -1247,22 +1173,6 @@ plugin.whiteboard.DESELECT=反选 plugin.whiteboard.DELETE=删除 plugin.whiteboard.PROPERTIES=属性 -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=一种连接Yahoo!聊天服务并聊天的协议。 -plugin.yahooaccregwizz.USERNAME=用户名: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=用户名和密码 - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Zeroconf (Bonjour) 服务协议。 -plugin.zeroaccregwizz.FIRST_NAME=名字: -plugin.zeroaccregwizz.LAST_NAME=姓: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=记住 Bonjour 联系人? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=帐号和密码 -plugin.zeroaccregwizz.USERID=用户ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=GOOGLE TALK协议 @@ -1276,19 +1186,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, IP电话门户 plugin.iptelaccregwizz.USERNAME=用户名 plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=订阅iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP和聊天 +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=用户名 plugin.sip2sipaccregwizz.RETYPE_PASSWORD=再次输入密码 plugin.sip2sipaccregwizz.EMAIL=Email 地址 -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=请查看以下网站查看服务介绍
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=这个 email 地址将被用来发送语音留言,
    未接来电提醒和重置密码服务 -plugin.sip2sipaccregwizz.INFO_NOTE=访问以下地址获取该服务介绍:http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=该sip2sip.info帐号已存在 -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=创建免费的sip2sip.info帐号 - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && 即时通信 plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=请查看以下网站查看服务介绍
    http://ippi.fr @@ -1297,6 +1199,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=已添加的ippi账号 plugin.ippiaccregwizz.CREATE_ACCOUNT=创建免费的ippi帐号 # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=关闭聊天窗口 plugin.keybindings.CHAT_COPY=复制 plugin.keybindings.CHAT_CUT=剪切 @@ -1319,15 +1222,16 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=姓名 plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=主快捷键 plugin.keybindings.globalchooser.SHORTCUT_SECOND=第二快捷方式 plugin.keybindings.globalchooser.PRESS_BTN=点击设置快捷方式 -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=等待中 plugin.keybindings.globalchooser.PUSH_TO_TALK=按键通话 plugin.keybindings.globalchooser.ENABLE_SPECIAL=启用特殊键检测 plugin.keybindings.PLUGIN_NAME=快捷键 +#Enum KeybindingSet.Category plugin.keybindings.CHAT=聊天 plugin.keybindings.MAIN=主要 plugin.keybindings.GLOBAL=全局快捷键 # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=启用 plugin.notificationconfig.DESCRIPTION=描述 plugin.notificationconfig.TURN_ON_ALL=全部启用 plugin.notificationconfig.TURN_OFF_ALL=全部禁用 @@ -1349,6 +1253,7 @@ plugin.notificationconfig.tableheader.SOUND=通过提醒设备播放提示音 plugin.notificationconfig.tableheader.PLAYBACK_SOUND=通过回放设备播放声音 plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=通过PC扬声器设备播放声音 plugin.notificationconfig.tableheader.DESCRIPTION=事件描述 +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=来电 plugin.notificationconfig.event.SecurityMessage=安全消息 plugin.notificationconfig.event.IncomingFile=正在传入的文件 @@ -1389,7 +1294,7 @@ impl.media.security.WARNING_NO_EXPECTED_RS_MATCH=找不到共享密钥。< impl.media.security.SEVERE_GENERIC_MSG=检测到严重的服务安全问题。
    您的通话不安全
    错误代码: {0} impl.media.security.ZRTP_GENERIC_MSG=检测到严重的ZRTP问题。
    您的通话不安全
    错误代码: {0} impl.media.security.INTERNAL_PROTOCOL_ERROR=发生了协议内部错误。
    您的通话不安全
    错误代码: {0} -impl.media.security.CHECKSUM_MISMATCH=内部ZRTP包的校验失败。
    如果您看到此消息,通常这可能意味着拒绝服务攻击! +impl.media.security.CHECKSUM_MISMATCH= 内部ZRTP包的校验失败。
    如果您看到此消息,通常这可能意味着拒绝服务攻击! impl.media.security.RETRY_RATE_EXCEEDED=尝试安全协商次数过多。 这很可能意味着对方存在网络连接问题.
    您的通话不安全
    错误代码: {0} impl.media.security.DATA_SEND_FAILED=加密数据传输失败。 网络数据连接或者对方已断开。
    您的呼叫不安全
    错误代码: {0} impl.media.security.SECURITY_OFF=加密通话已关闭 @@ -1450,6 +1355,7 @@ impl.neomedia.configform.VIDEO=视频 impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=周期性内部刷新 impl.neomedia.configform.H264.defaultProfile=编码缺省配置: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=基线 impl.neomedia.configform.H264.defaultProfile.high=高 impl.neomedia.configform.H264.defaultProfile.main=主体 @@ -1480,7 +1386,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=当前密码: plugin.securityconfig.masterpassword.ENTER_PASSWORD=新密码: plugin.securityconfig.masterpassword.REENTER_PASSWORD=确认密码: plugin.securityconfig.masterpassword.MP_TITLE=主密码 -plugin.securityconfig.masterpassword.MP_NOT_SET=(未设置) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=您输入的主密码错误。 请重试。 plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=主密码错误! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=密码修改失败 @@ -1496,7 +1401,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=密码 plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(未知) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(无法解密) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=存储的密码 -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=删除 plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=清空 plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=确认要删除全部保存的密码? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=删除全部密码 @@ -1592,7 +1496,6 @@ plugin.globalproxy.PROXY_PORT=代理端口 plugin.globalproxy.PROXY_USERNAME=代理用户名 plugin.globalproxy.PROXY_PASSWORD=代理密码 plugin.globalproxy.DESCRIPTION={0} 将对所有网络连接应用以上代理设置。\n目前对代理的支持尚处于试验阶段,并且只支持部分协议。详细信息请查看下表: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=附加DNS代理 plugin.globalproxy.FWD_DNS_NOTE=Tor的作用。通过将所有的DNS查询路径转发到Tor代理而有助于回避DNS漏洞。需要重启。 @@ -1609,6 +1512,11 @@ plugin.reconnectplugin.NETWORK_DOWN=网络连接已断开! plugin.chatconfig.TITLE=聊天 plugin.chatconfig.replacement.TITLE=图片/视频: plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=允许插入表情 +plugin.chatconfig.replacement.REPLACEMENT_TITLE=替换图像和视频 +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=启用 +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL=禁用(显示预览链接) +plugin.chatconfig.replacement.DISABLE_REPLACEMENT=禁用 +plugin.chatconfig.replacement.CONFIGURE_REPLACEMENT=图像和视频替换设置选项更改 plugin.chatconfig.replacement.REPLACEMENT_SOURCES=来源: plugin.chatconfig.spellcheck.TITLE=拼写检查 @@ -1625,7 +1533,6 @@ plugin.provisioning.RESTART_WARNING=请注意所有修改仅在下次启动{0} plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=复制UUID到剪贴板 plugin.provisioning.CLIPBOARD_FAILED=复制UUID到剪贴板失败 -plugin.provisioning.EXIT_ON_FAIL=如果配置失败则退出程序 plugin.provisioning.CREDENTIALS=最后存储的配置证书 plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=确认移除预置密码么? plugin.provisioning.PROV_FAILED=预置失败 @@ -1692,8 +1599,6 @@ util.dns.DNSSEC_WARNING=
    {0}已视图连接位于{1} Date: Wed, 18 Jan 2017 23:52:20 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 292 of 1505 strings translated (32 fuzzy). --- resources/languages/resources_hu.properties | 297 ++++++++++++++++++++++------ 1 file changed, 235 insertions(+), 62 deletions(-) diff --git a/resources/languages/resources_hu.properties b/resources/languages/resources_hu.properties index 47ac7ba..f7bfa1f 100644 --- a/resources/languages/resources_hu.properties +++ b/resources/languages/resources_hu.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -25,60 +36,54 @@ # from your system's language, pass the language code to ant: # ant -Duser.language=xx run -service.gui.ABOUT=Névjegy -service.gui.ACCEPT=Elfogad +service.gui.ABOUT=&Névjegy +service.gui.ACCEPT=&Elfogadás service.gui.ACCOUNT=Felhasználói fiók service.gui.ACCOUNT_ME=Én service.gui.ACCOUNT_REGISTRATION_WIZARD=Fiók regisztrációs varázsló service.gui.ACCOUNTS=Felhasználói fiókok -service.gui.ADD=Hozzáad -service.gui.ADD_ACCOUNT=Fiók hozzáadása -service.gui.ADD_CONTACT=Partner felvétele +service.gui.ADD=&Hozzáadás +service.gui.ADD_CONTACT=&Partner felvétele service.gui.ADD_AUTHORIZED_CONTACT={0} felvétele a partnerlistára service.gui.ADD_CONTACT_TO_CONTACTLIST=A partner felvétele a partnerlistára service.gui.ADD_CONTACT_TO=Partner felvétele ehhez service.gui.ADD_CONTACT_ERROR={0} partner felvétele nem sikerült service.gui.ADD_CONTACT_ERROR_TITLE=Hiba a partner felvételekor -service.gui.ADD_CONTACT_EXIST_ERROR={0} már szerepel partnerként a partnerlistában +service.gui.ADD_CONTACT_EXIST_ERROR={0} már szerepel partnerlistában service.gui.ADD_CONTACT_NETWORK_ERROR=A szerver nem válaszolt {0} partnerfelvételi kérelmünkre service.gui.ADD_CONTACT_NOT_SUPPORTED={0} partner felvétele nem sikerült. Ez a művelet nem támogatott. -service.gui.ADD_CONTACT_IDENTIFIER=Ebbe a mezőbe írd be annak a partnernek az azonosítóját, akit fel szeretnél venni. -service.gui.ADD_CONTACT_WIZARD=Partner felvételi varázsló service.gui.ADD_CONTACT_NOT_CONNECTED=Partner felvételéhez kapcsolódva kell lenned. Jelentkezz be a kiválasztott szolgáltatóhoz, és próbáld újra. service.gui.ADD_GROUP_LOCAL_ERROR=A {0} csoport létrehozása nem sikerült. A probléma egy helyi IO művelet közben történt. service.gui.ADD_GROUP_EXIST_ERROR=A {0} csoport már szerepel a partnerlistában. Válassz egy másik nevet. service.gui.ADD_GROUP_NET_ERROR=A {0} csoport létrehozása nem sikerült. A problémát hálózati hiba okozta. Ellenőrizd a hálózati kapcsolatod, és próbáld újra. service.gui.ADD_GROUP_ERROR=A {0} csoport létrehozása nem sikerült. service.gui.ADD_GROUP_EMPTY_NAME=A csoport neve nem lehet üres. -service.gui.ADD_GROUP=Csoport létrehozása -service.gui.ADD_SUBCONTACT=Alpartner felvétele service.gui.ADDRESS=Cím service.gui.ADMINISTRATOR=rendszergazda -service.gui.ADVANCED=Speciális -service.gui.ALL=Mind -service.gui.ALL_CONTACTS=Minden partner +service.gui.ADVANCED=&Speciális +service.gui.ALL_CONTACTS=&Minden partner service.gui.ALTERNATE_ADDRESS=Alternatív cím -service.gui.APPLY=Alkalmaz +service.gui.APPLY=&Alkalmaz service.gui.ARE_CALLING={0} hív... service.gui.ARE_NOW=Te most {0} vagy -service.gui.AUTHORIZE=Engedélyez +service.gui.AT=itt: +service.gui.AUTHORIZE=&Engedélyezés service.gui.AUTHORIZATION_ACCEPTED={0} elfogadta az engedélyezési kérésed. service.gui.AUTHENTICATION_FAILED={0} hitelesítése nem sikerült. A beírt jelszó nem jó. -service.gui.AUTHENTICATION_REQUESTED=Hitelesítés folyamatban service.gui.AUTHENTICATION_REQUESTED_SERVER=A {0} szerver kéri, hogy hitelesítsd magad. service.gui.AUTHENTICATION_REJECTED={0} elutasította az engedélyezési kérésed. -service.gui.AUTHENTICATION_WINDOW_TITLE={0} engedélyezés +service.gui.AUTHENTICATION_WINDOW_TITLE={0} hitelesítés service.gui.AUTHORIZATION_REQUESTED=Engedélyezés folyamatban -service.gui.AUTHORIZATION_REQUESTED_INFO={0} partner kéri az engedélyezésedet. +service.gui.AUTHORIZATION_REQUESTED_INFO={0} partner kéri az engedélyezésed. service.gui.AUTHORIZATION_RESPONSE=Válasz az engedélyezésre service.gui.AWAY_STATUS=Nincs a gépnél -service.gui.EXTENDED_AWAY_STATUS=Hosszabb ideje nincs a gépnél -service.gui.BAN=Letilt -service.gui.BANNED=letiltva -service.gui.BAN_FAILED=Letiltás nem sikerült -service.gui.BAN_FAILED_GENERAL_ERROR={0} letiltása nem sikerült. Egy meg nem határozott szerver hiba történt. -service.gui.BAN_FAILED_NOT_ALLOWED={0} letiltása nem sikerült. A csevegőszoba tulajdonosa és rendszergazdája nem tiltható le. -service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS={0} letiltása nem sikerült. A letiltáshoz nincs elég jogosultságod. +service.gui.EXTENDED_AWAY_STATUS=Hosszabb távollét +service.gui.BAN=&Kitiltás +service.gui.BANNED=kitiltva +service.gui.BAN_FAILED=Kitiltás sikertelen +service.gui.BAN_FAILED_GENERAL_ERROR={0} kitiltása nem sikerült. Egy meg nem határozott szerver hiba történt. +service.gui.BAN_FAILED_NOT_ALLOWED={0} kitiltása nem sikerült. A csevegőszoba tulajdonosa és rendszergazdája nem tiltható ki. +service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS={0} kitiltása nem sikerült. Nincs jogosultságod. service.gui.BRB_MESSAGE=Most nem vagyok a gépnél, de nemsokára leszek. service.gui.BROWSE=Böngészés service.gui.BUSY_MESSAGE=Bocsánat, most el vagyok foglalva. @@ -87,7 +92,7 @@ service.gui.CALL=Hívás service.gui.CALL_CONTACT=Partner hívása service.gui.CALL_FAILED=Sikertelen hívás service.gui.CALL_HISTORY_TOOL_TIP=A korábbi hívások listájáért kattints ide. -service.gui.CALL_HISTORY_GROUP_NAME=Korábbi hívások +service.gui.CALL_HISTORY_GROUP_NAME=Hívástörténet service.gui.CALL_VIA=Hívás ezen keresztül: service.gui.CALL_NAME_OR_NUMBER=Név vagy szám hívása service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=Ezzel a hívással csak a {0} hálózatban lévők, és a te {1} fiókod hívható. {2} nem tartalmaz ehhez a hálózathoz, illetve fiókhoz tartozó címet. @@ -106,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Ebbe a mezőbe írd be az új beceneved. service.gui.CHANGE_NICKNAME_ERROR=Hiba a becenév megváltoztatása közben service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Ez a becenév már létezik service.gui.CHANGE_VIDEO_QUALITY=A távoli videó minőség megváltoztatása -service.gui.CHAT_CONFERENCE_LABEL=Konferenciák service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} konferenciája service.gui.CHAT_ROOM_ALREADY_JOINED=A(z) {0} csevegés már csatlakozott. service.gui.CHAT_ROOM_CONFIGURATION={0} csevegés beállítása @@ -120,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=távozott {0}-ból/ből service.gui.CHAT_ROOM_USER_KICKED=ki lett rúgva {0}-ból/ből service.gui.CHAT_ROOM_USER_QUIT=kilépett {0}-ból/ből service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Tilos üzenet küldeni (hang nem engedélyezett) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Elmenti a csevegést későbbi használatra -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Törli a kiválasztott csevegést az elmentett csevegések listájából. service.gui.CHAT_ROOM_NAME=Csevegés neve service.gui.CLEAR_CUSTOM_MESSAGES=Testreszabott üzenetek törlése service.gui.ROOM_NAME=Csevegés -service.gui.AUTOJOIN=Automatikus csatlakozás service.gui.CHANGE_PASSWORD=Jelszó megváltoztatása service.gui.CHAT_ROOM_NAME_INFO=Ebbe a mezőbe írd be a létrehozandó csevegés nevét. service.gui.CHAT_ROOM_NOT_EXIST=A(z) {0} csevegés nem található a(z) {1} szerveren. Ellenőrizd, hogy beírt név helyes-e. service.gui.CHAT_ROOM_NOT_CONNECTED=A(z) {0} csevegéshez való csatlakozáshoz be kell jelentkezned. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Csak bejelentkezve tudsz kilépni a csevegésből. -service.gui.CHAT_ROOM_NOT_JOINED=A csevegéshez előbb csatlakoznod kell, hogy abban további műveleteket tudj kezdeményezni. service.gui.CHAT_ROOM_OPTIONS=Csevegés beállítások service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=A(z) {0} csevegéshez való csatlakozáshoz regisztráció szükséges. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=A(z) {0} csevegés jelszót igényel. @@ -139,6 +139,7 @@ service.gui.CHAT_ROOMS=Csevegések service.gui.CHAT_ROOM=Csevegés service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} megváltoztatta a tárgyat {1}-ra/re service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=Folytathatod a beszélgetést a {0} csevegésben. +service.gui.CHAT_NICKNAME_CHANGE={0} új neve {1} service.gui.CHOOSE_CONTACT=Válassz partnert service.gui.CHOOSE_NUMBER=Válassz számot service.gui.CHOOSE_ACCOUNT=Válassz egyet a alábbi fiókok közül. @@ -149,54 +150,199 @@ service.gui.CLEAR=Törlés service.gui.CLOSE=Bezár service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Az utolsó üzenetet kevesebb mint 2 másodperccel ezelőtt kaptad. Biztos, hogy be akarod zárni ezt a csevegést? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Fájlküldés folyamatban. Biztos, hogy le akarod állítani? -service.gui.CONFIRM=Mehet service.gui.CONNECTED_STATUS=Kapcsolódva service.gui.CONNECTING=Kapcsolódás... service.gui.CONNECTING_STATUS=Kapcsolódás service.gui.CONNECTING_EARLY_MEDIA_STATUS=Kapcsolódás* service.gui.CONNECTION=Kapcsolat -service.gui.CONNECTION_FAILED_MSG=Kapcsolat sikertelen a következő fiókkal: Felhasználó: {0}, szerver név: {1}. Ellenőrizd a hálózati kapcsolatod, vagy további információért lépj kapcsolatba a hálózat-karbantartóval. service.gui.CONNECTION_EXPIRED_MSG=Jelenleg le vagy kapcsolódva a {0} szerverről. service.gui.CONTACT_NAME=Azonosító vagy szám -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=A kiválasztott {0} partner nem képes telefonálni. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=A kiválasztott {0} partner nem képes csevegés konferenciázni. service.gui.CONTACT_PAUSED_TYPING={0} szünetet tart az üzenet írása közben service.gui.CONTACT_TYPING={0} üzenetet ír service.gui.CONTACT_TYPING_SEND_FAILED=hűha... nem tudtuk megmondani {0}-nak/nek, hogy írtál service.gui.CONTACT_INFO=Elérhetőség -service.gui.CONTACTLIST=Partnerlista +service.gui.CONTACTS=Partnerek +service.gui.COPY=Másolás +service.gui.COPY_LINK=Hivatkozás másolása +service.gui.CREATE=Létrehoz +servoce.gui.CREATE_CALL_FAILED=A hívás indítása sikertelen. +service.gui.CREATE_CHAT_ROOM=Csevegés létrehozása... service.gui.CREATE_CHAT_ROOM_ERROR={0} csevegés létrehozása sikertelen. service.gui.CREATE_CHAT_ROOM_WIZARD=Csevegés létrehozó varázsló service.gui.CREATE_CONFERENCE_CALL=Konferenciahívás létrehozása... -service.gui.CREATE_CONFERENCE_CHAT=Konferencia csevegés létrehozása... service.gui.CREATE_GROUP=Csoport létrehozása... service.gui.CREATE_GROUP_NAME=Ebbe a mezőbe írd be a létrehozandó csoport nevét. -service.gui.CREATE_FIRST_GROUP_WIZARD=A partnerlistád nem tartalmaz egy csoportot sem. Először hozz létre egy csoportot (Fájl -> Csoport létrehozása). service.gui.CREATE_VIDEO_BRIDGE=Videó híd létrehozása... service.gui.CREATE_VIDEO_BRIDGE_MENU=Videó híd létrehozása service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Videó konferencia kezdés / csatlakozás service.gui.CREATE_VIDEO_CONFERENCE=Új videó konferencia létrehozása ebben a csevegésben service.gui.CONTACT_INFO_NOT_SUPPORTED=Ennek a partnernek nincs webes elérhetősége service.gui.CUT=Kivágás -service.gui.DATE=Dátum service.gui.DELETE=Töröl service.gui.DENY=Elutasít service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyődet?
    A Rendben-re kattintva a hívás minden résztvevője látni fogja a képernyődet. - - - - +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Képernyő megosztva +service.gui.DIALPAD=Számlap +service.gui.DISPLAY_NAME=Képernyő név +service.gui.DISCONNECTED_STATUS=Kapcsolat bontva +service.gui.DND_STATUS=Ne zavarj +service.gui.DO_NOT_ASK_AGAIN=Többször ne kérdezd +service.gui.DO_NOT_SHOW_AGAIN=Ez az üzenet többször ne jelenjen meg. +service.gui.DRAG_FOR_SHARING=Húzd ide bármit, amit meg akarsz osztani... +service.gui.DURATION=időtartam +service.gui.DESTROY_CHATROOM=Csevegés megsemmisítése +service.gui.DESTROY_MESSAGE=Csevegés megsemmisítése +service.gui.EDIT=Szerkeszt +service.gui.EDITED_AT={0}-nál/nél szerkesztett +service.gui.EMAIL=Email +service.gui.EMAILS=Emailek +service.gui.EMPTY_HISTORY=Előzmények törlése +service.gui.ENABLE_DESKTOP_REMOTE_CONTROL=Munkaasztal távvezérlés engedélyezése +service.gui.ENABLE_TYPING_NOTIFICATIONS=Jelezze másoknál, ha üzenetet írunk nekik (csevegés tevékenység küldése) +service.gui.END_CONFERENCE=Konferencia befejezése +service.gui.ENTER_PHONE_NUMBER=Írd be a telefonszámot +service.gui.ENTER_NAME_OR_NUMBER=Írd be a nevet vagy a számot +service.gui.ERROR=Hiba +service.gui.ERROR_WAS=Hiba: {0} +service.gui.ERROR_RECEIVED_FROM=Hibát kaptunk {0}-tól/től +service.gui.ESTIMATED_TIME=Becsült időtartam: +service.gui.EVENTS=Események +service.gui.EXIT=Kilépés +service.gui.GENERAL=Általános +service.gui.GENERAL_ERROR=Általános hiba +service.gui.GROUP_NAME=Csoport neve +service.gui.FAILED_STATUS=Sikertelen hívás +service.gui.FAILED_TO_JOIN_CHAT_ROOM={0} nem tudott csatlakozni a csevegéshez. +service.gui.FAX=Fax +service.gui.FFC_STATUS=Elérhető (csevegésre) +service.gui.FILE=Fájl +service.gui.FILE_WAITING_TO_ACCEPT=Várakozás {0}-ra/re, hogy elfogadja a fájlodat. +service.gui.FILE_UNABLE_TO_SEND=Hiba a {0}-nak/nek szánt fájl küldése közben. +service.gui.FILE_RECEIVE_FAILED=Hiba a {0}-tól/től érkező fájl fogadása közben. +service.gui.FILE_SENDING_TO=Fájl küldése {0}- nak/nek. +service.gui.FILE_RECEIVING_FROM=Fájl fogadása {0}-tól/től. +service.gui.FILE_SEND_COMPLETED=A fájl küldés sikerült {0}-nak/nek. +service.gui.FILE_RECEIVE_COMPLETED=Fájl fagadva {0}-tól/től. +service.gui.FILE_TRANSFER_CANCELED=Fájl átvitel törölve. +service.gui.FILE_SEND_FAILED=Fájl küldés sikertelen: {0}. +service.gui.FILE_TOO_BIG=A fájlméret meghaladja a protokol által maximálisan engedélyezett méretet: {0}. +service.gui.FILE_SEND_REFUSED={0} visszautasította ezt a fájlt. +service.gui.FILE_TRANSFER_REFUSED=A fájl fogadása vissza lett visszautasítva. +service.gui.FILE_TRANSFER_NOT_SUPPORTED=A kiválasztott partner nem támogatja a fájl átvitelt. +service.gui.FILE_TRANSFER_PREPARING=Fájl küldés előkészítése {0}-nak/nek. Kis türelmet... +service.gui.FILE_TRANSFER_REQUEST_RECIEVED={0} szeretne egy fájlt megosztani veled. +service.gui.FILE_DOES_NOT_EXIST=Az adott fájl nem található. Vagy törölve lett, vagy át lett helyezve. +service.gui.FILE_OPEN_FAILED=Nem sikerült megnyitni a fájlt. Valószínű törölve lett, vagy át lett helyezve. +service.gui.FILE_OPEN_NOT_SUPPORTED=A fájl megnyitás funkciót ez a rendszer sajnos nem támogatja. +service.gui.FILE_OPEN_NO_PERMISSION=Nincs elég jogosultságod ennek a fájlnak a megnyitására. Ellenőrizd az olvasási jogosultságaidat, és próbáld meg újra. +service.gui.FILE_OPEN_NO_APPLICATION=Ehhez a fájl típushoz nem található alkalmazás. +service.gui.FINISH=Befejez +service.gui.FOLDER_DOES_NOT_EXIST=Az ezt a fájlt tartalmazó mappa nem található. Vagy törölve lett, vagy át lett helyezve. +service.gui.FOLDER_OPEN_FAILED=A mappa megnyitása nem sikerült. +service.gui.FOLDER_OPEN_NO_PERMISSION=Nincs elég jogosultságod ennek a mappának a megnyitásához. Ellenőrizd az olvasási jogosultságaidat, és próbáld meg újra. +service.gui.FOLDER_OPEN_NO_APPLICATION=Nem találtunk olyan alkalmazást, ami meg tudná nyitni ezt a mappát. +service.gui.FONT=Betűtípus +service.gui.FONT_BOLD=Félkövér +service.gui.FONT_COLOR=Szín +service.gui.FONT_FAMILY=Család +service.gui.FONT_ITALIC=dőlt +service.gui.FONT_SIZE=Méret +service.gui.FONT_STYLE=Stílus +service.gui.FONT_UNDERLINE=Aláhúzott +service.gui.GRANT_OWNERSHIP=Tulajdonjog megadása... +service.gui.GRANT_ADMIN=Adminisztrátor jogosultság megadása... +service.gui.GRANT_MODERATOR=Közvetítő (moderator) jogosultság megadása +service.gui.GRANT_MEMBERSHIP=Tagság megadása +service.gui.GRANT_VOICE=Hang megadása +service.gui.GUEST=látogató +service.gui.HANG_UP=Vonalbontás +service.gui.HD_QUALITY=HD videó +service.gui.HELP=Súgó +service.gui.HIDE=Elrejt +service.gui.HIDE_OFFLINE_CONTACTS=Kijelentkezett partnerek elrejtése +service.gui.HIDE_MAIN_WINDOW=
    Az X ablak gomb megnyomása nem lépteti ki az alkalmazást, hanem
    csak elrejti. Ha ki akarsz lépni, akkor azt a Fájl/Kilépés pontra kattintva teheted.
    +service.gui.HISTORY=Előzmények +service.gui.HISTORY_CONTACT=Előzmények - {0} +service.gui.HISTORY_TOGGLE_PER_CONTACT=Az ehhez a partnerhez tartozó előzmények rögzítésének kikapcsolása +service.gui.HISTORY_TOGGLE_PER_CHATROOM=Előzmények kikapcsolása ebben a csevegésben +service.gui.HISTORY_TOGGLE_ALL=Előzmények kikapcsolása az összes csevegésben, és az összes partnerrel +service.gui.HISTORY_ERASE_PER_CONTACT=Az összes előzmény törlése ezzel a partnerrel +service.gui.HISTORY_ERASE_PER_CHATROOM=Az összes előzmény törlése ebben a csevegésben +service.gui.HISTORY_ERASE_ALL=Az összes előzmény törlése {0}-ban/ben +service.gui.HISTORY_REMOVE_PER_CONTACT_WARNING=Biztosan véglegesen törölni akarod az összes ezen a gépen tárolt üzenetet {0}-val/vel? +service.gui.HISTORY_REMOVE_ALL_WARNING=Biztosan véglegesen törölni akarod az összes ezen a gépen tárolt üzenetet? +service.gui.HISTORY_REMOVE_ERROR=Az ezen a gépen tárolt üzenetek törlése nem sikerült. +service.gui.HOME=Kezdőlap +service.gui.HOME_PAGE=Kezdő oldal +service.gui.ICE=ICE (?) +service.gui.IDENTIFIER=Azonosító +service.gui.IGNORE=Mégse +service.gui.INSERT_SMILEY=Mosolygó arc beillesztése +service.gui.INCOMING_CALL=Bejövő hívás {0}-tól/től +service.gui.INCOMING_SCREEN_SHARE=Képernyőmegosztás kezdeményezés {0}-tól/től +service.gui.INCOMING_CALL_STATUS=Bejövő hívás +service.gui.INCOMING_SCREEN_SHARE_STATUS=Bejövő képernyőmegosztás +service.gui.INSTANT_MESSAGINGS=Üzenetek +service.gui.IM=Üzenet +service.gui.INITIATING_CALL_STATUS=Hívás kezdeményezése +service.gui.INVITATION=Meghívó szövege +service.gui.INVITATION_RECEIVED=Meghívás érkezett +service.gui.INVITATION_RECEIVED_MSG={0} meghívott, hogy csatlakozz a(z) {1} csevegéshez. Elfogadhatod, elutasíthatod, vagy figyelmen kívül hagyhatod ezt a meghívást. +service.gui.INVITATION_REJECTED={0} elutasította meghívásodat a csevegéshez való csatlakozáshoz. Ok: {1}. +service.gui.INVITE=Meghív +service.gui.INVITE_CONTACT_MSG=Válaszd ki azoknak a partnereknek a nevét, akiket ehhez a csevegéshez szeretnél hozzáadni, és kattints a Meghív gombra. +service.gui.INVITE_CONTACT_TO_CHAT=Partnerek meghívása csevegéshez +service.gui.INVITE_CONTACT_TO_CALL=Partnerek meghívása beszélgetéshez +service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Partnerek meghívása videó átjátszásra (video bridge) +service.gui.INVITE_REASON=A meghívás oka +service.gui.IS_CALLING={0} hív... +service.gui.IS_NOW={0} mostantól {1} +service.gui.JOIN=Csatlakozás +service.gui.JOIN_AS=Csatlakozás másként +service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Csatlakozás meglévő videókonferenciához +service.gui.JOIN_VIDEO=Videó csatlakoztatása +service.gui.JOB_TITLE=Beosztás +service.gui.JOIN_CHAT_ROOM=Csatlakozás csevegéshez... +service.gui.JOIN_CHAT_ROOM_TITLE=Csatlakozás csevegéshez +service.gui.JOIN_CHAT_ROOM_NAME=Írd be a csevegés nevét, amihez csatlakozni szeretnél. +service.gui.JOIN_CHAT_ROOM_WIZARD=Csevegés csatlakozó varázsló +service.gui.JOIN_AUTOMATICALLY=Csatlakozás automatikusan +service.gui.DONT_JOIN_AUTOMATICALLY=Ne csatlakozzon automatikusan +service.gui.KICK=Kick (?) +service.gui.KICK_FAILED=Kirúgás sikertelen +service.gui.KICK_FAILED_GENERAL_ERROR={0} kirúgása nem sikerült. Általános szerver hiba történt. +service.gui.KICK_FAILED_NOT_ALLOWED={0} kirúgása nem sikerült. A csevegés tulajdonosát és adminisztrátorát nem lehet kirúgni. +service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS={0} kirúgása nem sikerült. A kirúgáshoz nincs elég jogosultságod. +service.gui.LAST_NAME=Vezetéknév +service.gui.LEAVE=Elhagy +service.gui.LIMIT_REACHED_FOR_IP=Túl sok regisztráció van már a helyi IP címről, és a(z) {0} szerver nem enged már többet nyitni. +service.gui.LIST=Lista +service.gui.LOADING_ROOMS=Csevegések betöltése... +service.gui.LOADING=Betöltés... +service.gui.LOCALLY_ON_HOLD_STATUS=Helyileg várakoztatva +service.gui.LOGIN_NETWORK_ERROR=A bejelentkezés hálózati hiba miatt nem sikerült: felhasználó: {0}, szerver név: {1}. Ellenőrizd a hálózati csatlakozásodat. +service.gui.LOGIN_GENERAL_ERROR=Hiba bejelentkezés közben: felhasználó: {0}, szerver név: {1}:{2}. +service.gui.chat.role.ADMINISTRATOR=rendszergazda +service.gui.SHOW_OFFLINE_CONTACTS=Kijelentkezett partnerek elrejtése + + + + +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names # keep the following string short # service.gui.avatar.imagepicker +service.gui.avatar.imagepicker.CANCEL=Mégse -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -204,12 +350,28 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd # New Account Dialog # LDAP +impl.ldap.GENERAL=Általános +impl.ldap.EDIT=Szerkeszt +impl.ldap.CANCEL=Mégse +impl.ldap.MAIL_FIELD_EXAMPLE=Email + +# SIP Protocol + +#Jabber Protocol # Address book plugin # Google Contacts +impl.googlecontacts.EDIT=Szerkeszt +impl.googlecontacts.CANCEL=Mégse # account info +plugin.accountinfo.DISPLAY_NAME=Képernyő név +plugin.accountinfo.LAST_NAME=Vezetéknév +plugin.accountinfo.CITY=Város +plugin.accountinfo.COUNTRY=Ország +plugin.accountinfo.EMAIL=Email +plugin.accountinfo.JOB_TITLE=Beosztás # connection info @@ -218,10 +380,8 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd # aimaccregwizz # branding +plugin.branding.ABOUT_MENU_ENTRY=Névjegy -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -230,50 +390,54 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd # icqaccregwizz # irc accregwizz +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} engedélyezés # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +plugin.sipaccregwizz.DISPLAY_NAME=Képernyő név +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker +plugin.updatechecker.BUTTON_CLOSE=Bezár # usersearch # whiteboard - -# yahoo accregwizz - -# zero accregwizz +plugin.whiteboard.COLOR=Szín +plugin.whiteboard.DELETE=Töröl # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +plugin.keybindings.CHAT_COPY=Másolás +plugin.keybindings.CHAT_CUT=Kivágás +#Enum KeybindingSet.Category +plugin.keybindings.CHAT=Csevegés # Notification Configuration Form +#NotificationsTable constants +plugin.notificationconfig.event.IncomingCall=Bejövő hívás +plugin.notificationconfig.event.IncomingFile=Bejövő hívás +plugin.notificationconfig.event.HangUp=Vonalbontás # ZRTP Securing # ZRTP Configuration +impl.media.security.zrtp.TITLE=Hívás @@ -281,6 +445,7 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -288,6 +453,10 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd # Security configuration form title # otr plugin +plugin.otr.authbuddydialog.CANCEL=Mégse +plugin.otr.authbuddydialog.HELP=Súgó +plugin.otr.configform.GENERATE=Általános +plugin.otr.configform.COLUMN_NAME_CONTACT=Partnerek # global proxy plugin #plugin.globalproxy.PROTOCOL_SUPPORT @@ -297,17 +466,21 @@ service.gui.DESKTOP_SHARING_WARNING=Biztosan meg akarod osztani a képernyőd #plugin chat config +plugin.chatconfig.TITLE=Csevegés #provisioning plugin # packet logging service # dns config plugin +net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Mégse +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=Elutasít #plugin spellcheck #Certificate configuration plugin +plugin.certconfig.KEYSTORE=Fájl # Phone number contact source plugin -- cgit v1.1 From 58a5f15be5a620b9a8a18428eb56dca0e7271aed Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:26 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 70 of 1505 strings translated (46 fuzzy). --- resources/languages/resources_lt.properties | 88 ++++++++++++++--------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/resources/languages/resources_lt.properties b/resources/languages/resources_lt.properties index 188d04a..2685111 100644 --- a/resources/languages/resources_lt.properties +++ b/resources/languages/resources_lt.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -25,46 +36,39 @@ # from your system's language, pass the language code to ant: # ant -Duser.language=xx run -service.gui.ABOUT=Apie -service.gui.ACCEPT=Sutinku +service.gui.ABOUT=&Apie +service.gui.ACCEPT=&Priimti service.gui.ACCOUNT=Paskyra service.gui.ACCOUNT_ME=Aš service.gui.ACCOUNT_REGISTRATION_WIZARD=Paskyros registravimo vedlys service.gui.ACCOUNTS=Paskyros -service.gui.ADD=Pridėti -service.gui.ADD_ACCOUNT=Pridėti paskyrą -service.gui.ADD_CONTACT=Pridėti kontaktą -service.gui.ADD_CONTACT_TO=Pridėti kontaktą į +service.gui.ADD=&Pridėti +service.gui.ADD_CONTACT=&Pridėti kontaktą +service.gui.ADD_CONTACT_TO=&Pridėti kontaktą į service.gui.ADD_CONTACT_ERROR=Nepavyko pridėti kontakto, kurio id: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Klaida pridedant kontaktą -service.gui.ADD_CONTACT_EXIST_ERROR=Kontaktas ''{0}'' jau yra jūsų kontaktų sąraše. -service.gui.ADD_CONTACT_IDENTIFIER=Žemiau esančiame lauke įveskite kontakto, kurį norite pridėti, identifikatorių. -service.gui.ADD_CONTACT_WIZARD=Kontakto pridėjimo vedlys. +service.gui.ADD_CONTACT_EXIST_ERROR=Kontaktas {0} jau yra jūsų kontaktų sąraše. service.gui.ADD_GROUP_LOCAL_ERROR=Nepavyko pridėti grupės: {0}. Įvyko vietinė įvesties/išvesties klaida. -service.gui.ADD_GROUP_EXIST_ERROR={0} jau yra jūsų kontaktų sąraše. Pasirinkite kitą pavadinimą. -service.gui.ADD_GROUP_NET_ERROR=Nepavyko pridėti grupės: {0}. Įvyko tinklo klaida. Patikrinkite savo tinklo jungtį ir pabandykite iš naujo. +service.gui.ADD_GROUP_EXIST_ERROR=Grupė {0} jau yra jūsų kontaktų sąraše. Pasirinkite kitą pavadinimą. +service.gui.ADD_GROUP_NET_ERROR=Nepavyko pridėti grupės: {0}. Įvyko tinklo klaida. Patikrinkite savo tinklo ryšį ir bandykite dar kartą. service.gui.ADD_GROUP_ERROR=Nepavyko pridėti grupės: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Grupės pavadinimas negali būti tuščias. -service.gui.ADD_GROUP=Sukurti grupę -service.gui.ADD_SUBCONTACT=Pridėti kontaktą kontakte service.gui.ADMINISTRATOR=administratorius service.gui.ADVANCED=papildomi nustatymai -service.gui.ALL=Visi -service.gui.ALL_CONTACTS=Visi kontaktai -service.gui.APPLY=Taikyti +service.gui.ALL_CONTACTS=&Visi kontaktai +service.gui.APPLY=&Taikyti service.gui.ARE_CALLING=skambina... service.gui.ARE_NOW=Jūs dabar esate {0} service.gui.AT=prie service.gui.AUTHORIZATION_ACCEPTED=kontaktas priėmė jūsų kvietimą. service.gui.AUTHENTICATION_FAILED=Autentifikacija nepavyko. Įvestas neteisingas slaptažodis. -service.gui.AUTHENTICATION_REQUESTED=Reikalinga autentifikacija -service.gui.AUTHENTICATION_REQUESTED_SERVER=Serveris {0} paprašė jūsų autentifikacijos +service.gui.AUTHENTICATION_REQUESTED_SERVER=Serveris {0} paprašė jūsų nustatyti tapatybę. service.gui.AUTHENTICATION_REJECTED=kontaktas atmetė jūsų kvietimą. service.gui.AUTHENTICATION_WINDOW_TITLE={0} kvietimas service.gui.AUTHORIZATION_REQUESTED=Reikalingas kvietimo priėmimas. service.gui.AUTHORIZATION_REQUESTED_INFO=Kontaktas {0} prašo jūsų sutikimo. service.gui.AUTHORIZATION_RESPONSE=Sutikimo atsakymas -service.gui.AWAY_STATUS=Išėjęs +service.gui.AWAY_STATUS=Pasišalinęs service.gui.BAN=&Uždrausti service.gui.BAN_FAILED=Uždraudimas nepavyko service.gui.BAN_FAILED_GENERAL_ERROR={0} Uždraudimas nepavyko. Įvyko serverio klaida. @@ -96,12 +100,10 @@ service.gui.CHAT_ROOM_USER_KICKED=buvo išmestas iš {0} service.gui.CHAT_ROOM_USER_QUIT=išėjo iš {0} service.gui.CHAT_ROOM_NAME=Pokalbių kambario pavadinimas service.gui.ROOM_NAME=Pakalbių Kambarys -service.gui.AUTOJOIN=Automatinis prisijungimas service.gui.CHAT_ROOM_NAME_INFO=Žemiau esančiame lauke įveskite kuriamo pokalbių kambario pavadinimą. service.gui.CHAT_ROOM_NOT_EXIST={0} kambarys nerastas {1} serveryje. Prašau patikrinti ar teisingai įvedėte pavadinimą. service.gui.CHAT_ROOM_NOT_CONNECTED=Jūs turite būti užsiregistravęs, jei norite prisijungti prie {0} pokalbių kambario. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Jūs turite būti užsiregistravęs, jei norite palikti pokalbių kambarį. -service.gui.CHAT_ROOM_NOT_JOINED=Turite būti prisijungęs prie pokalbių kambario, jei norite atlikti tolimesnius veiksmus su juo. service.gui.CHAT_ROOM_OPTIONS=Pokalbių kambario nustatymai service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Norint prisijungti prie {0} pokalbių kambario reikalinga registracija. service.gui.CHAT_ROOM_REQUIRES_PASSWORD={0} pokalbių kambarys reikalauja slaptažodžio. @@ -115,9 +117,7 @@ service.gui.CONNECTING=Jungiamasi... service.gui.CONNECTING_STATUS=Jungtis service.gui.CONNECTING_EARLY_MEDIA_STATUS=Jungiamasi... service.gui.CONNECTION=Jungtis -service.gui.CONNECTION_FAILED_MSG=Įvyko klaida bandant prisijungti šiai paskyrai: Vartotojo vardas: {0}, Serverio vardas: {1}. Patikrinkite savo tinklo jungtį arba susisiekite su tinklo administratoriumi. service.gui.CONNECTION_EXPIRED_MSG=Jūs esate atsijungęs nuo {0} serverio. -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Pasirinktas kontaktas nepalaiko telefoninių pokalbių. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Pasirinktas kontaktas nepalaiko konferenciniu pokalbių kambarių. service.gui.CONTACT_PAUSED_TYPING={0} stabtelėjo rašant žinutę service.gui.CONTACT_TYPING={0} rašo žinutę @@ -130,23 +130,25 @@ service.gui.CREATE_CHAT_ROOM=&Sukurti pokalbių kambarį... service.gui.CREATE_CHAT_ROOM_ERROR=Nepavyko sukurti {0} pokalbių kambario. service.gui.CREATE_CHAT_ROOM_WIZARD=Pokalbių kambario kūrimo vedlys service.gui.CREATE_CONFERENCE_CALL=&Pradėti konferencinį skambutį... -service.gui.CREATE_CONFERENCE_CHAT=&Pradėti konferencinį pokalbių kambarį... service.gui.CREATE_GROUP=&Sukurti grupę... service.gui.CREATE_GROUP_NAME=Žemiau esančiame lauke įveskite kuriamos grupės pavadinimą. -service.gui.CREATE_FIRST_GROUP_WIZARD=Jūsų kontaktų sąraše nėra jokių grupių. Pirma sukurkite grupę (Failas/Sukurti grupę). service.gui.FAILED_STATUS=Skambutis nepavyko service.gui.IS_CALLING=skambina... -service.gui.CLOSE_CHAT_ROOM_DIALOG=Uždaryti service.gui.KICK_FAILED_GENERAL_ERROR={0} Uždraudimas nepavyko. Įvyko serverio klaida. service.gui.KICK_FAILED_NOT_ALLOWED={0} Uždraudimas nepavyko. Kambario savininkas ir administratorius negali būti uždraustas. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS={0} Uždraudimas nepavyko. Jūs neturite reikalingų teisių. +service.gui.chat.role.ADMINISTRATOR=administratorius + +#enum values from IceProcessingState -service.gui.security.COMPARE_WITH_PARTNER=Palyginkite su partneriu ir paspauskite ant užrakto patvirtinimui. +#service.gui.CERT_INFO_ are combined from Rdn names + + # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Palyginkite su parnteriu: {0} @@ -155,9 +157,6 @@ service.gui.avatar.imagepicker.CANCEL=&Panaikinti -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -167,6 +166,10 @@ service.gui.avatar.imagepicker.CANCEL=&Panaikinti # LDAP impl.ldap.CANCEL=&Panaikinti +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -183,9 +186,6 @@ impl.googlecontacts.CANCEL=&Panaikinti # branding plugin.branding.ABOUT_MENU_ENTRY=Apie -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -194,23 +194,19 @@ plugin.branding.ABOUT_MENU_ENTRY=Apie # icqaccregwizz # irc accregwizz +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} kvietimas # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -220,23 +216,20 @@ plugin.updatechecker.BUTTON_CLOSE=Uždaryti # whiteboard -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=&Kopijuoti +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Pokalbis # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -249,6 +242,7 @@ impl.media.security.zrtp.TITLE=Skambinti +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. -- cgit v1.1 From 9e632fa2437225e5a1950da1f381106e0eea19c0 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:33 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1644 of 1655 strings translated (3 fuzzy). --- resources/languages/resources_es.properties | 180 ++-------------------------- 1 file changed, 11 insertions(+), 169 deletions(-) diff --git a/resources/languages/resources_es.properties b/resources/languages/resources_es.properties index 3892235..28b5083 100644 --- a/resources/languages/resources_es.properties +++ b/resources/languages/resources_es.properties @@ -43,7 +43,6 @@ service.gui.ACCOUNT_ME=Yo service.gui.ACCOUNT_REGISTRATION_WIZARD=Asistente para registrar una cuenta service.gui.ACCOUNTS=Cuentas service.gui.ADD=Agregar -service.gui.ADD_ACCOUNT=Agregar cuenta service.gui.ADD_CONTACT=Agregar contacto service.gui.ADD_AUTHORIZED_CONTACT=Agregar {0} a su lista de contactos service.gui.ADD_CONTACT_TO_CONTACTLIST=Agregar contacto a su lista de contactos @@ -53,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Error al agregar contacto service.gui.ADD_CONTACT_EXIST_ERROR=El contacto {0} ya existe en su lista de contactos. service.gui.ADD_CONTACT_NETWORK_ERROR=El servidor no responde a la solicitud de agregar el contacto con id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=No se pudo agregar el contacto con id: {0}. Operación no soportada. -service.gui.ADD_CONTACT_IDENTIFIER=Introduzca en el campo inferior el identificador del contacto que desea agregar. -service.gui.ADD_CONTACT_WIZARD=Asistente para agregar contactos service.gui.ADD_CONTACT_NOT_CONNECTED=Usted necesita estar conectado para agregar un contacto. Por favor, inicie sesión con el proveedor seleccionado, y vuelva a intentarlo. service.gui.ADD_GROUP_LOCAL_ERROR=No fue posible agregar el grupo: {0}. El problema ocurrió en una operación de entrada/salida local. service.gui.ADD_GROUP_EXIST_ERROR=El grupo {0} ya existe en su lista de contactos. Elija otro nombre. service.gui.ADD_GROUP_NET_ERROR=No se pudo agregar el grupo: {0}. El problema fue causado por un error en la red. Por favor, revise su conexión de red e inténtelo nuevamente. service.gui.ADD_GROUP_ERROR=No se pudo agregar el grupo: {0}. service.gui.ADD_GROUP_EMPTY_NAME=El nombre del grupo no puede estar vacío. -service.gui.ADD_GROUP=Crear grupo -service.gui.ADD_SUBCONTACT=&Agregar subcontacto service.gui.ADDRESS=Dirección service.gui.ADMINISTRATOR=administrador service.gui.ADVANCED=&Avanzado -service.gui.ALL=&Todos service.gui.ALL_CONTACTS=&Todos los contactos service.gui.ALTERNATE_ADDRESS=Dirección alterna service.gui.APPLY=&Aplicar @@ -76,7 +70,6 @@ service.gui.AT=a las service.gui.AUTHORIZE=&Autorizar service.gui.AUTHORIZATION_ACCEPTED={0} ha aceptado su solicitud de autorización. service.gui.AUTHENTICATION_FAILED=La autenticación falló para {0}. La contraseña que ha introducido no es válida. -service.gui.AUTHENTICATION_REQUESTED=Solicitud de autenticación service.gui.AUTHENTICATION_REQUESTED_SERVER=El servidor {0} ha solicitado su autenticación. service.gui.AUTHENTICATION_REJECTED={0} ha rechazado su solicitud de autorización. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autenticación @@ -118,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=En el siguiente campo, puede introducir su nue service.gui.CHANGE_NICKNAME_ERROR=Error al cambiar el apodo service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=El apodo ya existe service.gui.CHANGE_VIDEO_QUALITY=Cambiar la calidad del vídeo remoto -service.gui.CHAT_CONFERENCE_LABEL=Conferencias service.gui.CHAT_CONFERENCE_ITEM_LABEL=Conferencia de {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Ya se encuentra en la sala {0}. service.gui.CHAT_ROOM_CONFIGURATION=Configuración de la sala {0} @@ -132,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=ha abandonado {0} service.gui.CHAT_ROOM_USER_KICKED=ha sido expulsado de {0} service.gui.CHAT_ROOM_USER_QUIT=ha cerrado su sesión {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=El Envió de mensajes esta prohibido (revocado) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Guardar la sala de chat para uso posterior -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Eliminar la sala seleccionada de la lista de salas guardadas service.gui.CHAT_ROOM_NAME=Nombre de la sala de charlas service.gui.CLEAR_CUSTOM_MESSAGES=Limpiar mensajes personalizados service.gui.ROOM_NAME=Sala de charla -service.gui.AUTOJOIN=Auto-ingresar service.gui.CHANGE_PASSWORD=Cambiar contraseña service.gui.CHAT_ROOM_NAME_INFO=Introduzca en el campo inferior el nombre con el que desea crear la sala de charlas. service.gui.CHAT_ROOM_NOT_EXIST=La sala {0} no existe en el servidor {1}. Por favor, compruebe que el nombre es el correcto. service.gui.CHAT_ROOM_NOT_CONNECTED=Necesita estar conectado para entrar en la sala {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Tiene que estar conectado para abandonar una sala de chat. -service.gui.CHAT_ROOM_NOT_JOINED=Necesita estar dentro de la sala de charlas para realizar acciones sobre ella. service.gui.CHAT_ROOM_OPTIONS=Opciones de la sala service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Necesita registrarse antes poder entrar en la sala {0}. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=La sala {0} ha solicitado contraseña. @@ -162,24 +150,20 @@ service.gui.CLEAR=Vaciar service.gui.CLOSE=Cerra&r service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Recibió un nuevo mensaje hace menos de 2 segundos. ¿Está seguro de querer abandonar esta sala de chat? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Tiene transferencias de archivos activas. ¿Está seguro que desea cancelarlas? -service.gui.CONFIRM=Confirmar service.gui.CONNECTED_STATUS=Conectado service.gui.CONNECTING=Conectando... service.gui.CONNECTING_STATUS=Conectando service.gui.CONNECTING_EARLY_MEDIA_STATUS=Conectando* service.gui.CONNECTION=Conexión -service.gui.CONNECTION_FAILED_MSG=Falló la conexión para la cuenta: Usuario: {0}, Servidor: {1}. Por favor, verifique su conexión a la red o contacte con el administrador de red para más información. service.gui.CONNECTION_EXPIRED_MSG=Actualmente está desconectado del servidor {0}. service.gui.CONTACT_NAME=ID o Número service.gui.CONTACT_NAME_PROMPT=juana.perez@ejemplo.com service.gui.CONTACT_NAME_INFO=Agregar una dirección de mensajería instantánea (como juana.perez@ejemplo.com) o un número de VoIP -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=El contacto {0} no soporta telefonía. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=El contacto {0} no soporta conferencias. service.gui.CONTACT_PAUSED_TYPING={0} paró de escribir un mensaje service.gui.CONTACT_TYPING={0} está escribiendo un mensaje service.gui.CONTACT_TYPING_SEND_FAILED=oh-oh... no le pudimos decir a {0} que está escribiendo service.gui.CONTACT_INFO=Información de &contacto -service.gui.CONTACTLIST=Lista de Contactos service.gui.CONTACTS=Contactos service.gui.COPY=&Copiar service.gui.COPY_LINK=Copiar en&lace @@ -189,17 +173,14 @@ service.gui.CREATE_CHAT_ROOM=&Crear sala de charlas... service.gui.CREATE_CHAT_ROOM_ERROR=Falló la creación de la sala {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Asistente de creación de salas de charlas service.gui.CREATE_CONFERENCE_CALL=&Crear una conferencia... -service.gui.CREATE_CONFERENCE_CHAT=&Crear una conferencia... service.gui.CREATE_GROUP=&Crear grupo... service.gui.CREATE_GROUP_NAME=Introduzca en el campo inferior el nombre del grupo que desea crear. -service.gui.CREATE_FIRST_GROUP_WIZARD=Su lista de contactos no contiene ningún grupo. Por favor, cree primero un grupo (Archivo/Crear grupo). service.gui.CREATE_VIDEO_BRIDGE=Crear un puente de &vídeo... service.gui.CREATE_VIDEO_BRIDGE_MENU=Crear un puente de &vídeo service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Crear / Unirse a videoconferencia service.gui.CREATE_VIDEO_CONFERENCE=Crear una nueva videoconferencia para esta sala de chat service.gui.CONTACT_INFO_NOT_SUPPORTED=Este contacto no soporta información de contacto web service.gui.CUT=Cor&tar -service.gui.DATE=Fecha service.gui.DELETE=Eliminar service.gui.DENY=&Denegar service.gui.DESKTOP_SHARING_WARNING=¿Está seguro de que desea compartir su pantalla?
    Al pulsar Aceptar permitirá que los miembros de esta llamada vean su pantalla. @@ -212,7 +193,6 @@ service.gui.DISCONNECTED_STATUS=Desconectado service.gui.DND_STATUS=No molestar service.gui.DO_NOT_ASK_AGAIN=No volver a preguntar service.gui.DO_NOT_SHOW_AGAIN=No mostrar este mensaje de nuevo -service.gui.DOWNLOAD_NOW=&Descargar ahora service.gui.DRAG_FOR_SHARING=Arrastre hasta aquí lo que desea compartir... service.gui.DURATION=duración service.gui.DESTROY_CHATROOM=Destruir sala de charlas @@ -233,7 +213,6 @@ service.gui.ERROR_RECEIVED_FROM=Se recibió un error de {0} service.gui.ESTIMATED_TIME=Tiempo estimado: service.gui.EVENTS=Eventos service.gui.EXIT=&Salir -service.gui.EXTENDED_CRITERIA=Criterios extendidos service.gui.GENERAL=General service.gui.GENERAL_ERROR=Error general service.gui.GROUP_NAME=Nombre del grupo @@ -275,7 +254,6 @@ service.gui.FONT_ITALIC=Itálica service.gui.FONT_SIZE=Tamaño service.gui.FONT_STYLE=Estilo service.gui.FONT_UNDERLINE=Subrayado -service.gui.FROM={0} de {1} service.gui.GRANT_OWNERSHIP=Permitir ser el propietario... service.gui.GRANT_ADMIN=Permitir administrar... service.gui.GRANT_MODERATOR=Permitir moderar @@ -301,7 +279,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=¿Está seguro de que desea eliminar de f service.gui.HISTORY_REMOVE_ERROR=Error al eliminar los mensajes almacenados localmente. service.gui.HOME=Inicio service.gui.HOME_PAGE=Página inicial -service.gui.HOUR=Hora service.gui.ICE=ICE service.gui.IDENTIFIER=Identificador service.gui.IGNORE=&Ignorar @@ -325,13 +302,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Invitar contactos al puente de vídeo service.gui.INVITE_REASON=Motivo de la invitación service.gui.IS_CALLING={0} está llamando... service.gui.IS_NOW={0} ahora es {1} -service.gui.JITSI_WARNING=SIP Communicator ha sido renombrado recientemente como Jitsi.
    Si desea que su versión se mantenga actualizada, entonces debe descargar Jitsi ahora.

    Disculpe cualquier inconveniencia que esto le pueda causar.

    El equipo de desarrollo de Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator ahora es Jitsi service.gui.JOIN=&Entrar service.gui.JOIN_AS=E&ntrar como service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Unirse a una videoconferencia existente service.gui.JOIN_VIDEO=Unir vídeo -service.gui.CLOSE_CHAT_ROOM_DIALOG=Cerra&r service.gui.JOB_TITLE=Puesto service.gui.JOIN_CHAT_ROOM=&Entrar a la sala... service.gui.JOIN_CHAT_ROOM_TITLE=Entrar a la sala @@ -344,7 +318,6 @@ service.gui.KICK_FAILED=Expulsar falló service.gui.KICK_FAILED_GENERAL_ERROR=Falló la expulsión de {0}. Ocurrió un error general en el servidor. service.gui.KICK_FAILED_NOT_ALLOWED=Falló la expulsión de {0}. Ni el dueño ni el administrador de la sala pueden ser expulsados. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Fallo al expulsar a {0}. No dispone de los privilegios necesarios. -service.gui.LAST=Último service.gui.LAST_NAME=Apellidos: service.gui.LEAVE=&Abandonar service.gui.LIMIT_REACHED_FOR_IP=Existen muchas cuentas registradas en el servidor {0} desde su dirección IP local, y no permite establecer más. @@ -364,7 +337,6 @@ service.gui.MESSAGE=Mensaje service.gui.MISSED_CALLS_TOOL_TIP=Llamadas perdidas de: service.gui.MISSED_CALLS_MORE_TOOL_TIP= y {0} más service.gui.MODERATOR=moderador -service.gui.MORE=Ver más service.gui.MORE_LABEL=Ver más service.gui.MOVE=Mover service.gui.MOVE_SUBCONTACT=M&over contacto @@ -373,7 +345,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=El contacto que ha elegido es el mismo que\n service.gui.MOVE_SUBCONTACT_QUESTION=¿Está seguro de querer mover a {0} a {1}? service.gui.MOVE_TO_GROUP=&Mover al grupo service.gui.MOVE_CONTACT=Mover contacto -service.gui.MOVE_CONTACT_ERROR=El contacto no se puede mover service.gui.MSG_DELIVERY_FAILURE=El mensaje de arriba no pudo ser entregado service.gui.MSG_DELIVERY_NOT_SUPPORTED=El protocolo que está utilizando no soporta mensajes mientras está desconectado. Puede intentar comunicarse con {0} usando otro protocolo o esperar a que se conecte. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Ocurrió un error interno. Es muy probable que sea un fallo de programación. Infórmelo en: https://jitsi.org/Development/BugsAndIssues. @@ -387,7 +358,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Debe estar conectado para poder enviar m service.gui.MULTIPLE_LOGINS=Se ha conectado más de una vez con la misma cuenta de usuario. La cuenta: Usuario: {0}, Servidor: {1} está actualmente desconectada. service.gui.MY_CHAT_ROOMS=Agregar sala de Chat service.gui.MY_CHAT_ROOMS_TITLE=Agregar sala de chat -service.gui.MUTE=Silencio service.gui.MUTUALLY_ON_HOLD_STATUS=Mutuamente en Espera service.gui.NAME=Nombre service.gui.NETWORK=Red @@ -419,7 +389,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=No está en la lista de Contactos service.gui.SD_QUALITY=Calidad estándar service.gui.OFFLINE=Desconectado service.gui.OK=&OK -service.gui.OLDER_CALLS=Llamadas antiguas service.gui.ONLINE=Conectado service.gui.OPEN=Abrir service.gui.OPEN_FILE_FROM_IMAGE=Doble clic para abrir el archivo. @@ -431,7 +400,6 @@ service.gui.OPEN_ON_ACTIVITY=Abrir al estar activo service.gui.OPEN_ON_MESSAGE=Abrir al recibir mensaje service.gui.OPEN_ON_IMPORTANT_MESSAGE=Solamente Abrir en mensajes importantes service.gui.OR=o -service.gui.OR_ENTER_PHONE_NUMBER=O introduzca el teléfono aquí... service.gui.ORGANIZATION=Organización service.gui.OTHER=Otro service.gui.chat.role.OWNER=Propietario @@ -457,7 +425,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Intro' para sugerencias service.gui.PRESS_FOR_CALL_INFO=Presione para información de la llamada service.gui.PRESS_TO_OPEN_CRM=Presione para abrir la aplicación CRM service.gui.PREVIOUS=Anterior -service.gui.PREVIOUS_TOOLTIP=Explorar conversaciones antiguas service.gui.PRINT=Im&primir service.gui.PROACTIVE_NOTIFICATION=está escribiendo service.gui.PROBLEMS_ENCOUNTERED=Se encontraron problemas @@ -473,7 +440,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Ha desconectado y reconectado al servido service.gui.RE_REQUEST_AUTHORIZATION=Volver a solicitar autorización service.gui.REFERRED_STATUS=Referido service.gui.REJECT=&Rechazar -service.gui.REMIND_ME_LATER=Recordarme más tarde service.gui.REMEMBER_PASSWORD=Recordar contraseña service.gui.REMOVE=&Eliminar service.gui.REMOVE_ACCOUNT=&Eliminar cuenta @@ -499,31 +465,22 @@ service.gui.REVOKE_ADMIN=Cancelar admin service.gui.REVOKE_MODERATOR=Cancelar moderador service.gui.REVOKE_MEMBERSHIP=Cancelar membresía service.gui.REVOKE_VOICE=Cancelar voz -service.gui.ROOT_GROUP=Grupo raíz service.gui.SAVE=&Guardar -service.gui.SAVE_AS_DEFAULT=Guardar como predeterminado service.gui.SEARCH=&Buscar service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Presione el botón para mostrar todas las salas de conversación existentes en el servidor seleccionado. Después seleccione aquella a la que desea conectarse y presione el botón Entrar. service.gui.SEARCH_STRING_CONTACT_SOURCE=Contacto buscado service.gui.SECURITY=Seguridad -service.gui.SELECT_ACCOUNT=Seleccionar cuenta de usuario service.gui.SELECT_ACCOUNT_INFO=¿Cual cuenta desea utilizar para comunicarse con este contacto? service.gui.SELECT_COLOR=Seleccionar color service.gui.SELECT_GROUP=Seleccione un grupo service.gui.SELECT_GROUP_INFO=¿Que grupo desea usar para mostrar este contacto? (Opcional) -service.gui.SELECT_GROUP_WIZARD_MSG=La lista inferior contiene todos los grupos de su lista de contactos. Seleccione a la que desea agregar el nuevo contacto. service.gui.SELECT_NO_GROUP=Sin grupo -service.gui.SELECT_GROUP_WIZARD=Seleccione grupo service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=La lista inferior contiene todas las cuentas de usuario que tienen soporte para chat multi usuario. Seleccione aquella que desee usar para crear la sala de chat. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=La lista inferior contiene todas las cuentas de usuario registradas. Seleccione aquellas que desee usar para comunicarse con el nuevo contacto. -service.gui.SELECT_PROVIDERS_WIZARD=Seleccione cuenta service.gui.SELECT_VIDEO_CONFERENCE=Seleccionar videoconferencia service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Elija una sala de chat de la lista y presione Aceptar para agregarla service.gui.SEND=&Enviar service.gui.SEND_FILE=Enviar archivo -service.gui.SELECT_CONTACT_SUPPORTING_INFO=No hay información para este contacto. service.gui.SEND_MESSAGE=&Enviar mensaje -service.gui.SEND_AS_SMS=Enviar como SMS service.gui.SEND_PRIVATE_MESSAGE=Enviar mensaje privado service.gui.SEND_SMS=Enviar S&MS service.gui.SEND_SMS_DETAILS=Recuerde que debe introducir el teléfono en formato internacional, por ejemplo: empezando por +44 para Reino Unido, +447777000000 @@ -562,7 +519,6 @@ service.gui.STREET=Calle service.gui.SUBJECT=Asunto service.gui.SUMMARY=Resumen service.gui.TELEPHONY=Telefonía -service.gui.TODAY=Hoy service.gui.TOOLS=&Herramientas service.gui.TRANSFER=Trans&ferir service.gui.TO=&Para: @@ -572,7 +528,6 @@ service.gui.TRANSFER_CALL_TO=Transferir a: service.gui.TRANSPARENCY_NOT_ENABLED=La transparencia no está soportada por su configuración actual. service.gui.TYPE_YOUR_REQUEST=Escriba su petición aquí service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=No es posible cambiar la calidad de vídeo de esta llamada. -service.gui.UNMUTE=Apagar silencio service.gui.USER_IDENTIFIER=Identificación de usuario: service.gui.USER_EXISTS_ERROR=Este usuario ya existe en el servidor. Escoja otro o use otro servidor. service.gui.USERNAME_NULL=Por favor introduzca su nombre y contraseña. @@ -585,7 +540,6 @@ service.gui.USE_PROVISIONING=Usar aprovisionamiento en línea service.gui.VALUE=Valor service.gui.VIDEO_CALL=&Videollamada service.gui.VIA=vía -service.gui.VIA_SMS=Vía SMS service.gui.VIEW=&Ver service.gui.VIEW_HISTORY=Ver &historial service.gui.VIEW_SMILEYS=Ver emoticono&s @@ -605,9 +559,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Ajustar volumen service.gui.WAITING_AUTHORIZATION=Esperando autorización service.gui.WARNING=Advertencia service.gui.YES=Sí -service.gui.YESTERDAY=Ayer -service.gui.EXISTING_ACCOUNT_ERROR=La cuenta introducida ya se encontraba instalada. -service.gui.NEW_MAIL=¡Ha recibido un correo!
    De: {0} {1}
    Asunto: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Ha recibido un nuevo mensaje de correo en su bandeja de entrada {0}:
    service.gui.NEW_GMAIL_MANY_HEADER=Ha recibido {2} mensajes en su bandeja de entrada{0} :
    service.gui.NEW_GMAIL_FOOTER=una o más conversaciones sin leer en su bandeja de entrada.
    @@ -634,7 +585,6 @@ service.gui.SECURITY_ERROR=Error de seguridad service.gui.SPEED=Velocidad: service.gui.SILENT_MEMBER=silenciar miembro service.gui.NON_SECURE_CONNECTION=No se puede establecer una conexión segura para la cuenta {0}. Si desea conectarse a un servidor no seguro, seleccione "Permitir conexiones no seguras" en la configuración de su cuenta -service.gui.UPDATE=Actualizar service.gui.MOBILE_PHONE=Móvil service.gui.VIDEO_PHONE=Vídeo service.gui.WORK_PHONE=Trabajo @@ -669,12 +619,10 @@ service.gui.callinfo.CALL_INFORMATION=Información de la Llamada service.gui.callinfo.CALL_IDENTITY=Identidad service.gui.callinfo.PEER_COUNT=Conteo de Participantes service.gui.callinfo.IS_CONFERENCE_FOCUS=Enfocar conferencia -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Cifrado activado service.gui.callinfo.CALL_TRANSPORT=Señalización de transporte de llamadas service.gui.callinfo.CALL_DURATION=Duración de la llamada service.gui.callinfo.TLS_PROTOCOL=Protocolo TLS service.gui.callinfo.TLS_CIPHER_SUITE=Suite de cifrado TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Cadena del certificado del servidor TLS service.gui.callinfo.TLS_CERTIFICATE_CONTENT=El contenido del certificado del servidor TLS se muestra a continuación. service.gui.callinfo.VIEW_CERTIFICATE=Ver Certificado service.gui.callinfo.CODEC=Códec / Frecuencia @@ -694,10 +642,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocolo de intercambio de claves service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE Candidato de tipo extendido service.gui.callinfo.ICE_STATE=Estado de Procesamiento ICE: + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Reuniendo candidatos service.gui.callinfo.ICE_STATE.RUNNING=Revise conectividad service.gui.callinfo.ICE_STATE.COMPLETED=Terminado service.gui.callinfo.ICE_STATE.FAILED=Falló + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP local / Puerto service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=IP Local reflexiva / Puerto service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=IP Local retransmitida / Puerto @@ -718,11 +669,12 @@ service.gui.ALWAYS_TRUST=Siempre confiar en este certificado service.gui.CERT_DIALOG_TITLE=Verificar Certificado service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} no puede verificar la identidad del servidor al conectarse a
    {1}.

    El certificado no es confiable, esto significa que la identidad del servidor no puede ser verificada automáticamente.

    ¿Desea continuar con la conexión?
    Para mayor información, presione "Ver Certificado". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} no puede verificar el certificado del servidor.

    El certificado no es confiable, esto significa que la identidad del servidor no puede
    ser verificada automáticamente.

    ¿Desea continuar con la conexión?

    Para mayor información, de un clic en "Ver Certificado". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} no puede verificar la identidad del cliente.

    El certificado no es confiable, esto significa que la identidad del cliente no puede
    ser verificada automáticamente. ¿Desea continuar?

    Para mayor información presione "Ver Certificado". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} no puede verificar la identidad del cliente {1}.

    El certificado no es confiable, esto significa que la identidad del cliente no puede
    ser verificada automáticamente. ¿Desea continuar con la conexión?

    Para mayor información presione "Ver Certificado". service.gui.CONTINUE_ANYWAY=Continuar de todas formas service.gui.CERT_INFO_CHAIN=Cadena del certificado: service.gui.CERT_INFO_ISSUED_TO=Emitido a + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nombre Común: service.gui.CERT_INFO_O=Organización: service.gui.CERT_INFO_C=País: @@ -741,12 +693,10 @@ service.gui.CERT_INFO_SIGN_ALG=Algoritmo de la Firma: service.gui.CERT_INFO_PUB_KEY_INFO=Información de la clave pública service.gui.CERT_INFO_ALG=Algoritmo: service.gui.CERT_INFO_PUB_KEY=Clave Pública: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Exponente: service.gui.CERT_INFO_KEY_SIZE=Tamaño de la Clave: service.gui.CERT_INFO_SIGN=Firma: -service.gui.CONTINUE=Continuar service.gui.SHOW_CERT=Ver Certificado service.gui.HIDE_CERT=Ocultar Certificado @@ -769,12 +719,9 @@ service.gui.security.SECURE_AUDIO=Audio seguro service.gui.security.AUDIO_NOT_SECURED=Audio no seguro service.gui.security.SECURE_VIDEO=Vídeo seguro service.gui.security.VIDEO_NOT_SECURED=Vídeo no seguro -service.gui.security.NO_VIDEO=Sin video -service.gui.security.CIPHER=Cifrado: {0} service.gui.security.CALL_SECURED_TOOLTIP=Llamada asegurada. Para mayor información presione aquí. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Llamada no segura. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Presione aquí para comparar la seguridad con su contraparte. -service.gui.security.COMPARE_WITH_PARTNER=Compare con su contacto y presione en el candado para confirmar. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparar con su contra-parte. service.gui.security.STRING_COMPARED=¡Cadena comparada! @@ -792,20 +739,14 @@ service.gui.avatar.imagepicker.CLICK=Presione y Sonría service.gui.avatar.imagepicker.IMAGE_FILES=Archivos de imágenes service.gui.avatar.imagepicker.IMAGE_PICKER=Imagen service.gui.avatar.imagepicker.IMAGE_SIZE=Tamaño de imagen -service.gui.avatar.imagepicker.INITIALIZING=Inicializando service.gui.avatar.imagepicker.RESET=Reiniciar service.gui.avatar.imagepicker.SET=Definir service.gui.avatar.imagepicker.TAKE_PHOTO=Tomar una foto -service.gui.avatar.imagepicker.WEBCAM_ERROR=Error en cámara web service.gui.security.encryption.required=¡Cifrado requerido! service.protocol.ICE_FAILED=No se pudo establecer una conexión (falló ICE y no se encontró relé) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Error en almacenamiento de lista de contactos SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=No se pueden leer los recusros {0}. De {1} @@ -835,9 +776,7 @@ impl.ldap.QUERY_CUSTOM=Consulta personalizada impl.ldap.QUERY_CUSTOM_HINT=Usar {0} como un marcador para el término de búsqueda. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Añadir automáticamente comodines en la consulta impl.ldap.QUERY_PHOTO_INLINE=Obtener foto junto con otros atributos -impl.ldap.NEW=Nuevo impl.ldap.EDIT=editar -impl.ldap.REMOVE=Eliminar impl.ldap.ENABLED=Activado impl.ldap.SERVER_NAME=Nombre del Servidor impl.ldap.SERVER_NAME_EXAMPLE=Mi servidor LDAP @@ -890,9 +829,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Hacer a Outlook su cliente de c # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Contactos de Google -impl.googlecontacts.NEW=Nuevo impl.googlecontacts.EDIT=editar -impl.googlecontacts.REMOVE=Eliminar impl.googlecontacts.ENABLED=Activado impl.googlecontacts.ACCOUNT_NAME=Nombre de cuenta impl.googlecontacts.SAVE=Guardar @@ -935,11 +872,8 @@ plugin.accountinfo.ORGANIZATION=Nombre de la organización: plugin.accountinfo.JOB_TITLE=Puesto: plugin.accountinfo.ABOUT_ME=Información sobre mí: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Fotos plugin.accountinfo.GLOBAL_ICON=Usar icono global plugin.accountinfo.LOCAL_ICON=Usar este ícono: -plugin.accountinfo.CHANGE=Cambiar -plugin.accountinfo.ONLY_MESSAGE=Sólo mensajes # connection info plugin.connectioninfo.TITLE=Información de la conexión @@ -959,45 +893,14 @@ plugin.aimaccregwizz.USERNAME=Usuario AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Usuario y Contraseña plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registrar nueva cuenta plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=En el caso de no disponer de una cuenta AIM, presione este botón para crear una nueva. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Modificar las opciones predeterminadas del servidor # branding plugin.branding.ABOUT_WINDOW_TITLE=Acerca de {0} plugin.branding.LOGO_MESSAGE=VoIP && Mensajería Instantánea. -plugin.branding.LOADING=Cargando plugin.branding.ABOUT_MENU_ENTRY=&Acerca de -plugin.branding.WELCOME_MESSAGE=
    {1} se está desarrollando actualmente. La versión que está ejecutando es únicamente experimental y PUEDE QUE NO se comporte como espera. Por favor, consulte a {2} para más información.
    -plugin.branding.COPYRIGHT=
    (c) 2003-2013 Copyright jitsi.org. Todos los derechos reservados. Visite https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi es distribuido bajo los terminos la licencia Apache (http://www.apache.org/licenses/LICENSE-2.0).
    plugin.busylampfield.PICKUP=Tomar llamada -# Dict protocol -service.protocol.DICTIONARIES=Diccionarios -plugin.dictaccregwizz.ANY_DICTIONARY=Cualquier Diccionario -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Cualquier Diccionario de {0} -plugin.dictaccregwizz.FIRST_MATCH=Primera Coincidencia -plugin.dictaccregwizz.NO_MATCH=Sin coincidencias -plugin.dictaccregwizz.MATCH_RESULT=No hay definiciones para "{0}", puede ser:\n -plugin.dictaccregwizz.INVALID_DATABASE=El diccionario "{0}" ya no existe en el servidor. -plugin.dictaccregwizz.INVALID_STRATEGY=La estrategia no está disponible en el servidor. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=El protocolo de servicio Dict -plugin.dictaccregwizz.HOST=Anfitrión -plugin.dictaccregwizz.SERVER_INFO=Información del Servidor -plugin.dictaccregwizz.STRATEGY_SELECTION=Selección de Estrategia -plugin.dictaccregwizz.STRATEGY_LIST=Lista de estrategias: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Buscar estrategias -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=La estrategia se usa para buscar palabras similares si una traducción no se encuentra, gracias a distintos enfoques. Por ejemplo las estrategias de prefijo buscan palabras que empiezan como la palabra que desea traducir. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Infomación de la cuenta Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Este asistente creará su primera cuenta Dict por usted en dict.org.\n\nPuede agregar nuevos diccionarios usando el asistente de registro de cuentas. Complete el campo de anfitrión con el diccionario que desee agregar. -plugin.dictaccregwizz.THREAD_CONNECT=Intentado conectarse al servidor -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Fallo el intento de conexión, No es un servidor dict o está apagado -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Recuperando estrategias -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=No hay estrategía en el servidor -plugin.dictaccregwizz.POPULATE_LIST=Generando lista -plugin.dictaccregwizz.CLOSING_CONNECTION=Cerrando conexión - # generalconfig plugin.generalconfig.AUTO_START=Auto - Iniciar {0} cuando arranque o reinicie el sistema plugin.generalconfig.CHATALERTS_ON_MESSAGE=Utilizar alertas en la barra de tareas / dock para llamadas entrantes y charlas @@ -1007,9 +910,6 @@ plugin.generalconfig.SHOW_HISTORY=Mostrar plugin.generalconfig.HISTORY_SIZE=últimos mensajes en conversaciones plugin.generalconfig.SEND_MESSAGES_WITH=Enviar mensajes usando: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Traer la ventana del chat al frente -plugin.generalconfig.ERROR_PERMISSION=No dispone de los privilegios necesarios para desactivar el inicio automático -plugin.generalconfig.TRANSPARENCY=Transparencia -plugin.generalconfig.ENABLE_TRANSPARENCY=Activar transparencia plugin.generalconfig.DEFAULT_LANGUAGE=Idioma de la Interfaz plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Los cambios se llevarán a cabo al reiniciar. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% traducido @@ -1040,7 +940,6 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Suponer siempre la pérdida plugin.generalconfig.SILK_SAT=Umbral de actividad de voz (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Anunciar soporte a FEC en SDP: plugin.generalconfig.RESTORE=Restaurar opciones predeterminadas -plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimizar la ventana principal en lugar de esconderla # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish @@ -1083,7 +982,6 @@ plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=El protocolo XMPP plugin.jabberaccregwizz.USERNAME=Nombre de usuario XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmar contraseña -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID y Contraseña plugin.jabberaccregwizz.CSERVER=Servidor plugin.jabberaccregwizz.SERVER=Conectar al servidor plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Activar mantener vivo @@ -1099,13 +997,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Comentarios plugin.jabberaccregwizz.RESOURCE=Recurso plugin.jabberaccregwizz.AUTORESOURCE=Auto generar recurso plugin.jabberaccregwizz.PRIORITY=Prioridad -plugin.jabberaccregwizz.XMPP_ERROR=Error XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Error desconocido de XMPP ({0}). Verifique que el nombre del servidor es correcto. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Sus contraseñas no coinciden. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Modificar las opciones predeterminadas del servidor -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Opciones avanzadas plugin.jabberaccregwizz.USE_ICE=Usar ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Utilizar Jingle/ICE de Google (experimental) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Auto descubrir servidores STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=Soporte TURN plugin.jabberaccregwizz.TURN_USERNAME=Nombre de usuario TURN @@ -1133,11 +1027,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Desactivar copias de los mensajes plugin.jabberaccregwizz.DTMF_AUTO=Auto: Selecciona automáticamente entre RTP y en banda plugin.jabberaccregwizz.SERVER_OPTIONS=Opciones de servidor plugin.jabberaccregwizz.CHANGE_PASSWORD=Cambiar contraseña de la cuenta -plugin.jabberaccregwizz.NEW_PASSWORD=Nueva contraseña -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirmar nueva contraseña plugin.jabberaccregwizz.PORT_FIELD_INVALID=Por favor introduzca un número de puerto válido para continuar. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Tiene que iniciar sesión en la cuenta para poder cambiar la contraseña. -plugin.jabberaccregwizz.PASSWORD_EMPTY=La contraseña esta vacía. plugin.jabberaccregwizz.TLS_REQUIRED=La conexión no usa TLS, no se realizará el cambio de contraseña. plugin.jabberaccregwizz.PASSWORD_CHANGED=La contraseña se cambio con éxito plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Su servidor de XMPP no soporta el cambio de contraseña. @@ -1151,19 +1042,9 @@ plugin.jabberaccregwizz.RESET=Reiniciar plugin.jabberaccregwizz.RESET_DESCRIPTION=Reiniciar a la configuración global plugin.jabberaccregwizz.DISABLE_JINGLE=Desactivar Jingle (llamadas de audio y vídeo con XMPP). -# mailbox -plugin.mailbox.OUTGOING=Mensaje saliente: -plugin.mailbox.INCOMING=Mensaje entrante: -plugin.mailbox.WAIT_TIME=Espera hasta que la llamada es enviada al buzón de voz -plugin.mailbox.MAX_MESSAGE_TIME=Duración máxima del mensaje entrante -plugin.mailbox.CONFIRM=Confirmar -plugin.mailbox.DEFAULTS=Predeterminados -plugin.mailbox.MAILBOX=Buzón - # plugin manager plugin.pluginmanager.INSTALL=Instalar plugin.pluginmanager.UNINSTALL=Desinstalar -plugin.pluginmanager.UPDATE=Actualizar plugin.pluginmanager.PLUGINS=Módulos plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Seleccionar archivo @@ -1188,7 +1069,6 @@ plugin.sipaccregwizz.SERVER_PORT=Puerto del servidor plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Puerto del proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Transporte preferido -plugin.sipaccregwizz.ADVANCED_OPTIONS=Opciones avanzadas plugin.sipaccregwizz.PROXY_OPTIONS=Opciones del proxy plugin.sipaccregwizz.PROXY_AUTO=Configurar proxy de forma automática plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Ignorar control de seguridad del proxy, seleccione en escenarios de alta disponibilidad (use sólo si es necesario) @@ -1209,8 +1089,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Selecciona automáticamente entre RTP y en plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=En banda -plugin.sipaccregwizz.REGISTER=REGISTRO -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Modificar las opciones predeterminadas del servidor plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Activar soporte para llamadas cifradas plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indique el soporte de ZRTP en el protocolo de señalización plugin.sipaccregwizz.AUTH_NAME=Nombre autorizado @@ -1231,10 +1109,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Revisar URI de Correo de Voz plugin.sipaccregwizz.NOT_SAME_PASSWORD=Sus contraseñas no coinciden. plugin.sipaccregwizz.NO_CERTIFICATE= (use autenticación regular) plugin.sipaccregwizz.SAVP_OPTION=indicador RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Apagado (indica RTP/AVP solamente) plugin.sipaccregwizz.SAVP_OPTION_1=Obligatorio (ofrece y acepta RTP/SAVP solamente) plugin.sipaccregwizz.SAVP_OPTION_2=Opcional (ofrece primero RTP/SAVP, y después RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Habilitar S-Descriptor (también conocido como SDES o SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Elegir protocolos con cifrado habilitado y su prioridad (superior como primer protocolo): plugin.sipaccregwizz.CIPHER_SUITES=Habilita suites de cifrado: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} automáticamente tratará de garantizar todas sus llamadas con ZRTP y podrá oír y ver una notificación una vez que una conexión segura se establece. Sólo debe cambiar la configuración avanzada si sabe muy bien lo que está haciendo.
    @@ -1248,15 +1126,6 @@ plugin.skinmanager.DEFAULT_SKIN=Tema predeterminado plugin.skinmanager.ADD_NEW_SKIN=Agregar un nuevo tema... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=El tema predeterminado de la aplicación. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Protocolo para conectarse remotamente a distintas máquinas usando SSH. -plugin.sshaccregwizz.USERNAME=ID de cuenta: -plugin.sshaccregwizz.IDENTITY_FILE=Archivo de identidad: -plugin.sshaccregwizz.KNOWN_HOSTS=Anfitriones conocidos: -plugin.sshaccregwizz.OPTIONAL=Opcional -plugin.sshaccregwizz.ACCOUNT_DETAILS=Detalles de la cuenta - # status update plugin.autoaway.AUTO_STATUS=Auto Ausente plugin.autoaway.ENABLE_CHANGE_STATUS=Cambiar el estado si no estoy presente @@ -1304,22 +1173,6 @@ plugin.whiteboard.DESELECT=Deseleccionar plugin.whiteboard.DELETE=Eliminar plugin.whiteboard.PROPERTIES=Propiedades -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protocolo para conectarse y conversar en el Servicio de Yahoo!. -plugin.yahooaccregwizz.USERNAME=Usuario: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Usuario y Contraseña - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=El protocolo de servicio Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Nombre: -plugin.zeroaccregwizz.LAST_NAME=Apellidos: -plugin.zeroaccregwizz.EMAIL=Correo: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=¿Recordar contactos de Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID y Contraseña -plugin.zeroaccregwizz.USERID=User ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Protocolo Google Talk @@ -1333,19 +1186,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, el Portal de Telecomunica plugin.iptelaccregwizz.USERNAME=Usuario plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Inscribirse a iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP y charlas +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Usuario plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Escriba nuevamente la contraseña plugin.sip2sipaccregwizz.EMAIL=Dirección de correo -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Si necesita ayuda sobre este servicio visite
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=La dirección de correo es usada para enviar mensajes del correo de voz,
    notificaciones de llamadas perdidas y para recuperar una contraseña -plugin.sip2sipaccregwizz.INFO_NOTE=Si necesita ayuda sobre este servicio visite http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Cuenta actual de sip2sip.info -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Crear una cuenta gratuita de sip2sip.info - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP y Mensajero Instantáneo plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Si necesita ayuda sobre este servicio visite
    http://ippi.fr @@ -1354,6 +1199,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Cuenta ippi existente plugin.ippiaccregwizz.CREATE_ACCOUNT=Crear una cuenta ippi gratuita # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Cerrar ventana de charla plugin.keybindings.CHAT_COPY=Copiar plugin.keybindings.CHAT_CUT=Cortar @@ -1376,10 +1222,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Nombre plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=acceso directo principal plugin.keybindings.globalchooser.SHORTCUT_SECOND=acceso directo secundario plugin.keybindings.globalchooser.PRESS_BTN=Pulse para establecer atajo -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Esperando plugin.keybindings.globalchooser.PUSH_TO_TALK=Presione para hablar plugin.keybindings.globalchooser.ENABLE_SPECIAL=Activar la detección de teclas especiales plugin.keybindings.PLUGIN_NAME=Asignación de teclas +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Charla plugin.keybindings.MAIN=Principal plugin.keybindings.GLOBAL=Accesos rápidos globales @@ -1407,6 +1253,7 @@ plugin.notificationconfig.tableheader.SOUND=Reproducir un sonido a través del d plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Reproducir un sonido a través del dispositivo de reproducción plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Reproducir un sonido a través del dispositivo de altavoz del PC plugin.notificationconfig.tableheader.DESCRIPTION=Descripción del evento +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Llamada Entrante plugin.notificationconfig.event.SecurityMessage=Mensaje de Seguridad plugin.notificationconfig.event.IncomingFile=Recibiendo Archivo @@ -1508,6 +1355,7 @@ impl.neomedia.configform.VIDEO=Vídeo impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Actualización Periodica de Intra impl.neomedia.configform.H264.defaultProfile=Perfil para codificar en: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Base impl.neomedia.configform.H264.defaultProfile.high=Alto impl.neomedia.configform.H264.defaultProfile.main=Principal @@ -1538,7 +1386,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Contraseña actual: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Escriba su nueva contraseña: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Reescribir la contraseña: plugin.securityconfig.masterpassword.MP_TITLE=Contraseña Maestra -plugin.securityconfig.masterpassword.MP_NOT_SET=(no configurado) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=No introdujo la Contraseña Maestra correcta. Por favor inténtelo nuevamente. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=¡La Contraseña Maestra no es correcta! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Falló el Cambio de Contraseña @@ -1554,7 +1401,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Contraseña plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(desconocido) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(no puede descifrarse) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Contraseñas almacenadas -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Eliminar plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Eliminar todo plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=¿Está seguro que desea eliminar todas las contraseñas? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Eliminar todas las contraseñas @@ -1650,7 +1496,6 @@ plugin.globalproxy.PROXY_PORT=Puerto del proxy plugin.globalproxy.PROXY_USERNAME=Usuario del Proxy plugin.globalproxy.PROXY_PASSWORD=Contraseña del Proxy plugin.globalproxy.DESCRIPTION={0} usará la configuración del proxy para todas las redes a las que está conectado o se conecte de ahora en adelante. \nEl soporte de proxy es experimental y solo funciona con algunos protocolos. Revise la siguiente tabla para más detalles: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Proxy también de DNS plugin.globalproxy.FWD_DNS_NOTE=Es útil con Tor. Ayuda a evitar las fuga de DNS mediante el envío de todo el tráfico de DNS al proxy de Tor. Requiere reiniciar. @@ -1688,7 +1533,6 @@ plugin.provisioning.RESTART_WARNING=¡Tenga en cuenta que los cambios sólo surt plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Copiar UUID al portapapeles plugin.provisioning.CLIPBOARD_FAILED=Falló el copiado de UUID al portapapeles -plugin.provisioning.EXIT_ON_FAIL=Salir de la aplicación si el aprovisionamiento falla plugin.provisioning.CREDENTIALS=Últimas credenciales de aprovisionamiento almacenadas plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=¿Está seguro que desea eliminar la contraseña de aprovisionamiento? plugin.provisioning.PROV_FAILED=Falló el aprovisonamiento @@ -1755,8 +1599,6 @@ util.dns.DNSSEC_WARNING=
    {0} ha tratado de conectarse al s #plugin spellcheck plugin.spellcheck.TITLE=Ortografía y Gramática plugin.spellcheck.MENU=Mostrar Ortografía y Gramática -plugin.spellcheck.LANG=Idioma -plugin.spellcheck.EDIT_PERSONAL_DICT=Editar plugin.spellcheck.ENABLE_SPELL_CHECK=Activar revisión ortográfica plugin.spellcheck.dialog.FIND=Buscar siguiente plugin.spellcheck.dialog.REPLACE=Reemplazar -- cgit v1.1 From 054175baf4e4fd4171e3c80b2d2ded8229d5b48f Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:45 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1120 of 1505 strings translated (88 fuzzy). --- resources/languages/resources_ar.properties | 224 ++++++---------------------- 1 file changed, 45 insertions(+), 179 deletions(-) diff --git a/resources/languages/resources_ar.properties b/resources/languages/resources_ar.properties index 9583582..deee731 100644 --- a/resources/languages/resources_ar.properties +++ b/resources/languages/resources_ar.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,29 +43,24 @@ service.gui.ACCOUNT_ME=أنا (خاص بي) service.gui.ACCOUNT_REGISTRATION_WIZARD=المساعدة في تسجيل الحساب service.gui.ACCOUNTS=حسابات service.gui.ADD=&إضافة -service.gui.ADD_ACCOUNT=إضافة حساب service.gui.ADD_CONTACT=إضافة عضو (مستخدم) -service.gui.ADD_AUTHORIZED_CONTACT=إضف {0} إلى قائمة المستخدمين لديك +service.gui.ADD_AUTHORIZED_CONTACT=أضِف {0} إلى قائمة جهات الاتصال +service.gui.ADD_CONTACT_TO_CONTACTLIST=أضف الإسم هذه إلى قائمة جهات اتصالك service.gui.ADD_CONTACT_TO=إضافة عضو إلى service.gui.ADD_CONTACT_ERROR=خطأ عند إضافة المستخدم التالي : {0} service.gui.ADD_CONTACT_ERROR_TITLE=حدث خطأ لدى إضافة مستخدم service.gui.ADD_CONTACT_EXIST_ERROR=اسم المستخدم {0} موجود بالفعل في قائمة المستخدمين لديك. service.gui.ADD_CONTACT_NETWORK_ERROR=الخادم لم يستجب لطلب إضافة الصديق ذات الرقم {0} service.gui.ADD_CONTACT_NOT_SUPPORTED=فشل في إضافة المستخدم:{0}. عملية غير مدعومة. -service.gui.ADD_CONTACT_IDENTIFIER=أكتب في الخانة التي في الأسفل اسم العضو (المستخدم) الذي تريد إضافته. -service.gui.ADD_CONTACT_WIZARD=المساعد في إضافة مشترك (عضو أو مستخدم). service.gui.ADD_CONTACT_NOT_CONNECTED=يجب أن تكون متصل لكي تضيف اسم مستخدم الى قائمة الأصدقاء, رجاءا سجل دخولك و جرب مرة اخرى. service.gui.ADD_GROUP_LOCAL_ERROR=لم تتم إضافة المجموعة :{0}. السبب : مشكلة حدثت اثناء عملية إدخال-إخراج محلية. service.gui.ADD_GROUP_EXIST_ERROR=المجموعة {0} موجودة بالفعل في قائمة المستخدمين لديك. من فضلك اختر إسما آخر. service.gui.ADD_GROUP_NET_ERROR=لم تتم إضافة المجموعة بإسم {0}. السبب : حدوث مشكلة في الشبكة. من فضلك تأكد من اتصال الشبكة لديك ثم حاول مرة اخرى. service.gui.ADD_GROUP_ERROR=لم تتم إضافة المجموعة بإسم : {0}. service.gui.ADD_GROUP_EMPTY_NAME=إسم المجموعة يحب أن لا يكون فارغا. -service.gui.ADD_GROUP=إنشاء مجموعة -service.gui.ADD_SUBCONTACT=&إضافة مستخدم فرعي. service.gui.ADDRESS=عنوان service.gui.ADMINISTRATOR=المسؤول service.gui.ADVANCED=&متقدم -service.gui.ALL=&الكل service.gui.ALL_CONTACTS=&جميع المستخدمين. service.gui.APPLY=&تطبيق service.gui.ARE_CALLING={0} يتصل بك... @@ -63,7 +69,6 @@ service.gui.AT=عند service.gui.AUTHORIZE=&ترخيص service.gui.AUTHORIZATION_ACCEPTED={0} وافق على طلب تفويضك. service.gui.AUTHENTICATION_FAILED=فشل التحقق ل{0} . كلمة السر التي ادخلتها غير صالحة. -service.gui.AUTHENTICATION_REQUESTED=طلب التحقق service.gui.AUTHENTICATION_REQUESTED_SERVER=الخادم {0} يطلب منك معلومات الدخول (التحقق). service.gui.AUTHENTICATION_REJECTED={0} رفض طلب تفويضك . service.gui.AUTHENTICATION_WINDOW_TITLE=التحقق أو التأكد من الهوية لـ {0}. @@ -102,7 +107,6 @@ service.gui.CHANGE_NICKNAME_LABEL=فى الحقل فى الأسفل، يمكنك service.gui.CHANGE_NICKNAME_ERROR=خطأ في تغير الإسم المستعار service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=الاسم موجود مسبقاً service.gui.CHANGE_VIDEO_QUALITY=تغيير جودة الفيديو -service.gui.CHAT_CONFERENCE_LABEL=مأتمرات service.gui.CHAT_ROOM_ALREADY_JOINED=تم دخول الغرفة {0} مسبقا. service.gui.CHAT_ROOM_CONFIGURATION=إعدادات غرفة الدردشة {0} service.gui.CHAT_ROOM_CONFIGURATION_FAILED=فشل فى الحصول على إعدادات غرفة الدردشة {0}. فقط مالك صالون الدردشة قادر على تغير الإعدادات . @@ -114,13 +118,11 @@ service.gui.CHAT_ROOM_USER_QUIT=خرج من {0} service.gui.CHAT_ROOM_NAME=إسم غرفه الدردشة service.gui.CLEAR_CUSTOM_MESSAGES=احذف الرسائل المخصصة service.gui.ROOM_NAME=غرفة الدردشة -service.gui.AUTOJOIN=دخول تلقائي service.gui.CHANGE_PASSWORD=تغيير كلمة المرور service.gui.CHAT_ROOM_NAME_INFO=فى الحقل الأسفل إدخل أسم الغرفة التى تريد إنشاءها. service.gui.CHAT_ROOM_NOT_EXIST=الغرفة {0} غير موجودة لدى الخادم {1}. الرجاء التحقق من الإسم المدخل. service.gui.CHAT_ROOM_NOT_CONNECTED=يجب أن تكون مسجلا لكي تدخل غرفة الدردشة{0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=يجب أن تكون مسجلا لكي تخرج من غرفة الدردشة. -service.gui.CHAT_ROOM_NOT_JOINED=يجب ان تكون داخل غرفة الدردشة لكى تقوم ببعض الإجراءات. service.gui.CHAT_ROOM_OPTIONS=خيارات غرفة الدردشة service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=غرفة الدردشة {0} تتطلب تسجيلا قبل دخولها. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=غرفة الدردشة {0} تتطلب كلمة سر. @@ -136,21 +138,17 @@ service.gui.CLEAR=مسح service.gui.CLOSE=غلق& service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=لقد وصلتك رسالة جديدة منذ أقل من ثانيتين. هل تود أن تغلق هذا الحوار أو النقاش؟ service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=لديك ملفات تنقل حاليا و غير مكتملة. هل أنت متأكد من رغبتك في إلغائها؟ -service.gui.CONFIRM=أكِّد service.gui.CONNECTED_STATUS=متصل service.gui.CONNECTING=الاتصال جار... service.gui.CONNECTING_STATUS=جاري الإتصال service.gui.CONNECTING_EARLY_MEDIA_STATUS=جاري الإتصال* service.gui.CONNECTION=الإتصال -service.gui.CONNECTION_FAILED_MSG=لم يتم الاتصال من الحساب : إسم المستخدم: {0} إسم الخادم : {1}. يرجى التأكد من الاتصال بالشبكة أو الاتصال بمسؤول الشبكة لديك لمزيد من المعلومات. service.gui.CONNECTION_EXPIRED_MSG=أنت غير متصل عبر الخادم {0}. service.gui.CONTACT_NAME=معرًف أو رقم -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=المستخدم {0} الذي تم إختياره لا يمكنه الاتصال بالهاتف. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=المستخدم {0} الذي تم إختياره لا يمكنه استخدام الدردشة عديدة المستخدمين. service.gui.CONTACT_PAUSED_TYPING=لقد توقف {0} لحظة عن كتابة الرسالة. service.gui.CONTACT_TYPING=المستخدم {0} يكتب رسالة الآن. service.gui.CONTACT_INFO=&معلومات جهة الإتصال -service.gui.CONTACTLIST=قائمة جهات الإتصال service.gui.CONTACTS=المستخدمين (الأعضاء) service.gui.COPY=&نسخ service.gui.COPY_LINK=نسخ &ربط @@ -160,15 +158,12 @@ service.gui.CREATE_CHAT_ROOM=&إنشاء غرفة دردشة ... service.gui.CREATE_CHAT_ROOM_ERROR=فشل إنشاء غرفة الدردشة {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=مساعدة لإنشاء غرفة دردشة service.gui.CREATE_CONFERENCE_CALL=&إنشاء اتصال حوار متعدد (مكالمة)... -service.gui.CREATE_CONFERENCE_CHAT=&إنشاء حوار متعدد (اتصال دردشة)... service.gui.CREATE_GROUP=&إنشاء مجموعة... service.gui.CREATE_GROUP_NAME=فى الحقل فى الأسفل أدخل أسم المجموعة التى تريد إنشاءها. -service.gui.CREATE_FIRST_GROUP_WIZARD=قائمة المستخدمين لديك ليس فيها أي مجموعة. لطفا، بادر بإنشاء مجموعة (ملف /إنشاء مجموعة). service.gui.CREATE_VIDEO_BRIDGE=إنشاء &جسر فيديو... service.gui.CREATE_VIDEO_BRIDGE_MENU=إنشاء &جسر فيديو service.gui.CONTACT_INFO_NOT_SUPPORTED=هذا المستخدم لا يمكنه التعامل مع معلومات المستخدم في الشبكة العنكبوتية service.gui.CUT=&قص -service.gui.DATE=تاريخ service.gui.DELETE=حذف service.gui.DENY=&رفض service.gui.DESKTOP_SHARING_WARNING=هل أنت متأكد من أنك تريد بدء مشاركة الشاشة؟
    عند الموافقة سيتمكن البعض من رؤية ما تراه أمامك على الشاشة. @@ -178,7 +173,6 @@ service.gui.DISCONNECTED_STATUS=مفصول service.gui.DND_STATUS=لا تزعجني service.gui.DO_NOT_ASK_AGAIN=لا تسألني مرة ثانية service.gui.DO_NOT_SHOW_AGAIN=لا تعرض هذه الرسالة مرة ثانية -service.gui.DOWNLOAD_NOW=&تنزيل الآن service.gui.DRAG_FOR_SHARING=اسحب هنا كل ما تريد مشاركته... service.gui.DURATION=مدة service.gui.EDIT=&تعديل @@ -195,7 +189,6 @@ service.gui.ERROR_RECEIVED_FROM=خطأ مستقبل من service.gui.ESTIMATED_TIME=الوقت المخمن : service.gui.EVENTS=أحداث service.gui.EXIT=خ&روج -service.gui.EXTENDED_CRITERIA=معايير مطولة service.gui.GENERAL=عام service.gui.GENERAL_ERROR=خطأ عام service.gui.GROUP_NAME=إسم المجموعة @@ -253,12 +246,12 @@ service.gui.HISTORY=&السجل service.gui.HISTORY_CONTACT=سجل - {0} service.gui.HOME=الرئيسية service.gui.HOME_PAGE=الصفحة الرئيسية -service.gui.HOUR=ساعة service.gui.ICE=ICE service.gui.IDENTIFIER=معرف service.gui.IGNORE=&تجاهل service.gui.INSERT_SMILEY=أدخل وجها تعبيريا service.gui.INCOMING_CALL=مكالمة واردة من : {0} +service.gui.INCOMING_SCREEN_SHARE=مكالمة واردة من : {0} service.gui.INCOMING_CALL_STATUS=مكالمة واردة service.gui.INSTANT_MESSAGINGS=IMs service.gui.INITIATING_CALL_STATUS=التحضير للمكالمة @@ -273,11 +266,8 @@ service.gui.INVITE_CONTACT_TO_CALL=أرسل دعوة إلى المستخدمين service.gui.INVITE_REASON=سبب الدعوة service.gui.IS_CALLING=يتصل .... service.gui.IS_NOW={0} هو {1} الآن -service.gui.JITSI_WARNING=لقد تم تسمية سيب كومينيكاتور بـ جيتسي مؤخرا.
    لجعل نسختك حديثة دوما، بادر بتنزيل جيتسي الآن.
    نأسف لما قد يسببه ذلك لكم.
    مع تحيات فريق تطوير جيتسي -service.gui.JITSI_WARNING_TITLE=سيب كومينيكاتور أصبح يعرف بـ جيتسي service.gui.JOIN=&إنضم أو شارك service.gui.JOIN_AS=إ&نضم كـ -service.gui.CLOSE_CHAT_ROOM_DIALOG=غ&لق service.gui.JOB_TITLE=عنوان الوظيفة service.gui.JOIN_CHAT_ROOM=&أدخل غرفة الدردشة... service.gui.JOIN_CHAT_ROOM_TITLE=أدخل غرفة الدردشة @@ -288,7 +278,6 @@ service.gui.KICK_FAILED=فشل الصد service.gui.KICK_FAILED_GENERAL_ERROR=فشل صد {0}. حدث خطأ عام فى الخادم. service.gui.KICK_FAILED_NOT_ALLOWED=فشل صد{0}. مالك ومدير الغرفة لا يمكن صد (إخراجه) service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=فشل صد{0}. ليس لديك صلاحيات كافيه لفعل ذلك. -service.gui.LAST=آخر service.gui.LAST_NAME=اسم العائلة service.gui.LEAVE=&أترك service.gui.LIMIT_REACHED_FOR_IP=لديك العديد من التسجيلات من عنوان انترنت واحد و الخادم {0} لا يسمح لك بعمل المزيد منها. @@ -308,7 +297,6 @@ service.gui.MESSAGE=رسالة service.gui.MISSED_CALLS_TOOL_TIP=مكالمات لم يتم الرد عليها واردة من: service.gui.MISSED_CALLS_MORE_TOOL_TIP= و بالاضافة إلى {0} service.gui.MODERATOR=منسق -service.gui.MORE=رؤية المزيد service.gui.MORE_LABEL=أنقل service.gui.MOVE=أنقل service.gui.MOVE_SUBCONTACT=أن&قل مستخدم @@ -317,7 +305,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=المستخدم الذي اخترت هو ن service.gui.MOVE_SUBCONTACT_QUESTION=متأكد من نقل {0} إلى {1}؟ service.gui.MOVE_TO_GROUP=&أنقل إلى مجموعة service.gui.MOVE_CONTACT=نقل مستخدم -service.gui.MOVE_CONTACT_ERROR=&لا يمكن نقل المستخدم service.gui.MSG_DELIVERY_FAILURE=الرسالة في أعلاه لم يتمكن من إرسالها service.gui.MSG_DELIVERY_NOT_SUPPORTED=نظام الاتصال (بروتوكول) المستخدم لا يتعامل مع الرسائل المبيتة. حاول أن تستخدم {0} نظاما آخر أو أن تنتظر حتى يكون المستخدم متصلا, service.gui.MSG_DELIVERY_INTERNAL_ERROR=حصل خلل داخلي. أغلب الظن بسبب خلل. يرجى الإعلام عنه هنا: http://www.jitsi.org/index.php/Development/BugsAndIssues @@ -328,7 +315,6 @@ service.gui.MSG_NOT_POSSIBLE=الرسائل غير ممكنة مع هذا الم service.gui.MSG_RECEIVED={0} كتب service.gui.MSG_SEND_CONNECTION_PROBLEM=عليك أن تكون مسجلا حتى تبعث رسائلا. service.gui.MULTIPLE_LOGINS=لقد سجلت دخولك أكثر من مرة بهذا الحساب. الحساب التالي غير موصول حاليا: اسم المستخدم: {0}، اسم الخادم: {1}. -service.gui.MUTE=بدون صوت service.gui.MUTUALLY_ON_HOLD_STATUS=في وضع الانتظار من الجهتين. service.gui.NAME=اسم service.gui.NETWORK=شبكة @@ -339,6 +325,7 @@ service.gui.NEW_MESSAGE=رسالة جديدة service.gui.NEW_NAME=اسم جديد service.gui.NEW_STATUS_MESSAGE=رسالة جديدة للدلالة على الحالة service.gui.NEW_STATUS_MESSAGE_SAVE=أحفظ كرسالة مخصصة +service.gui.NICKNAME=لقب service.gui.NO=لا service.gui.NONE=لا أحد service.gui.NO_CAMERA_AVAILABLE=لا توجد كاميرا @@ -355,7 +342,6 @@ service.gui.NON_EXISTING_USER_ID=الخادم {0} لا يعرف هوية الم service.gui.SD_QUALITY=جودة قياسية service.gui.OFFLINE=غير متصل service.gui.OK=&موافق -service.gui.OLDER_CALLS=المكالمات السابقة service.gui.ONLINE=متصل (مسجل) service.gui.OPEN=فتح service.gui.OPEN_FILE_FROM_IMAGE=اضغط مرتين لفتح الملف. @@ -363,9 +349,12 @@ service.gui.OPEN_FOLDER=فتح المجلد service.gui.OPEN_IN_BROWSER=فتح في &مستعرض service.gui.OPTIONS=خيارات service.gui.OR=أو -service.gui.OR_ENTER_PHONE_NUMBER=أو أدخل رقم الهاتف هنا... service.gui.ORGANIZATION=منظمة service.gui.OTHER=أخرى +service.gui.chat.role.ADMINISTRATOR=المسؤول +service.gui.chat.role.MODERATOR=منسق +service.gui.chat.role.MEMBER=عضو أو مشترك +service.gui.chat.role.SILENT_MEMBER=عضو صامت service.gui.OWNER=مالك الغرفة service.gui.PASSWORD=كلمة السر service.gui.PASSWORD_CHANGE_FAILURE=فشل تغيير كلمة المرور @@ -380,7 +369,6 @@ service.gui.PRESENCE=حضور service.gui.PRESS_ENTER_FOR_SUGGESTIONS="إدخال" للمقترحات service.gui.PRESS_FOR_CALL_INFO=إضغط للحصول على معلومات المكالمة service.gui.PREVIOUS=سابق -service.gui.PREVIOUS_TOOLTIP=استعراض الحوارات السابقة service.gui.PRINT=&طباعة service.gui.PROACTIVE_NOTIFICATION=يكتب رسالة service.gui.PROTOCOL=نظام (بروتوكول) @@ -393,7 +381,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=لقد قمت بقطع الاتصال و service.gui.RE_REQUEST_AUTHORIZATION=(أعد) طلب التصريح service.gui.REFERRED_STATUS=مشار إليه service.gui.REJECT=&رفض -service.gui.REMIND_ME_LATER=ذكرًني لاحقا service.gui.REMEMBER_PASSWORD=حفظ كلمة السر service.gui.REMOVE=&حذف service.gui.REMOVE_ACCOUNT=&حذف حساب @@ -417,27 +404,18 @@ service.gui.REVOKE_ADMIN=إخلاء المسؤولية service.gui.REVOKE_MODERATOR=التخلي عن واجب التنسيق service.gui.REVOKE_MEMBERSHIP=التخلي عن العضوية service.gui.REVOKE_VOICE=التخلي عن الكلام -service.gui.ROOT_GROUP=مجموعة رئيسة service.gui.SAVE=&احفظ -service.gui.SAVE_AS_DEFAULT=احفظ كافتراضي service.gui.SEARCH=&ابحث service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=اضغط على الزر في الأسفل لإظهار جميع غرف الحوار على الخادم الذي اخترت. ثم اختر ما تريد منها للدخول إليها و اضغط على دخول أو انضمام. service.gui.SEARCH_STRING_CONTACT_SOURCE=بحث جهة إتصال service.gui.SECURITY=حماية -service.gui.SELECT_ACCOUNT=اختر حسابا service.gui.SELECT_COLOR=اختر لونا service.gui.SELECT_GROUP=اختر مجموعة -service.gui.SELECT_GROUP_WIZARD_MSG=القائمة في الأسفل تحتوي على جميع أسماء مجموعات المستخدمين لديك. اختر ما شئت منها لتحديد مكان إضافة المستخدم الجديد. service.gui.SELECT_NO_GROUP=و لا مجموعة -service.gui.SELECT_GROUP_WIZARD=حدد المجموعة service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=القائمة في الأسفل تحتوي على جميع أسماء المستخدمين الذين لديهم خدمة الحوار المتعدد. اختر ما شئت منها لإنشاء غرفة حوار لك. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=القائمة في الأسفل تحتوي على جميع الحسابات المسجلة. اختر ما شئت منها للإتصال بالمستخدم الجديد. -service.gui.SELECT_PROVIDERS_WIZARD=اختر حسابا service.gui.SEND=&أرسل service.gui.SEND_FILE=أرسل ملفا -service.gui.SELECT_CONTACT_SUPPORTING_INFO=لا توجد معلومات عن هذا المستخدم. service.gui.SEND_MESSAGE=&أرسل رسالة -service.gui.SEND_AS_SMS=أرسل رسالة قصيرة (خدمة SMS) service.gui.SEND_SMS=أ&رسل رسالة قصيرة (خدمة SMS) service.gui.SEND_SMS_DETAILS=تذكًر أن عليك إدخال الرقم كاملا. مثال ، بـدءا بـ 44+ لبريطانيا، كما يلي : 447777000000+. service.gui.SEND_SMS_NOT_SUPPORTED=البروتوكول الذي اخترت لا يتعامل مع خدمة الرسائل القصيرة. @@ -472,7 +450,6 @@ service.gui.STREET=الشارع service.gui.SUBJECT=موضوع service.gui.SUMMARY=خلاصة service.gui.TELEPHONY=هاتف -service.gui.TODAY=اليوم service.gui.TOOLS=&أداوات service.gui.TRANSFER=&تحويل service.gui.TO=&إلى: @@ -482,7 +459,6 @@ service.gui.TRANSFER_CALL_TO=تحويل إلى : service.gui.TRANSPARENCY_NOT_ENABLED=الشفافية غير متاحة حسب الاعدادات الحالية لديك. service.gui.TYPE_YOUR_REQUEST=أدخل طلبك هنا service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=لم نستطع تغييرجودة فيديوهذه المكالمة. -service.gui.UNMUTE=تفعيل الصوت service.gui.USER_IDENTIFIER=معرف المستخدم : service.gui.USER_EXISTS_ERROR=هذا المستخدم موجود أصلا على الشبكة التي اخترت. لطفا، اختر شبكة أخرى. service.gui.USERNAME_NULL=إملأ اسم المستخدم و كلمة السر. @@ -494,7 +470,6 @@ service.gui.USE_PROVISIONING=استخدم التزود (بخدمة أو بعنو service.gui.VALUE=قيمة: service.gui.VIDEO_CALL=&مكالمة بالصوت و الصورة (فيديو) service.gui.VIA=عبر -service.gui.VIA_SMS=باستخدام خدمة الرسائل القصيرة service.gui.VIEW=&عرض service.gui.VIEW_HISTORY=عرض &السجل service.gui.VIEW_SMILEYS=أظهر الرسوم &التعبيرية @@ -512,9 +487,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=عدّل مستوى الصوت service.gui.WAITING_AUTHORIZATION=جاري انتظار تصريح service.gui.WARNING=تحذير service.gui.YES=نعم -service.gui.YESTERDAY=يوم أمس -service.gui.EXISTING_ACCOUNT_ERROR=الحساب الذي أدخلت موجود أصلا. -service.gui.NEW_MAIL=لديك بريد جديد واحد !
    من: {0} {1}
    الموضوع {2}
    {3}; service.gui.NEW_GMAIL_HEADER=لديك رسالة جديدة في {0} صندوق البريد:
    service.gui.NEW_GMAIL_MANY_HEADER=عدد الرسائل الجديدة هو {2} في صندوق البريد:{0}
    service.gui.NEW_GMAIL_FOOTER=لديك حوارا واحدا لم يقرأ بعد في صندوقك.
    @@ -536,7 +508,6 @@ service.gui.SECURITY_WARNING=تحذير حماية service.gui.SECURITY_ERROR=خلل حماية service.gui.SPEED=السرعة: service.gui.SILENT_MEMBER=عضو صامت -service.gui.UPDATE=تجديد أو تحديث service.gui.MOBILE_PHONE=محمول service.gui.VIDEO_PHONE=فيديو service.gui.WORK_PHONE=العمل @@ -563,7 +534,6 @@ service.gui.callinfo.TECHNICAL_CALL_INFO=معلومة تقنية عن الإتص service.gui.callinfo.CALL_INFORMATION=معلومات الطلب service.gui.callinfo.CALL_IDENTITY=هوية service.gui.callinfo.PEER_COUNT=عدد المشاركين -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=تفعيل التشفير service.gui.callinfo.CALL_DURATION=مدة المكالمة service.gui.callinfo.VIEW_CERTIFICATE=أظهر الشهادة service.gui.callinfo.CODEC=برنامج ترميز / تردد @@ -578,8 +548,11 @@ service.gui.callinfo.JITTER=Jitter service.gui.callinfo.MEDIA_STREAM_RTP=RTP service.gui.callinfo.MEDIA_STREAM_SRTP=RTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=بروتوكول مفتاح التبادل + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.COMPLETED=إكتمل service.gui.callinfo.ICE_STATE.FAILED=فشل + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=مضيف محلي / مدخل service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=IP عن بعد / مدخل service.gui.callinfo.HARVESTING_MS_FOR=ms (ل @@ -588,9 +561,10 @@ service.gui.ALWAYS_TRUST=الوثوق دوما بهذه الشهادة service.gui.CERT_DIALOG_TITLE=تحقق من الشهادة service.gui.CERT_DIALOG_DESCRIPTION_TXT={0}لا يمكن التحقق من هوية الخادم عند الاتصال
    بـ {1}:{2}.

    الشهادة غير موثوق بها، يعني أن هوية الخادم لا يمكن
    التحقق منها تلقائيا. هل تريد الاستمرار بالاتصال؟

    للمزيد من المعلومات اضغط على "إظهار الشهادة". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0}لا يمكن التحقق من هوية الخادم عند الاتصال
    بـ {1}:{2}.

    الشهادة غير موثوق بها، يعني أن هوية الخادم لا يمكن
    التحقق منها تلقائيا. هل تريد الاستمرار بالاتصال؟

    للمزيد من المعلومات اضغط على "إظهار الشهادة". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} لا يمكن التحقق من هوية المستخدم.

    الشهادة غير موثوق بها، يعني أن هوية المستخدم لا يمكن
    التحقق منها تلقائيا. هل تريد الاستمرار بالاتصال؟

    للمزيد من المعلومات اضغط على "إظهار الشهادة". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} لا يمكن التحقق من هوية المستخدم.

    الشهادة غير موثوق بها، يعني أن هوية المستخدم لا يمكن
    التحقق منها تلقائيا. هل تريد الاستمرار بالاتصال؟

    للمزيد من المعلومات اضغط على "إظهار الشهادة". service.gui.CONTINUE_ANYWAY=واصل على أي حال + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=اسم الشهرة: service.gui.CERT_INFO_O=منظمة : service.gui.CERT_INFO_C=اسم البلد: @@ -599,17 +573,16 @@ service.gui.CERT_INFO_L=المكان أو المنطقة: service.gui.CERT_INFO_OU=الوحدة التنظيمية: service.gui.CERT_INFO_ISSUED_ON=أصدرت بتاريخ: service.gui.CERT_INFO_EXPIRES_ON=تاريخ انتهاء الصلاحية: +service.gui.CERT_INFO_FINGERPRINTS=بصمة service.gui.CERT_INFO_SER_NUM=الرقم التسلسلي: service.gui.CERT_INFO_VER=نسخة: service.gui.CERT_INFO_SIGN_ALG=نوع نمط التوقيع: service.gui.CERT_INFO_ALG=النمط المستخدم: service.gui.CERT_INFO_PUB_KEY=المفتاح العام: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} بايت: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} بت service.gui.CERT_INFO_EXP=الأس: service.gui.CERT_INFO_KEY_SIZE=طول المفتاح service.gui.CERT_INFO_SIGN=التوقيع: -service.gui.CONTINUE=تابع service.gui.SHOW_CERT=أظهر الشهادة service.gui.HIDE_CERT=إخفاء الشهادة @@ -630,10 +603,8 @@ service.gui.security.SECURE_AUDIO=صوت أمن service.gui.security.AUDIO_NOT_SECURED=صوت غير أمن service.gui.security.SECURE_VIDEO=فيديو أمن service.gui.security.VIDEO_NOT_SECURED=فيديو غير أمن -service.gui.security.NO_VIDEO=لا يوجد فيديو -service.gui.security.CIPHER=تشفير: {0} +service.gui.security.CALL_SECURED_TOOLTIP=مكالمة أمنة. لمعلومات أكثر إضغط هنا. service.gui.security.CALL_NOT_SECURED_TOOLTIP=مكالمة غير أمنة. -service.gui.security.COMPARE_WITH_PARTNER=قارن مع رفيق (أو شريك) و اضغط على القفل للتفعيل. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=قارن مع الرفيق أو الشريك : {0} service.gui.security.STRING_COMPARED=سلسلة حرفية مقارنة! @@ -650,19 +621,13 @@ service.gui.avatar.imagepicker.CLICK=اضغط و ابتسم service.gui.avatar.imagepicker.IMAGE_FILES=ملفات الصور service.gui.avatar.imagepicker.IMAGE_PICKER=صورة service.gui.avatar.imagepicker.IMAGE_SIZE=حجم الصورة -service.gui.avatar.imagepicker.INITIALIZING=تجهيز service.gui.avatar.imagepicker.RESET=إعادة لوضع البدء service.gui.avatar.imagepicker.SET=جهِّز service.gui.avatar.imagepicker.TAKE_PHOTO=تصور -service.gui.avatar.imagepicker.WEBCAM_ERROR=خطأ في الكاميرا service.gui.security.encryption.required=تشفير ملزم! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=خطأ في تخزين قائمة الإتصال SIP impl.protocol.sip.XCAP_ERROR_UNAUTHORIZED=اسم المستخدم أو كلمة السر خاطئة بإستخدام xcap. ل {0}. @@ -684,9 +649,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=اختر شبكة # LDAP impl.ldap.CONFIG_FORM_TITLE=إعداد LDAP impl.ldap.GENERAL=عام -impl.ldap.NEW=جديد impl.ldap.EDIT=تعديل -impl.ldap.REMOVE=احذف impl.ldap.ENABLED=تم تفعيله impl.ldap.SERVER_NAME=اسم الخادم impl.ldap.SERVER_NAME_EXAMPLE=خادمي LDAP @@ -719,6 +682,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=هاتف البيت impl.ldap.PHONE_PREFIX=بادئة هاتف impl.ldap.PHONE_PREFIX_EXAMPLE=مثال: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=كتاب العناوين plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=تفعيل البحث في كتاب العناوين لنظام ماكنتوش أوو أس إكس @@ -729,9 +696,7 @@ plugin.addrbook.PREFIX_EXAMPLE=مثال: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=مستخدمي غوغل -impl.googlecontacts.NEW=جديد impl.googlecontacts.EDIT=حرر -impl.googlecontacts.REMOVE=حذف impl.googlecontacts.ENABLED=تم تفعيله impl.googlecontacts.ACCOUNT_NAME=اسم الحساب impl.googlecontacts.SAVE=احفظ @@ -760,9 +725,6 @@ plugin.accountinfo.EMAIL=بريد ألكتروني: plugin.accountinfo.PHONE=هاتف: plugin.accountinfo.MOBILE_PHONE=هاتف جوال plugin.accountinfo.JOB_TITLE=عنوان الوظيفة -plugin.accountinfo.USER_PICTURES=صور المستخدم -plugin.accountinfo.CHANGE=غيِّر -plugin.accountinfo.ONLY_MESSAGE=رسائل فقط # connection info @@ -781,49 +743,12 @@ plugin.aimaccregwizz.USERNAME=اسم مستخدم AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=اسم المستخدم و كلمة السر plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=التسجيل بحساب جديد plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=إذا لم يكن لديك حساب من AIM ، اضغط على هذا الزر لإنشاء حساب جديد. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=تخطي خيارات الخادم الافتراضية # branding plugin.branding.ABOUT_WINDOW_TITLE=عن {0} plugin.branding.LOGO_MESSAGE=نقل الصوت عبر الانترنت و الرسائل المباشرة، تقنية مجانية -plugin.branding.LOADING=تحميل plugin.branding.ABOUT_MENU_ENTRY=&عن البرنامج -plugin.branding.WELCOME_MESSAGE=
    {1} حاليا تحت التطوير المستمر‫.‬ النسخة التي لديك نسخة تجريبية و قد لا تعمل كما تتوقع‫.‬ لمزيد من المعلومات بإمكانك زيارة {2} .
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 حقوق النشر jitsi.org. الحقوق محفوظة. بالإمكان زيارة http://jitsi.org.
    -plugin.branding.LICENSE=
    جيتسي يوزع حسب اتفاقية LGPL ""(http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=القواميس -plugin.dictaccregwizz.ANY_DICTIONARY=أي قاموس -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=أي قاموس من {0} -plugin.dictaccregwizz.FIRST_MATCH=أول تطابق -plugin.dictaccregwizz.NO_MATCH=لا تطابق -plugin.dictaccregwizz.MATCH_RESULT=لا توجد تعريفات لـ "{0}"، ربما أنك تقصد:\n -plugin.dictaccregwizz.INVALID_DATABASE=القاموس الحالي "{0}" لم يعد موجودا لدى الخادم. -plugin.dictaccregwizz.INVALID_STRATEGY=فنون التخطيط الحالية غير موجودة لدى الخادم. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول خدمة Dict -plugin.dictaccregwizz.HOST=المضيف -plugin.dictaccregwizz.SERVER_INFO=معلومات الخادم -plugin.dictaccregwizz.STRATEGY_SELECTION=اختيار فن التخطيط -plugin.dictaccregwizz.STRATEGY_LIST=قائمة بفنون التخطيط: -plugin.dictaccregwizz.SEARCH_STRATEGIES=فنون تخطيط البحث -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=أساليب البحث تبحث عن التشابه في الكلمات، إذا لم يوجد تطابق، بفضل عدة حلول. مثلا أساليب البحث حسب البداية تبحث عن الكلمات التي تبدأ بالمقطع الذي تحدده. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=معلومات حساب Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=هذا المساعد سينشئ لك حساب Dict من dict.org.\n\nيمكنك أن تضيف قاموسا جديدا باستخدام "المساعد في تسجيل حساب جديد". املأ حقل اسم المضيف باسم القاموس الذي تود اضافته. -plugin.dictaccregwizz.THREAD_CONNECT=محاولة الاتصال بالخادم -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=فشل الاتصال، هذا ليس خادم Dict أو أن الخادم غير متصل. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=عرض فنون التخطيط -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=لا توجد فنون للتخطيط على الخادم -plugin.dictaccregwizz.POPULATE_LIST=ملء القائمة -plugin.dictaccregwizz.CLOSING_CONNECTION=إنهاء الإتصال - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    لاستخدام الدردشة على الفيس بوك يجب إنشاء "اسم مستخدم
    من صفحة إعدادات الحساب على الفيس بوك.


    Nملاحظة: عندما تنشئ اسم مستخدم عليك أن تسجل خروجك من الصفحة
    ، قد يتطلب وقتا قبل أن تسجل دخولك باستخدام اسم المستخدم الجديد!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول الدردشة لفيس بوك -plugin.facebookaccregwizz.PROTOCOL_NAME=فيس بوك -plugin.facebookaccregwizz.USERNAME=اسم المستخدم: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=اسم المستخدم و كلمة السر + # generalconfig plugin.generalconfig.AUTO_START=إعادة تشغيل {0} تلقائيا عند بدء تشغيل أو إعادة تشغيل الحاسوب @@ -833,9 +758,6 @@ plugin.generalconfig.SHOW_HISTORY=أظهر plugin.generalconfig.HISTORY_SIZE=الرسائل الحديثة في الحوارات الجديدة plugin.generalconfig.SEND_MESSAGES_WITH=ابعث الرسائل مع: plugin.generalconfig.BRING_WINDOW_TO_FRONT=لجعل نافذة الحوار فوق الأخريات -plugin.generalconfig.ERROR_PERMISSION=ليس لديك صلاحيات كافية لإلغاء إعادة التشغيل تلقائيا -plugin.generalconfig.TRANSPARENCY=شفافية أو صراحة -plugin.generalconfig.ENABLE_TRANSPARENCY=تفعيل الشفافية plugin.generalconfig.DEFAULT_LANGUAGE=لغة الواجهة البينية plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=التغييرات سوف تفعَّل لدى اعادة التشغيل التالي. plugin.generalconfig.SIP_CLIENT_PORT=ميناء عميل سيب SIP @@ -873,19 +795,20 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=تسجيل حساب جديد plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول IRC. plugin.ircaccregwizz.USERNAME_AND_PASSWORD=رمز المستخدم و كلمة السر +plugin.ircaccregwizz.USERNAME=لقب plugin.ircaccregwizz.INFO_PASSWORD=أغلب خوادم IRC لا تتطلب كلمة سر. plugin.ircaccregwizz.AUTO_NICK_CHANGE=غيِّر تلقائيا اللقب إذا كان مستعملا أصلا plugin.ircaccregwizz.USE_DEFAULT_PORT=استعمل الميناء الافتراضي plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=لقبي لا يحتاج إلى تعريف plugin.ircaccregwizz.HOST=اسم المضيف: plugin.ircaccregwizz.IRC_SERVER=خادم +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=التحقق أو التأكد من الهوية لـ {0}. +plugin.ircaccregwizz.SASL_USERNAME=اسم المستخدم: # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول XMPP plugin.jabberaccregwizz.USERNAME=XMPP إسم المستخدم plugin.jabberaccregwizz.PASSWORD_CONFIRM=أكد كلمة السر -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=اسم المستخدم و كلمة السر plugin.jabberaccregwizz.CSERVER=خادم plugin.jabberaccregwizz.SERVER=الاتصال بالخادم plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=تفعيل "إبقاء الاتصال" @@ -901,13 +824,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=تعقيب أو ملاحظة plugin.jabberaccregwizz.RESOURCE=وسيلة أو مورد plugin.jabberaccregwizz.AUTORESOURCE=أنتج تلقائيا وسيلة plugin.jabberaccregwizz.PRIORITY=أولوية -plugin.jabberaccregwizz.XMPP_ERROR=خطأ XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=خطأ XMPP غير معروف. تأكد من اسم الخادم. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=كلمة السر غير مطابقة -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=تخطي خيارات الخادم الافتراضية -plugin.jabberaccregwizz.ADVANCED_OPTIONS=خيارات متقدمة plugin.jabberaccregwizz.USE_ICE=استعمل ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=إستعمل Google's Jingle/ICE (تجريبي) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=استكشف تلقائيا خادم STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=دعم لـ TURN plugin.jabberaccregwizz.TURN_USERNAME=اسم المستخدم لـ TURN @@ -933,9 +852,6 @@ plugin.jabberaccregwizz.TELEPHONY_DOMAIN=نطاق الهاتف plugin.jabberaccregwizz.ALLOW_NON_SECURE=إسمح لإتصالات غير أمنة plugin.jabberaccregwizz.SERVER_OPTIONS=خيارات الخادم plugin.jabberaccregwizz.CHANGE_PASSWORD=تغيير حساب كلمة المرور -plugin.jabberaccregwizz.NEW_PASSWORD=كلمة مرور جديدة -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=أكد كلمة السر -plugin.jabberaccregwizz.PASSWORD_EMPTY=كلمة المرور فارغة plugin.jabberaccregwizz.PASSWORD_CHANGED=لقد تمّ تغيير كلمة المرور بنجاح plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=خادمك XMPP لا يدعم تغيير كلمة المرور. plugin.jabberaccregwizz.ENTER_NEW_PASSWORD=الرجاء إدخال كلمة المرور في كلا الحقلين @@ -944,25 +860,9 @@ plugin.jabberaccregwizz.AUDIO=سمعي plugin.jabberaccregwizz.VIDEO=فيديو (عرض بالصور) plugin.jabberaccregwizz.RESET=إعادة لوضع البدء -# mailbox -plugin.mailbox.OUTGOING=رسالة صادرة: -plugin.mailbox.INCOMING=رسائل واردة: -plugin.mailbox.WAIT_TIME=المدة حتى ترسل المكالمة إلى البريد الصوتي -plugin.mailbox.MAX_MESSAGE_TIME=أقصى فترة للرسالة الواردة -plugin.mailbox.CONFIRM=أكِّد -plugin.mailbox.DEFAULTS=افتراضيات -plugin.mailbox.MAILBOX=صندوق البريد - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول للوصول إلى الدردشة في خدمة MSN -plugin.msnaccregwizz.USERNAME=بريد الكتروني: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=اسم المستخدم و كلمة السر - # plugin manager plugin.pluginmanager.INSTALL=تثبيت plugin.pluginmanager.UNINSTALL=إزالة -plugin.pluginmanager.UPDATE=تجديد أو تحديث plugin.pluginmanager.PLUGINS=إضافات مدمجة plugin.pluginmanager.URL=عنوان وحيد لكائن مصدري plugin.pluginmanager.CHOOSE_FILE=اختر ملفا @@ -987,7 +887,6 @@ plugin.sipaccregwizz.SERVER_PORT=ميناء الخادم plugin.sipaccregwizz.PROXY=بروكسي (خادم يقوم مقام عميل أو خادم) plugin.sipaccregwizz.PROXY_PORT=ميناء البروكسي plugin.sipaccregwizz.PREFERRED_TRANSPORT=وسيلة النقل المفضلة -plugin.sipaccregwizz.ADVANCED_OPTIONS=خيارات متقدمة plugin.sipaccregwizz.PROXY_OPTIONS=خيارات البروكسي plugin.sipaccregwizz.PROXY_AUTO=إعداد البروكسي تلقائيا plugin.sipaccregwizz.ENABLE_PRESENCE=تفعيل الحضور (بسيط) @@ -1003,8 +902,6 @@ plugin.sipaccregwizz.DTMF=DTMF plugin.sipaccregwizz.DTMF_METHOD=طريقة DTMF plugin.sipaccregwizz.DTMF_RTP=(RTP ( RFC2833 / RFC 4733 plugin.sipaccregwizz.DTMF_SIP_INFO=معلومات SIP -plugin.sipaccregwizz.REGISTER=سجَّل -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=تجاهل خيارات الخادم الافتراضية plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=تفعيل تشفير المكالمات plugin.sipaccregwizz.AUTH_NAME=اسم السماح بالدخول plugin.sipaccregwizz.DISPLAY_NAME=الإسم المعروض @@ -1021,6 +918,7 @@ plugin.sipaccregwizz.VOICEMAIL=بريد صوتي plugin.sipaccregwizz.MWI=جاري إنتطار رسالة (MWI) plugin.sipaccregwizz.NOT_SAME_PASSWORD=كلمة السر غير مطابقة plugin.sipaccregwizz.SAVP_OPTION=إشارة RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_1=إجباري (عرض و اقبل فقط RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=أختياري (عرض أولا RTP/SAVP, و بعدها RTP/AVP) plugin.sipaccregwizz.SHOW_ADVANCED=إعدادات متقدمة للتشفير @@ -1033,15 +931,6 @@ plugin.skinmanager.DEFAULT_SKIN=المظهَر الافتراضي plugin.skinmanager.ADD_NEW_SKIN=أضف مظهَراً جديداً... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=المظهَر الافتراضي للتطبيق -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول آمن للاتصال بالحواسيب البعيدة باستخدام SSH -plugin.sshaccregwizz.USERNAME=معرِّف الحساب: -plugin.sshaccregwizz.IDENTITY_FILE=ملف الهوية: -plugin.sshaccregwizz.KNOWN_HOSTS=الحواسيب أو المضيفات المعروفة: -plugin.sshaccregwizz.OPTIONAL=اختياري -plugin.sshaccregwizz.ACCOUNT_DETAILS=تفاصيل الحساب - # status update plugin.autoaway.AUTO_STATUS=غائب تلقائياً plugin.autoaway.ENABLE_CHANGE_STATUS=غيِّر الحالة أثناء غيابك @@ -1087,22 +976,6 @@ plugin.whiteboard.DESELECT=إلغاء الاختيار plugin.whiteboard.DELETE=حذف plugin.whiteboard.PROPERTIES=خصائص -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول للاتصال و الدردشة مع خدمة ياهوو. -plugin.yahooaccregwizz.USERNAME=اسم المستخدم: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=اسم المستخدم و كلمة السر - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=خدمة الـ"من دون تعريف" -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=نظام الـ"بدون تعريف" أو بونجور. -plugin.zeroaccregwizz.FIRST_NAME=الاسم الأول: -plugin.zeroaccregwizz.LAST_NAME=اسم العائلة: -plugin.zeroaccregwizz.EMAIL=بريد ألكتروني: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=تذكر مستخدمي بونجور ؟ -plugin.zeroaccregwizz.USERID_AND_PASSWORD=المعرِّف و كلمة السر -plugin.zeroaccregwizz.USERID=معرِّف المستخدم : - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=بروتوكول نقاش غوغل @@ -1116,19 +989,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org، بوابة الاتصا plugin.iptelaccregwizz.USERNAME=اسم المستخدم: plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=اشترك مع iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=الاتصال بالصوت (و الصورة) و التحاور عبر الانترنت +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=اسم المستخدم: plugin.sip2sipaccregwizz.RETYPE_PASSWORD= أعد كتابة كلمة السر plugin.sip2sipaccregwizz.EMAIL=بريد ألكتروني -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=للمزيد عن هذه الخدمة تفضل بزيارة
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=عنوان البريد الالكتروني يستعمل لارسال بريد صوتي
    و للتنبيه عند وجود مكالمات فائتة و لاسترجاع كلمة السر مفقودة -plugin.sip2sipaccregwizz.INFO_NOTE=للمساعدة حول هذه الخدمة، تفضل بزيارةhttp://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=حساب sip2sip.info موجود أصلا -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=أنشئ حساب sip2sip.info مجانا - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=نقل الصوت عبر الانترنت و الرسائل المباشرة plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=للمزيد عن هذه الخدمة تفضل بزيارة
    http://ippi.fr @@ -1137,6 +1002,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=حساب ippi موجود أصلا plugin.ippiaccregwizz.CREATE_ACCOUNT=أنشئ حساب ippi مجانا # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=إغلاق نافذة الدردشة plugin.keybindings.CHAT_COPY=نسخ plugin.keybindings.CHAT_CUT=قص @@ -1158,14 +1024,15 @@ plugin.keybindings.globalchooser.MUTE_CALLS=كتم المكالمات plugin.keybindings.globalchooser.SHORTCUT_NAME=اسم plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=إختصار أوّلي plugin.keybindings.globalchooser.SHORTCUT_SECOND=إختصار ثانوي -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=جاري الإنتظار plugin.keybindings.globalchooser.ENABLE_SPECIAL=تفعيل مفتاح التحقق الخاص plugin.keybindings.PLUGIN_NAME=ارتباط المفاتيح +#Enum KeybindingSet.Category plugin.keybindings.CHAT=دردشة plugin.keybindings.MAIN=رئيسي plugin.keybindings.GLOBAL=اختصارات عامة # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=تفعيل plugin.notificationconfig.DESCRIPTION=وصف plugin.notificationconfig.TURN_ON_ALL=تشغيل الكل plugin.notificationconfig.TURN_OFF_ALL=إيقاف الكل @@ -1182,6 +1049,7 @@ plugin.notificationconfig.BROWSE_SOUND=اختر ملف الصوت plugin.notificationconfig.BROWSE_PROGRAM=إختر برنامج plugin.notificationconfig.tableheader.EXECUTE=تنفيذ برنامج: plugin.notificationconfig.tableheader.DESCRIPTION=وصف الحدث +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=مكالمة واردة plugin.notificationconfig.event.SecurityMessage=رسالة أمنة plugin.notificationconfig.event.IncomingFile=مكالمة واردة @@ -1275,6 +1143,7 @@ impl.neomedia.configform.VIDEO=فيديو impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultProfile=تشفير التخطيط الافتراضي للخيارات للمستخدم إلى: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=خط أساس impl.neomedia.configform.H264.defaultProfile.high=عالي impl.neomedia.configform.H264.defaultProfile.main=رئيسي @@ -1303,7 +1172,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=كلمة السر الحا plugin.securityconfig.masterpassword.ENTER_PASSWORD=أدخل كلمة سر جديدة: plugin.securityconfig.masterpassword.REENTER_PASSWORD=أعد كتابة كلمة السر: plugin.securityconfig.masterpassword.MP_TITLE=كلمة السر الرئيسة -plugin.securityconfig.masterpassword.MP_NOT_SET=(غير مجهز) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=لم تقم بإدخال كلمة السر الرئيسة الحالية كما يجب. لطفا، حاول مرة أخزى. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=كلمة السر الرئيسة غير صحيحة ! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=فشل تغيير كلمة السر @@ -1319,7 +1187,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=كلمة السر plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(مجهول) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(لا يمكن فك الترميز) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=كلمات مرور محفوظة -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=حذف plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=احذف الكل plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=أمتأكد من أنك تريد حذف كل كلمات السر؟ plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=حذف كل كلمات السر @@ -1381,7 +1248,6 @@ plugin.globalproxy.PROXY_PORT=ميناء البروكسي plugin.globalproxy.PROXY_USERNAME=اسم المستخدم للبروكسي plugin.globalproxy.PROXY_PASSWORD=كلمة السر للبروكسي plugin.globalproxy.DESCRIPTION={0} سيستخدم إعدادات البروكسي أعلاه لجميع الشبكات التي ستتصل بها أو منها منذ الآن.\nإن دعم البروكسي هو تجريبي حاليا و يعمل مع عدد من البروتوكولات. تأكد من الجدول في الأسفل لمزيد من المعلومات: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1394,6 +1260,8 @@ plugin.reconnectplugin.NETWORK_DOWN=قطع الاتصال بالشبكة ! plugin.chatconfig.TITLE=دردشة أو حوار plugin.chatconfig.replacement.TITLE=صورة/فيديو plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=تفعيل تبديل الوجوه التعبيرية +plugin.chatconfig.replacement.REPLACEMENT_TITLE=تفعيل تبديل الصورة أو الفيديو +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=تفعيل plugin.chatconfig.replacement.REPLACEMENT_SOURCES=مصادر: plugin.chatconfig.spellcheck.TITLE=تدقيق إملاء @@ -1461,8 +1329,6 @@ net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult #plugin spellcheck plugin.spellcheck.TITLE=هجاء و قواعد plugin.spellcheck.MENU=أظهر هجاء و قواعد -plugin.spellcheck.LANG=لغة -plugin.spellcheck.EDIT_PERSONAL_DICT=تعديل plugin.spellcheck.ENABLE_SPELL_CHECK=مكن التدقيق الإملائي plugin.spellcheck.dialog.FIND=ابحث عن التالي plugin.spellcheck.dialog.REPLACE=بدّل -- cgit v1.1 From 65c6dcabe1186861d82d8305647717873e2c062c Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:52 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 229 of 1505 strings translated (43 fuzzy). --- resources/languages/resources_fi.properties | 123 ++++++++++++++-------------- 1 file changed, 63 insertions(+), 60 deletions(-) diff --git a/resources/languages/resources_fi.properties b/resources/languages/resources_fi.properties index 2fe17fc..726c514 100644 --- a/resources/languages/resources_fi.properties +++ b/resources/languages/resources_fi.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,38 +43,33 @@ service.gui.ACCOUNT_ME=Minä service.gui.ACCOUNT_REGISTRATION_WIZARD=Tilin Rekisteröinti Apuri service.gui.ACCOUNTS=Tilit service.gui.ADD=&Lisää -service.gui.ADD_ACCOUNT=Lisää tili service.gui.ADD_CONTACT=&Lisää kontakti service.gui.ADD_AUTHORIZED_CONTACT=Lisää {0} kontakti listallesi +service.gui.ADD_CONTACT_TO_CONTACTLIST=Lisää henkilö kontaktilistallesi service.gui.ADD_CONTACT_TO=&Lisää kontakti service.gui.ADD_CONTACT_ERROR=Epäonnistui lisäämään kontaktin tunnuksella: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Kontaktin lisäys Virhe -service.gui.ADD_CONTACT_EXIST_ERROR=Kontakti {0} löytyy jo sinun kontakti listalta. +service.gui.ADD_CONTACT_EXIST_ERROR=Kontakti {0} löytyy jo sinun kontaktilistalta. service.gui.ADD_CONTACT_NETWORK_ERROR=Palvelin ei vastannut pyyntöön lisätä kontaktia tunnuksella: {0} service.gui.ADD_CONTACT_NOT_SUPPORTED=Epäonnistui lisäämään kontaktin tunnuksella: {0}. Ei tuettu toiminto. -service.gui.ADD_CONTACT_IDENTIFIER=Anna alapuolella olevaan kenttään lisättävän kontaktin tunniste. -service.gui.ADD_CONTACT_WIZARD=Lisää kontakti apuri service.gui.ADD_CONTACT_NOT_CONNECTED=Sinun täytyy olla yhdistettynä lisääksesi kontaktin. Kirjaudu sisään valituun palveluun ja yritä uudelleen. service.gui.ADD_GROUP_LOCAL_ERROR=Ryhmän {0} nimen lisääminen epäonnistui. Ongelma tapahtui paikallisen IO operaation aikana. -service.gui.ADD_GROUP_EXIST_ERROR=Ryhmä {0} löytyy jo kontakti listasta. Valitse toinen nimi. +service.gui.ADD_GROUP_EXIST_ERROR=Ryhmä {0} löytyy jo kontaktilistasta. Valitse toinen nimi. service.gui.ADD_GROUP_NET_ERROR=Ryhmän {0} nimen lisääminen epäonnistui. Ongelma tapahtui verkko ongelman takia. Tarkista että verkkoyhteys toimii ja yritä uudelleen. service.gui.ADD_GROUP_ERROR=Ryhmän {0} nimen lisääminen epäonnistui. service.gui.ADD_GROUP_EMPTY_NAME=Ryhmän nimi ei voi olla tyhjä. -service.gui.ADD_GROUP=Luo ryhmä -service.gui.ADD_SUBCONTACT=&Lisää ali-kontakti service.gui.ADDRESS=Osoite service.gui.ADMINISTRATOR=ylläpitäjä service.gui.ADVANCED=&Edistynyt -service.gui.ALL=&Kaikki service.gui.ALL_CONTACTS=&Kaikki kontaktit +service.gui.ALTERNATE_ADDRESS=Toissijainen osoite service.gui.APPLY=&Käytä -service.gui.ARE_CALLING=soittaa... +service.gui.ARE_CALLING={0} soittaa... service.gui.ARE_NOW=Olet nyt {0} service.gui.AT=at service.gui.AUTHORIZE=&Vahvista service.gui.AUTHORIZATION_ACCEPTED=on hyväksynyt vahvistuspyynnön. service.gui.AUTHENTICATION_FAILED=Tunnistus virhe {0}. Syötetty salasana ei ole oikein. -service.gui.AUTHENTICATION_REQUESTED=Tunnistautuminen lähetetty service.gui.AUTHENTICATION_REQUESTED_SERVER={0} palvelin pyytää sinulta tunnistautumista. service.gui.AUTHENTICATION_REJECTED=eväsi sinun vahvistuspyynnön. service.gui.AUTHENTICATION_WINDOW_TITLE={0} tunnistautuminen @@ -73,6 +79,7 @@ service.gui.AUTHORIZATION_RESPONSE=Vahvistus vastaus service.gui.AWAY_STATUS=Poissa service.gui.EXTENDED_AWAY_STATUS=Pidennetty poissaolo service.gui.BAN=&Estä +service.gui.BANNED=estetty service.gui.BAN_FAILED=Estäminen epäonnistui service.gui.BAN_FAILED_GENERAL_ERROR=Estäminen epäonnistui {0}. Tapahtui yleinen palvelin virhe. service.gui.BAN_FAILED_NOT_ALLOWED=Estäminen epäonnistui {0}. Huoneen ylläpitäjää tai omistajaa ei voi estää. @@ -85,6 +92,7 @@ service.gui.CALL=Soita service.gui.CALL_CONTACT=Soita kontaktille service.gui.CALL_FAILED=Soitto epäonnistui service.gui.CALL_HISTORY_TOOL_TIP=Paina tästä nähdäksesi soitto historia +service.gui.CALL_HISTORY_GROUP_NAME=Soittohistoria service.gui.CALL_VIA=Soita: service.gui.CALL_NAME_OR_NUMBER=Soita nimellä tai numerolla service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=Tämä puhelu tukee ainoastaan osallistujat {0} verkosta ja sinun {1} tunnuksesta. {2} ei ole osoitetta tähän verkkoon tai tunnukseen. @@ -100,26 +108,41 @@ service.gui.CHANGE_ROOM_SUBJECT_LABEL=Alla olevaan kenttään voit laittaa huone service.gui.CHANGE_NICK=Vaihda kutsumanimi service.gui.CHANGE_NICKNAME=Vaihda kutsumanimi... service.gui.CHANGE_NICKNAME_LABEL=Alla olevaan kenttään voit laittaa uuden kutsumanimen. -service.gui.CHANGE_NICKNAME_ERROR=Tapahtui virhe muutettaessa nimeä +service.gui.CHANGE_NICKNAME_ERROR=Lempinimeä muutettaessa tapahtui virhe service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nimi on jo käytössä service.gui.CHANGE_VIDEO_QUALITY=Vaihda etävideon laatu -service.gui.CHAT_CONFERENCE_LABEL=Kokous service.gui.CHAT_CONFERENCE_ITEM_LABEL=käyttäjän {0} kokouksessa -service.gui.CHAT_ROOM_USER_JOINED=liittyi +service.gui.CHAT_ROOM_ALREADY_JOINED=Huoneeseen {0} on jo liitytty +service.gui.CHAT_ROOM_CONFIGURATION={0} huoneen asetukset +service.gui.CHAT_ROOM_CONFIGURATION_FAILED=Huoneen {0} asetuslomakkeen haku epäonnistui +service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=Huoneen {0} asetuslomakkeen haku epäonnistui. Vain huoneen omistajat voivat nähdä ja muokata asetuslomaketta. +service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=Virhe huoneen {0} asetuslomakkeen lähetyksessä. +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=Muokkaa jäsenlistaa +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=Oikealla olevassa listassa on huoneen jäsenet. Kun huoneen tila on "vain jäsenille", vain listassa olevat henkilöt voivat liittyä. +service.gui.CHAT_ROOM_USER_JOINED=liittyi {0} service.gui.CHAT_ROOM_USER_LEFT=on poistunut {0} -service.gui.CHAT_ROOM_USER_QUIT=poistui {0} +service.gui.CHAT_ROOM_USER_KICKED=potkaistiin huoneesta {0} +service.gui.CHAT_ROOM_USER_QUIT=poistui huoneesta {0} +service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Viestin lähetys estetty. service.gui.CHAT_ROOM_NAME=Keskusteluhuoneen nimi service.gui.ROOM_NAME=Keskusteluhuone service.gui.CHANGE_PASSWORD=Vaihda salasana +service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Huone {0} vaatii salasanan. service.gui.CHAT_ROOMS=Keskusteluhuone service.gui.CHAT_ROOM=Keskusteluhuone +service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} vaihtoi aiheeksi {1} +service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=Voit jatkaa keskustelua huoneessa {0} +service.gui.CHAT_NICKNAME_CHANGE={0} on nyt {1} +service.gui.CHOOSE_CONTACT=Valitse yhteyshenkilö +service.gui.CHOOSE_NUMBER=Valitse numero +service.gui.CHOOSE_ACCOUNT=Valitse yksi tunnuksista service.gui.CLOSE=&Sulje -service.gui.CONFIRM=Vahvista service.gui.CONNECTED_STATUS=Yhdistetty service.gui.CONNECTING=Yhdistää... service.gui.CONNECTING_STATUS=Yhdistää service.gui.CONNECTING_EARLY_MEDIA_STATUS=Yhdistää* service.gui.CONNECTION=Yhdistetään... +service.gui.CONNECTION_EXPIRED_MSG=Yhteys palvelimeen {0} on katkaistu. service.gui.CONTACT_NAME=Tunnus tai Numero service.gui.CONTACT_TYPING={0} kirjoittaa viestiä service.gui.COPY=&Kopioi @@ -129,8 +152,7 @@ service.gui.DELETE=Poista service.gui.DENY=&Estä service.gui.DO_NOT_ASK_AGAIN=Älä kysy uudestaan service.gui.DO_NOT_SHOW_AGAIN=Älä näytä tätä viestiä uudestaan -service.gui.DOWNLOAD_NOW=&Lataa nyt -service.gui.DRAG_FOR_SHARING=Raahaa hiirellä tähän mitä haluat jakaa... +service.gui.DRAG_FOR_SHARING=Vedä tähän tiedosto, jonka haluat jakaa... service.gui.DURATION=kesto service.gui.EDIT=&Muokkaa service.gui.EMPTY_HISTORY=&Tyhjennä historia @@ -155,16 +177,14 @@ service.gui.HIDE=Piilota service.gui.HISTORY=&Historia service.gui.HISTORY_CONTACT=Historia - {0} service.gui.HOME=Koti +service.gui.INSERT_SMILEY=Lisää hymiö service.gui.IS_CALLING=soittaa... -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Sulje service.gui.KICK_FAILED_GENERAL_ERROR=Estäminen epäonnistui {0}. Tapahtui yleinen palvelin virhe. service.gui.KICK_FAILED_NOT_ALLOWED=Estäminen epäonnistui {0}. Huoneen ylläpitäjää tai omistajaa ei voi estää. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Estäminen epäonnistui {0}. Sinulla ei ole tarpeeksi oikeuksia estämiseen. -service.gui.LAST=Viimeinen service.gui.LIST=Viimeinen service.gui.LOADING=Lataa... service.gui.MESSAGE=Viesti -service.gui.MORE=Näytä enemmän service.gui.MORE_LABEL=Siirrä service.gui.MOVE=Siirrä service.gui.NEXT=&Seuraava @@ -175,17 +195,20 @@ service.gui.NO=Ei service.gui.NONE=Ei mitään service.gui.NO_CAMERA_AVAILABLE=Ei kameraa saatavilla service.gui.NO_MESSAGE=Uusi viesti +service.gui.OFFLINE=Offline +service.gui.OK=&OK service.gui.ONLINE=Paikalla service.gui.OPEN=Avaa service.gui.OPEN_FOLDER=Avaa kansio -service.gui.OPEN_IN_BROWSER=Avaa &selaimeen +service.gui.OPEN_IN_BROWSER=Avaa &selaimessa service.gui.OPTIONS=Asetukset service.gui.OR=tai service.gui.ORGANIZATION=Yritys: +service.gui.chat.role.ADMINISTRATOR=ylläpitäjä service.gui.PASSWORD=Salasana service.gui.PASTE=&Liitä +service.gui.PORT=Portti service.gui.PREVIOUS=Edellinen -service.gui.PREVIOUS_TOOLTIP=Selaa vanhoja keskusteluja service.gui.PRINT=&Tulosta service.gui.PROACTIVE_NOTIFICATION=kirjoittaa viestiä service.gui.PROTOCOL=Protokolla @@ -193,34 +216,28 @@ service.gui.QUIT=&Lopeta service.gui.READY=Valmis service.gui.REASON=Syy service.gui.REJECT=&Hylkää -service.gui.REMIND_ME_LATER=Muistuta myöhemmin service.gui.REMEMBER_PASSWORD=Muista salasana service.gui.REMOVE=&Poista service.gui.REMOVE_ACCOUNT=&Poista tili service.gui.REMOVE_ACCOUNT_MESSAGE=Haluatko varmasti poistaa tämän tilin? service.gui.SAVE=&Tallenna -service.gui.SAVE_AS_DEFAULT=Tallenna oletuksena service.gui.SEARCH=&Etsi -service.gui.SELECT_ACCOUNT=Valitse tili -service.gui.SELECT_PROVIDERS_WIZARD=Valitse tili service.gui.SEND=&Lähetä service.gui.SEND_FILE=Lähetä &tiedosto service.gui.SET_STATUS_MESSAGE=Uusi tilaviesti service.gui.SETTINGS=&Asetukset service.gui.SHOW=Näytä -service.gui.SHOW_MORE=näytä lisää... +service.gui.SHOW_MORE=Näytä lisää... service.gui.SIGN_IN=Kirjaudu sisään service.gui.STATUS=Tila service.gui.SUBJECT=Aihe service.gui.TELEPHONY=Puhelin -service.gui.TODAY=Tänään service.gui.TOOLS=&Työkalut service.gui.VALUE=Arvo: service.gui.VOICEMAIL_NO_MESSAGES=Uusi viesti service.gui.WARNING=Varoitus service.gui.YES=Kyllä service.gui.NEW=Uusi -service.gui.UPDATE=Päivitys service.gui.MOBILE_PHONE=Matkapuhelin service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Työ @@ -239,19 +256,22 @@ service.gui.OCTOBER=Lok service.gui.NOVEMBER=Mar service.gui.DECEMBER=Jou + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.COMPLETED=Valmis + + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_O=Yritys: service.gui.CERT_INFO_C=Maa: service.gui.CERT_INFO_ST=Osavaltio tai lääni: service.gui.CERT_INFO_SER_NUM=Sarjanumero: service.gui.CERT_INFO_VER=Versio: -service.gui.CONTINUE=Jatka service.gui.AUTO_ANSWER_VALUE=Arvo: service.gui.AUTO_ANSWER_VIDEO=Video -service.gui.security.NO_VIDEO=Ei videoa # keep the following string short service.gui.avatar.CHOOSE_ICON=Valitse kuva @@ -264,9 +284,6 @@ service.gui.avatar.imagepicker.CHOOSE_FILE=Valitse ... -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -274,20 +291,20 @@ service.gui.avatar.imagepicker.CHOOSE_FILE=Valitse ... # New Account Dialog # LDAP -impl.ldap.NEW=Uusi impl.ldap.EDIT=&Muokkaa -impl.ldap.REMOVE=&Poista impl.ldap.AUTH_NONE=Ei mitään impl.ldap.SAVE=&Tallenna impl.ldap.CANCEL=&Peruuta impl.ldap.PASSWORD=Salasana +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts -impl.googlecontacts.NEW=Uusi impl.googlecontacts.EDIT=&Muokkaa -impl.googlecontacts.REMOVE=&Poista impl.googlecontacts.SAVE=&Tallenna impl.googlecontacts.CANCEL=&Peruuta impl.googlecontacts.PASSWORD=Salasana @@ -303,9 +320,6 @@ impl.googlecontacts.PASSWORD=Salasana # branding plugin.branding.ABOUT_MENU_ENTRY=&Tietoja -# Dict protocol - -# facebookaccregwizz # generalconfig plugin.generalconfig.SHOW_HISTORY=Näytä @@ -315,29 +329,22 @@ plugin.generalconfig.SHOW_HISTORY=Näytä # icqaccregwizz # irc accregwizz +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} tunnistautuminen # jabber accregwizz plugin.jabberaccregwizz.VIDEO=Video -# mailbox -plugin.mailbox.CONFIRM=Vahvista - -# msn accregwizz - # plugin manager -plugin.pluginmanager.UPDATE=Päivitys plugin.pluginmanager.NEW=Uusi # simple accregwizz # sipaccregwizz plugin.sipaccregwizz.XCAP_PASSWORD=Salasana +#used from SecurityPanel # skin manager -# ssh accregwizz -plugin.sshaccregwizz.OPTIONAL=Asetukset - # status update # updatechecker @@ -350,24 +357,21 @@ plugin.whiteboard.OPEN=Avaa plugin.whiteboard.COLOR=Väri plugin.whiteboard.DELETE=Poista -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=&Kopioi plugin.keybindings.CHAT_PASTE=&Liitä +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Keskustelu # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -381,6 +385,7 @@ impl.media.security.zrtp.TITLE=Soita impl.neomedia.configform.VIDEO=Video +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -389,7 +394,6 @@ impl.neomedia.configform.VIDEO=Video plugin.securityconfig.masterpassword.TITLE=Salasana plugin.securityconfig.masterpassword.REENTER_PASSWORD=Muista salasana plugin.securityconfig.masterpassword.COL_PASSWORD=Salasana -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=&Poista # otr plugin plugin.otr.authbuddydialog.CANCEL=&Peruuta @@ -415,7 +419,6 @@ plugin.chatconfig.TITLE=Keskustelu net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=&Estä #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=&Muokkaa #Certificate configuration plugin -- cgit v1.1 From d6392dba360eae295af12426da84a7b13ffdeda5 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:52:59 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1301 of 1505 strings translated (38 fuzzy). --- resources/languages/resources_uk.properties | 220 +++++----------------------- 1 file changed, 39 insertions(+), 181 deletions(-) diff --git a/resources/languages/resources_uk.properties b/resources/languages/resources_uk.properties index da09699..53e2064 100644 --- a/resources/languages/resources_uk.properties +++ b/resources/languages/resources_uk.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Я service.gui.ACCOUNT_REGISTRATION_WIZARD=Майстер реєстрування облікових записів service.gui.ACCOUNTS=Облікові записи service.gui.ADD=&Додати -service.gui.ADD_ACCOUNT=Додати обліковий запис service.gui.ADD_CONTACT=&Додати контакт service.gui.ADD_AUTHORIZED_CONTACT=Додати {0} до списку контактів service.gui.ADD_CONTACT_TO_CONTACTLIST=Додати контакт у ваш список контактів @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Помилка додавання конта service.gui.ADD_CONTACT_EXIST_ERROR=Контакт {0} вже існує у списку контактів. service.gui.ADD_CONTACT_NETWORK_ERROR=Сервер не відповів на запит додавання контакту: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Не вдалося додати контакт: {0}. Операція не підтримується. -service.gui.ADD_CONTACT_IDENTIFIER=Введіть ідентифікатор контакту, який хочете додати. -service.gui.ADD_CONTACT_WIZARD=Майстер додавання контактів service.gui.ADD_CONTACT_NOT_CONNECTED=Щоб додати контакт, необхідно підключитися. Будь-ласка, виконайте вхід і спробуйте знову. service.gui.ADD_GROUP_LOCAL_ERROR=Не вдалося додати групу: {0}. Відбувся збій операції вводу-виводу. service.gui.ADD_GROUP_EXIST_ERROR=Група {0} вже існує у списку контактів. Будьласка, оберіть інше ім’я. service.gui.ADD_GROUP_NET_ERROR=Не вдалося додати групу: {0}. Відбулася мережева помилка. Будьласка, перевірте ваше мережеве підключення і спробуйте знову. service.gui.ADD_GROUP_ERROR=Не вдалося додати групу: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Назва групи не може бути порожньою. -service.gui.ADD_GROUP=Створити групу -service.gui.ADD_SUBCONTACT=&Додати додатковий контакт service.gui.ADDRESS=Адреса service.gui.ADMINISTRATOR=адміністратор service.gui.ADVANCED=&Розширені -service.gui.ALL=&Всі service.gui.ALL_CONTACTS=&Всі контакти service.gui.ALTERNATE_ADDRESS=Альтернативна адреса service.gui.APPLY=&Застосувати @@ -65,7 +70,6 @@ service.gui.AT=час service.gui.AUTHORIZE=&Авторизувати service.gui.AUTHORIZATION_ACCEPTED={0} прийняв запит авторизації. service.gui.AUTHENTICATION_FAILED=Перевірити справжність {0} не вдалося. Введений пароль невірний. -service.gui.AUTHENTICATION_REQUESTED=Запит перевірки справжності service.gui.AUTHENTICATION_REQUESTED_SERVER=Сервер {0} запитує перевірку справжності. service.gui.AUTHENTICATION_REJECTED={0} відхилив запит авторизації. service.gui.AUTHENTICATION_WINDOW_TITLE=Ідентифікація {0} @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=В полі нижче ви можее вве service.gui.CHANGE_NICKNAME_ERROR=Помилка при зміні прізвиська service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Прізвисько вже існує service.gui.CHANGE_VIDEO_QUALITY=Змінити якість вхідного відео -service.gui.CHAT_CONFERENCE_LABEL=Конференції service.gui.CHAT_CONFERENCE_ITEM_LABEL=Конференція користувача {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Конференція {0} вже підключена. service.gui.CHAT_ROOM_CONFIGURATION=Конфігурація конференції {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=покинув {0} service.gui.CHAT_ROOM_USER_KICKED=був виключений з {0} service.gui.CHAT_ROOM_USER_QUIT=вийшов із {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Надсилання повідомлень заборонено (вимкнено звук) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Зберігає конференцію для подальшого використання -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Вилучає вибрану конференцію зі списку збережених конференцій service.gui.CHAT_ROOM_NAME=Назва конференції service.gui.CLEAR_CUSTOM_MESSAGES=Очистити персоналізовані повідомлення service.gui.ROOM_NAME=Конференція -service.gui.AUTOJOIN=Автоматичний вхід service.gui.CHANGE_PASSWORD=Змінити пароль service.gui.CHAT_ROOM_NAME_INFO=В полі нижче введіть ім’я конференції, яку хочете створити. service.gui.CHAT_ROOM_NOT_EXIST=Конференція {0} не знайдена на сервері {1}. Будьласка, перевірте правильність введеного імені. service.gui.CHAT_ROOM_NOT_CONNECTED=Ви повинні бути зареєстровані, щоб мати можливість приєднатися до конференції {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Ви повинні бути підключені щоб мати можливість вийти з конференції. -service.gui.CHAT_ROOM_NOT_JOINED=Ви повинні ввійти в конференцію, щоб мати можливість здійснювати операції з нею. service.gui.CHAT_ROOM_OPTIONS=Налаштування конференції service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Конференція {0} вимагає реєстрування для входу. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Конференція {0} запитує пароль. @@ -157,16 +156,13 @@ service.gui.CONNECTING=Підключення... service.gui.CONNECTING_STATUS=Підключення service.gui.CONNECTING_EARLY_MEDIA_STATUS=Підключення* service.gui.CONNECTION=З’єднання -service.gui.CONNECTION_FAILED_MSG=Не вдалося з’єднання для наступного облікового запису: Ім’я користувача: {0}, Назва сервера: {1}. Будьласка перевірте ваше мережеве підключення або звяжіться з вашим мережевим адміністратором для додаткової інформації. service.gui.CONNECTION_EXPIRED_MSG=В даний момент ви відключені від сервера {0}. service.gui.CONTACT_NAME=ID або номер -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Вибраний контакт {0} не підтримує голосовий звязок. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Вибраний контакт {0} не підтримує чат в конференції. service.gui.CONTACT_PAUSED_TYPING={0} переслав друковане повідомлення service.gui.CONTACT_TYPING={0} друкує повідомлення service.gui.CONTACT_TYPING_SEND_FAILED=співрозмовник {0} не побачить процес створення повідомлення service.gui.CONTACT_INFO=&Контактна інформація -service.gui.CONTACTLIST=Список контактів service.gui.CONTACTS=Контакти service.gui.COPY=&Копіювати service.gui.COPY_LINK=Копіювати &посилання @@ -176,27 +172,24 @@ service.gui.CREATE_CHAT_ROOM=&Створити конференцію... service.gui.CREATE_CHAT_ROOM_ERROR=Не вдалося створити конференцію {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Майстер створення конференцій service.gui.CREATE_CONFERENCE_CALL=&Створити багатокористувацький дзвінок... -service.gui.CREATE_CONFERENCE_CHAT=&Створити багатокористувацький чат... service.gui.CREATE_GROUP=&Створити групу... service.gui.CREATE_GROUP_NAME=В полі нижче введіть ім’я групи, яку хочете створити. -service.gui.CREATE_FIRST_GROUP_WIZARD=Ваш список контактів не містить жодної групи. Будьласка, спочатку створіть групу (Файл/Створити групу). service.gui.CREATE_VIDEO_BRIDGE=Створити &відеоміст... service.gui.CREATE_VIDEO_BRIDGE_MENU=Створити &відеоміст service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Створити / Долучитись до відео-конференції service.gui.CREATE_VIDEO_CONFERENCE=Створити нову відео-конференцію для цієї кімнати service.gui.CONTACT_INFO_NOT_SUPPORTED=Даний контакт не підтримує мережеву контактну інформацію service.gui.CUT=В&ирізати -service.gui.DATE=Дата service.gui.DELETE=Вилучити service.gui.DENY=&Відхилити service.gui.DESKTOP_SHARING_WARNING=Ви впевнені, що хочете надати доступ до вашого екрану?
    Натиснення OK дозволить абонентам, які беруть участину у розмові, бачити вміст вашого екрану. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Ви демонструєте ваш екран service.gui.DIALPAD=Номеронабирач service.gui.DISPLAY_NAME=Відображуване ім’я service.gui.DISCONNECTED_STATUS=Роз’єднано service.gui.DND_STATUS=Не турбувати service.gui.DO_NOT_ASK_AGAIN=Не питати знову service.gui.DO_NOT_SHOW_AGAIN=Не показувати це повідомлення знову -service.gui.DOWNLOAD_NOW=&Завантажити тепер service.gui.DRAG_FOR_SHARING=Перенесіть сюди для спільного доступу... service.gui.DURATION=тривалість service.gui.DESTROY_CHATROOM=Видалити конференцію @@ -217,7 +210,6 @@ service.gui.ERROR_RECEIVED_FROM=Помилка отримана від {0} service.gui.ESTIMATED_TIME=Приблизний час: service.gui.EVENTS=Події service.gui.EXIT=В&ийти -service.gui.EXTENDED_CRITERIA=Розширений критерій service.gui.GENERAL=Загальні service.gui.GENERAL_ERROR=Загальна помилка service.gui.GROUP_NAME=Ім’я групи @@ -259,7 +251,6 @@ service.gui.FONT_ITALIC=Курсив service.gui.FONT_SIZE=Розмір service.gui.FONT_STYLE=Стиль service.gui.FONT_UNDERLINE=Підкреслення -service.gui.FROM={0} від {1} service.gui.GRANT_OWNERSHIP=Додати до власників... service.gui.GRANT_ADMIN=Додати до адміністраторів... service.gui.GRANT_MODERATOR=Додати до модераторів @@ -271,7 +262,7 @@ service.gui.HD_QUALITY=HD відео service.gui.HELP=&Допомога service.gui.HIDE=Приховати service.gui.HIDE_OFFLINE_CONTACTS=Приховати контакти не в мережі -service.gui.HIDE_MAIN_WINDOW=
    Натиснення хрестика у куті вікна не завершить додаток, а тільки
    сховає его. Якщо бажаєте завершить додаток, оберіть Файл/Вийти.
    +service.gui.HIDE_MAIN_WINDOW=
    Натиснення хрестика у куті вікна не завершить додаток, а тільки
    сховає його. Якщо бажаєте завершить додаток, оберіть Файл/Вийти.
    service.gui.HISTORY=&Історія service.gui.HISTORY_CONTACT=Історія - {0} service.gui.HISTORY_TOGGLE_PER_CONTACT=Вимкнути історію для цього контакту @@ -285,12 +276,12 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Ви дійсно бажаєте наза service.gui.HISTORY_REMOVE_ERROR=Помилка під час видалення локально збережених повідомлень. service.gui.HOME=Домашній service.gui.HOME_PAGE=Домашня сторінка -service.gui.HOUR=Домашня сторінка service.gui.ICE=ICE service.gui.IDENTIFIER=Ідентифікатор service.gui.IGNORE=&Ігнорувати service.gui.INSERT_SMILEY=Вставити смайлик service.gui.INCOMING_CALL=Вхідний дзвінок від: {0} +service.gui.INCOMING_SCREEN_SHARE=Вхідний дзвінок від: {0} service.gui.INCOMING_CALL_STATUS=Вхідний дзвінок service.gui.INITIATING_CALL_STATUS=Здійснення виклику service.gui.INVITATION=Текст запрошення @@ -305,23 +296,21 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Запитити контакти д service.gui.INVITE_REASON=Причина запрошення service.gui.IS_CALLING=дзвонить... service.gui.IS_NOW={0} тепер {1} -service.gui.JITSI_WARNING=SIP Communicator був перейменований в Jitsi.
    Завантажуйте Jitsi, якщо Ви хочете використовувати нову версію програми.

    Прийміть наші вибачення за можливі завдані ненезручності. З повагою,

    Команда розробників Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator тепер став Jitsi service.gui.JOIN=&Війти service.gui.JOIN_AS=В&ійти як -service.gui.CLOSE_CHAT_ROOM_DIALOG=З&акрити +service.gui.JOIN_VIDEO=Приєднатися до відео +service.gui.JOB_TITLE=Посада service.gui.JOIN_CHAT_ROOM=&Ввійти в конференцію... service.gui.JOIN_CHAT_ROOM_TITLE=Ввійти в конференцію service.gui.JOIN_CHAT_ROOM_NAME=Будь-ласка, введіть ім’я конференції, в яку хочете ввійти. service.gui.JOIN_CHAT_ROOM_WIZARD=Майстер приєднання до конференції -service.gui.JOIN_AUTOMATICALLY=Приєднати автоматично -service.gui.DONT_JOIN_AUTOMATICALLY=Не приєднувати автоматично +service.gui.JOIN_AUTOMATICALLY=Приєднуватись автоматично +service.gui.DONT_JOIN_AUTOMATICALLY=Не приєднуватись автоматично service.gui.KICK=&Усунути service.gui.KICK_FAILED=Не вдалося усунути service.gui.KICK_FAILED_GENERAL_ERROR=Не вдалося усунути {0}. Відбулася загальна помилка сервера. service.gui.KICK_FAILED_NOT_ALLOWED=Не вдалося усунути {0}. Власник та адміністратор конференції не може бути усунутий. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Не вдалося усунути {0}. У вас немає на це прав. -service.gui.LAST=Останній service.gui.LAST_NAME=Прізвище: service.gui.LEAVE=&Покинути service.gui.LIMIT_REACHED_FOR_IP=У вас надто багато реєстрацій з локальної IP-адреси. Сервер {0} більше не дозволяє реєстрування. @@ -341,7 +330,6 @@ service.gui.MESSAGE=Повідомлення service.gui.MISSED_CALLS_TOOL_TIP=Пропущені виклики від: service.gui.MISSED_CALLS_MORE_TOOL_TIP= та {0} більше service.gui.MODERATOR=модератор -service.gui.MORE=Переглянути більше service.gui.MORE_LABEL=Більше service.gui.MOVE=Перемістити service.gui.MOVE_SUBCONTACT=П&еремістити контакт @@ -350,7 +338,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Вибраний вами контакт то service.gui.MOVE_SUBCONTACT_QUESTION=Ви впевнені, що бажаєте перемістити {0} до {1}? service.gui.MOVE_TO_GROUP=&Перемістити в групу service.gui.MOVE_CONTACT=Перемістити контакт -service.gui.MOVE_CONTACT_ERROR=&Контакт не може бути переміщений service.gui.MSG_DELIVERY_FAILURE=Попереднє повідомлення не може бути доставлено service.gui.MSG_DELIVERY_NOT_SUPPORTED=Протокол, який ви використовуєте підтримує offline-повідомлення. Ви можее спробувати зв’язатися з {0} через інший протокол або зачекати доки він/вона подключіться до мережі. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Відбулася внутрішня помилка додатку. Будьласка, повідомте про неї на адресу: http://www.jitsi.org/index.php/Development/BugsAndIssues. @@ -361,7 +348,6 @@ service.gui.MSG_NOT_POSSIBLE=Обмін повідомленнями немож service.gui.MSG_RECEIVED={0} написав service.gui.MSG_SEND_CONNECTION_PROBLEM=Ви повинні бути підключені до мережі, щоб мати можливість відправлять повідомлення. service.gui.MULTIPLE_LOGINS=Ви підключені більше одного разу тим же обліковим записом. Наступний обліковий запис: Ім’я користувача: {0}, Назва сервера: {1} на даний час відключений. -service.gui.MUTE=Вимкнути звук service.gui.MUTUALLY_ON_HOLD_STATUS=Чекає service.gui.NAME=Дія service.gui.NETWORK=Мережа @@ -392,7 +378,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Не в списку контакті service.gui.SD_QUALITY=Стандартна якість service.gui.OFFLINE=Не в мережі service.gui.OK=&OK -service.gui.OLDER_CALLS=Старі дзвінки service.gui.ONLINE=В мережі service.gui.OPEN=Відкрити service.gui.OPEN_FILE_FROM_IMAGE=Двічі клацніть, щоб відкрити файл. @@ -400,7 +385,6 @@ service.gui.OPEN_FOLDER=Відкрити теку service.gui.OPEN_IN_BROWSER=Відкрити в &браузері service.gui.OPTIONS=Опції service.gui.OR=або -service.gui.OR_ENTER_PHONE_NUMBER=Або введіть номер телефону... service.gui.ORGANIZATION=Організація: service.gui.OTHER=Інший service.gui.chat.role.OWNER=Власник @@ -424,7 +408,6 @@ service.gui.PRESENCE=Вітання service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' для пропозицій service.gui.PRESS_FOR_CALL_INFO=Натисніть для отримання інформації про дзвінок service.gui.PREVIOUS=Попередній -service.gui.PREVIOUS_TOOLTIP=Огляд старих розмов service.gui.PRINT=&Друк service.gui.PROACTIVE_NOTIFICATION=Друкує повідомлення service.gui.PROBLEMS_ENCOUNTERED=Виникли проблеми @@ -439,7 +422,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Ви були відключені та service.gui.RE_REQUEST_AUTHORIZATION=Запит повторної авторизації service.gui.REFERRED_STATUS=Переведений service.gui.REJECT=&Відхилити -service.gui.REMIND_ME_LATER=Нагадати мені пізніше service.gui.REMEMBER_PASSWORD=Запам’ятати пароль service.gui.REMOVE=&Вилучити service.gui.REMOVE_ACCOUNT=&Вилучити обліковий запис @@ -465,9 +447,7 @@ service.gui.REVOKE_ADMIN=Вилучити із адміністраторів service.gui.REVOKE_MODERATOR=Вилучити із модераторів service.gui.REVOKE_MEMBERSHIP=Анулювати членство service.gui.REVOKE_VOICE=Вилучити із голосування -service.gui.ROOT_GROUP=Коренева група service.gui.SAVE=&Зберегти -service.gui.SAVE_AS_DEFAULT=Зберегти замовчувані service.gui.SEARCH=&Пошук service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Натисніть кнопку ниже, щоб показати всі чати, існуючі на вибраному сервері. Потім оберіть той, до якого хочете приєднатися та натисніть на кнопку з’єднання. service.gui.SEARCH_STRING_CONTACT_SOURCE=Пошук контактів @@ -475,17 +455,11 @@ service.gui.SECURITY=Безпека service.gui.SELECT_ACCOUNT=Вибрати обліковий запис service.gui.SELECT_COLOR=Вибрати колір service.gui.SELECT_GROUP=Вибрати групу -service.gui.SELECT_GROUP_WIZARD_MSG=Наведений нижче список містить всі групи у списку контактів. Виберіть одну, до якої хочете додати новий контакт. service.gui.SELECT_NO_GROUP=Без групи -service.gui.SELECT_GROUP_WIZARD=Вкажіть групу service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Наведений нижче список містить всі облікові записи, які підтримують багатокористувацький чат. Виберіть той, який хочете використовувати для створення конференції. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Наведений нижче перелік містить всі зареєстровані облікові записи. Виберіть той, який хочете використовувати для спілкування з новим контактом. -service.gui.SELECT_PROVIDERS_WIZARD=Виберіть обліковий запис service.gui.SEND=&Надіслати service.gui.SEND_FILE=Надіслати &файл -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Інформація про цей контакт відсутня. service.gui.SEND_MESSAGE=&Надіслати повідомлення -service.gui.SEND_AS_SMS=Надіслати як SMS service.gui.SEND_SMS=Надіслати SMS service.gui.SEND_SMS_DETAILS=Пам’ятайте, що вам необхідно ввести номер телефону в міжнародном форматі, наприклад, починаючи з +380 для України, +380112233445 service.gui.SEND_SMS_NOT_SUPPORTED=Вибраний протокол не підтримує SMS повідомлень. @@ -519,7 +493,6 @@ service.gui.STOP_SHARING=Припинити загальний доступ service.gui.SUBJECT=Тема service.gui.SUMMARY=Зведення service.gui.TELEPHONY=Телефонія -service.gui.TODAY=Сьогодні service.gui.TOOLS=&Інструменти service.gui.TRANSFER=Передавання service.gui.TO=&Кому: @@ -529,7 +502,6 @@ service.gui.TRANSFER_CALL_TO=Переведення на: service.gui.TRANSPARENCY_NOT_ENABLED=Прозорість не підтримується поточною конфігурацією. service.gui.TYPE_YOUR_REQUEST=Введіть запит service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Не вдалося змінити якість відео для цього виклику. -service.gui.UNMUTE=Увімкнути звук service.gui.USER_IDENTIFIER=Ідентифікатор користувача: service.gui.USER_EXISTS_ERROR=Цей користувач вже існує у вибраній мережі. Будь-ласка, оберіть іншого користувача або мережу. service.gui.USERNAME_NULL=Будь-ласка, заповніть своє ім’я користувача та пароль. @@ -541,7 +513,6 @@ service.gui.USE_PROVISIONING=Використовувати автоналашт service.gui.VALUE=Значення: service.gui.VIDEO_CALL=&Відеовиклик service.gui.VIA=через -service.gui.VIA_SMS=Через SMS service.gui.VIEW=&Показати service.gui.VIEW_HISTORY=Показати &історію service.gui.VIEW_SMILEYS=Показати &смайли @@ -561,9 +532,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Регулювання гучності service.gui.WAITING_AUTHORIZATION=Чекаємо авторизації service.gui.WARNING=Попередження service.gui.YES=Так -service.gui.YESTERDAY=Вчора -service.gui.EXISTING_ACCOUNT_ERROR=Введенний обліковий запис вже існує. -service.gui.NEW_MAIL=У Вас один новий лист!
    От: {0} {1}
    Тема: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Ви відримали нового листа до {0} вхідні:
    service.gui.NEW_GMAIL_MANY_HEADER=Ви відримали {2} нових листів до {0} вхідні:
    service.gui.NEW_GMAIL_FOOTER=ще одине непрочитане повідомлення увхідних.
    @@ -586,7 +554,6 @@ service.gui.SECURITY_ERROR=Помилка безпеки service.gui.SPEED=Швидкість: service.gui.SILENT_MEMBER=мовчазний участник service.gui.NON_SECURE_CONNECTION=Неможливо встановити безпечне з’єднання для {0}. Якщо Ви хочете використовувати незахищене підключення, Будь-ласка, встановіть ознаку "Дозволити незахищене з’єднання" в конфігурації облікового запису -service.gui.UPDATE=Оновити service.gui.MOBILE_PHONE=Мобільний service.gui.VIDEO_PHONE=Відеовиклики service.gui.WORK_PHONE=Робочий @@ -619,7 +586,6 @@ service.gui.callinfo.CALL_INFORMATION=Інформація про виклик service.gui.callinfo.CALL_IDENTITY=Обліковий запис service.gui.callinfo.PEER_COUNT=Кількість учасників service.gui.callinfo.IS_CONFERENCE_FOCUS=Конференція -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Шифрування увімкнено service.gui.callinfo.CALL_TRANSPORT=Транспорт сигналізації service.gui.callinfo.CALL_DURATION=Тривалість виклику service.gui.callinfo.VIEW_CERTIFICATE=Показати сертифікат @@ -630,7 +596,6 @@ service.gui.callinfo.AUDIO_INFO=Аудіо потік service.gui.callinfo.VIDEO_INFO=Відео потік service.gui.callinfo.LOCAL_IP=Локальний IP / Порт service.gui.callinfo.REMOTE_IP=Віддалений IP / Порт -service.gui.callinfo.BANDWITH=Смуга пропускання service.gui.callinfo.LOSS_RATE=Втрата пакетів service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Джіттер @@ -640,10 +605,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Протокол обміну ключами service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE кандидат розширеного типу service.gui.callinfo.ICE_STATE=Стан ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Отримання кандидатів service.gui.callinfo.ICE_STATE.RUNNING=Перевірка підключення service.gui.callinfo.ICE_STATE.COMPLETED=Завершено service.gui.callinfo.ICE_STATE.FAILED=Помилка + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Локальний IP / Порт service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Локальний вхідний IP / Порт service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Локальний вихідний IP / Порт @@ -662,9 +630,10 @@ service.gui.ALWAYS_TRUST=Завжди довіряти цьому сертифі service.gui.CERT_DIALOG_TITLE=Перевірити сертифікат service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} не може перевірити достовірність сервера при підключенні до
    {1}.

    Не довірений сертифікат. Це означає, що сервер не може бути автоматично перевірений.

    Для отримання додаткової інформації, натисніть кнопку "Показати сертифікат".

    Ви хочете продовжити підключення? service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} не може перевірити достовірність сертифіката сервера

    Не довірений сертифікат. Це означає, що сервер не може бути автоматично перевірений.

    Для отримання додаткової інформації, натисніть кнопку "Показати сертифікат".

    Ви хочете продовжити підключення? -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} не може перевірити достовірність клієнта

    Не довірений сертифікат. Це означає, що клієнт не може бути автоматично перевірений.

    Для отримання додаткової інформації, натисніть кнопку "Показати сертифікат".

    Ви хочете дозволити підключення? service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} не може перевірити достовірність клієнта {1}

    Не довірений сертифікат. Це означає, що клієнт не може бути автоматично перевірений.

    Для отримання додаткової інформації, натисніть кнопку "Показати сертифікат".

    Ви хочете продовжити підключення? service.gui.CONTINUE_ANYWAY=Однак продовжити + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Назва сертифіката: service.gui.CERT_INFO_O=Організація: service.gui.CERT_INFO_C=Країна: @@ -679,12 +648,10 @@ service.gui.CERT_INFO_VER=Версія: service.gui.CERT_INFO_SIGN_ALG=Алгоритм підпису: service.gui.CERT_INFO_ALG=Алгоритм: service.gui.CERT_INFO_PUB_KEY=Відкритий ключ: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} байт: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} біт service.gui.CERT_INFO_EXP=Експонента: service.gui.CERT_INFO_KEY_SIZE=Розмір ключа: service.gui.CERT_INFO_SIGN=Підпис: -service.gui.CONTINUE=Продовжити service.gui.SHOW_CERT=Показати сертифікат service.gui.HIDE_CERT=Приховати сертифікат @@ -705,15 +672,12 @@ service.gui.security.SECURE_AUDIO=Аудіопотік захищено service.gui.security.AUDIO_NOT_SECURED=Аудіопотік не захищено service.gui.security.SECURE_VIDEO=Відеопотік захищено service.gui.security.VIDEO_NOT_SECURED=Відеопотік не захищено -service.gui.security.NO_VIDEO=Без відео -service.gui.security.CIPHER=Шифр: {0} service.gui.security.CALL_SECURED_TOOLTIP=Розмову захищено. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Розмову не захищено. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Натисніть тут, щоб звірити ключ із співрозмовником. -service.gui.security.COMPARE_WITH_PARTNER=Звірте ключ із співрозмовником та натисніть замочок для підтвердження. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Звірте ключ із співрозмовником: -service.gui.security.STRING_COMPARED=Ключ пошкоджено! +service.gui.security.STRING_COMPARED=Ключ перевірено! service.gui.security.SECURITY_ALERT=Ініціалізування захисту виклику. Відключення через service.gui.avatar.CHOOSE_ICON=Вибрати аватар @@ -727,19 +691,13 @@ service.gui.avatar.imagepicker.CLICK=Зробити знімок service.gui.avatar.imagepicker.IMAGE_FILES=Файли зображень service.gui.avatar.imagepicker.IMAGE_PICKER=Зображення service.gui.avatar.imagepicker.IMAGE_SIZE=Розмір зображення -service.gui.avatar.imagepicker.INITIALIZING=Ініціалізування service.gui.avatar.imagepicker.RESET=Скинути service.gui.avatar.imagepicker.SET=Задати service.gui.avatar.imagepicker.TAKE_PHOTO=Зробити знімок -service.gui.avatar.imagepicker.WEBCAM_ERROR=Помилка вебкамери service.gui.security.encryption.required=Необхідне шифрування! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Помилка в адресній книзі SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Неможливо прочитати ресурс {0}. Для {1} @@ -762,9 +720,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=Оберіть мережу # LDAP impl.ldap.CONFIG_FORM_TITLE=Налаштування LDAP impl.ldap.GENERAL=Загальні -impl.ldap.NEW=Новий impl.ldap.EDIT=змінити -impl.ldap.REMOVE=Вилучити impl.ldap.ENABLED=Активний impl.ldap.SERVER_NAME=Коротке ім’я impl.ldap.SERVER_NAME_EXAMPLE=Адресна книга LDAP @@ -797,6 +753,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Телефонний префікс impl.ldap.PHONE_PREFIX_EXAMPLE=Наприклад: +380 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Адресна книга plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Увімкнути пошук в адресній книзі MacOSX @@ -807,9 +767,7 @@ plugin.addrbook.PREFIX_EXAMPLE=Наприклад: +380 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Контакти Google -impl.googlecontacts.NEW=Новий impl.googlecontacts.EDIT=Змінити -impl.googlecontacts.REMOVE=Вилучити impl.googlecontacts.ENABLED=Активний impl.googlecontacts.ACCOUNT_NAME=Обліковий запис impl.googlecontacts.SAVE=Зберегти @@ -837,9 +795,6 @@ plugin.accountinfo.COUNTRY=Країна plugin.accountinfo.EMAIL=Електронна скринька: plugin.accountinfo.PHONE=Телефон: plugin.accountinfo.MOBILE_PHONE=mobilePhone -plugin.accountinfo.USER_PICTURES=Фотографії користувача -plugin.accountinfo.CHANGE=Змінити -plugin.accountinfo.ONLY_MESSAGE=Тільки повідомлення # connection info @@ -858,49 +813,12 @@ plugin.aimaccregwizz.USERNAME=AIM Ім’я: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Ідентифікатор користувача та пароль plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Реєстрування нового облікового запису plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=У випадку, якщо ви не маєте облікового запису AIM, натисніть на цю кнопку, щоб створити новий. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Перевизначити замовчувані параметри сервера # branding plugin.branding.ABOUT_WINDOW_TITLE=Про нас {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Обмін миттєвими повідомленнями -plugin.branding.LOADING=Завантаження plugin.branding.ABOUT_MENU_ENTRY=&Про програму -plugin.branding.WELCOME_MESSAGE=
    {1} наразі в стадії активної розробки. Версія, запущена вами, експеріментальна та може працювати не так как ви чекаєте. Будь-ласка, зверніться до {2} для отримання додаткової інформації.
    -plugin.branding.COPYRIGHT=
    (c)2003-2012 Copyright jitsi.org. Всі права захищено. Відвідайте http://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi пиширюється за ліцензією LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Словники -plugin.dictaccregwizz.ANY_DICTIONARY=Будь-який словник -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Будь-який словник від {0} -plugin.dictaccregwizz.FIRST_MATCH=Перший збіг -plugin.dictaccregwizz.NO_MATCH=Збіги відсутні -plugin.dictaccregwizz.MATCH_RESULT=Визначень для "{0}" не знайдено, можливо, ви маєте на увазі:\n -plugin.dictaccregwizz.INVALID_DATABASE=Поточного словника "{0}" не існує на сервері. -plugin.dictaccregwizz.INVALID_STRATEGY=Поточна стратегия відсутня на сервері. -plugin.dictaccregwizz.PROTOCOL_NAME=DICT -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=DICT протокол -plugin.dictaccregwizz.HOST=Хост -plugin.dictaccregwizz.SERVER_INFO=Інформація про сервер -plugin.dictaccregwizz.STRATEGY_SELECTION=Вибір методу -plugin.dictaccregwizz.STRATEGY_LIST=Список методів: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Пошук методів -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Використовувати метод для пошуку схожих слів, якщо переклад не був знайдений, завдяки різним методам. Наприклад, номери стратегії буде шукати слова, які починаються, как слово, яке бажано перкласти. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Інформація про обліковий запис -plugin.dictaccregwizz.FIRST_ACCOUNT=Цей мастер допоможе створити ваш перший обліковий запис на сайте dict.org.\n\nВи можете додати новий словник зареєструвавши обліковий запис у майстрі. Заповніть поля словника який ви хочете додати. -plugin.dictaccregwizz.THREAD_CONNECT=Спроба підключення до серверу -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Спроба підключення не вдалася, це не сервер словників або сервер недоступний -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Отримання метода -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Метод не знайдено на сервері -plugin.dictaccregwizz.POPULATE_LIST=Заповнення списку -plugin.dictaccregwizz.CLOSING_CONNECTION=Закриття з’єднання - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Для того, щоб використовувати Facebook чат необхідно створити "Обліковий запис користувача"
    в "Налаштуваннях облікового запису " на Facebook.


    Примітка: При створенні імені користувача необхідно вийти із сторінки
    і може знадобитися деякий час, пред тим як ви зможете війти з вашим новим іменем користувача!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Протокол чату Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Ім’я користувача: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Ім’я користувача та пароль + # generalconfig plugin.generalconfig.AUTO_START=Автоматичний запуск {0} при завантаженні компьютера @@ -910,9 +828,6 @@ plugin.generalconfig.SHOW_HISTORY=Показувати plugin.generalconfig.HISTORY_SIZE=останніх повідомлень в новому чаті plugin.generalconfig.SEND_MESSAGES_WITH=Надсилати повідомлення при натисненні: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Переносити вікно чату поверх всіх вікон при вхідному повідомленні -plugin.generalconfig.ERROR_PERMISSION=У вас немає достатніх привілеїв для відключения автозапуску -plugin.generalconfig.TRANSPARENCY=Прозорість -plugin.generalconfig.ENABLE_TRANSPARENCY=Увімкнути прозорість plugin.generalconfig.DEFAULT_LANGUAGE=Мова інтерфейсу plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Зміни будуть застосовані після наступного запуску Jitsi. plugin.generalconfig.SIP_CLIENT_PORT=Порт SIP @@ -961,6 +876,8 @@ plugin.ircaccregwizz.USE_DEFAULT_PORT=Використовувати замов plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=Мій псевдонім не вимагає ідентифікації plugin.ircaccregwizz.HOST=Хост: plugin.ircaccregwizz.IRC_SERVER=Сервер +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=Ідентифікація {0} +plugin.ircaccregwizz.SASL_USERNAME=Ім’я користувача # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP @@ -983,13 +900,10 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Коментар plugin.jabberaccregwizz.RESOURCE=Ресурс plugin.jabberaccregwizz.AUTORESOURCE=Автоматичне створення ресурсу plugin.jabberaccregwizz.PRIORITY=Приорітет -plugin.jabberaccregwizz.XMPP_ERROR=Помилка XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Невідома помилка XMPP. Упевніться, що назва сервера, правильна. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Паролі не співпадають. plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Перевизначити параметри замовчувані сервера -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Додаткові параметри plugin.jabberaccregwizz.USE_ICE=Використовувати ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Використовувати Google Jingle/ICE (експеріментальна функція) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Автоматично знаходити STUN/TURN сервери plugin.jabberaccregwizz.SUPPORT_TURN=Підтримувати TURN plugin.jabberaccregwizz.TURN_USERNAME=Ім’я користувача TURN @@ -1016,11 +930,8 @@ plugin.jabberaccregwizz.ALLOW_NON_SECURE=Дозволити небезпечні plugin.jabberaccregwizz.DTMF_AUTO=Автоматично вибирати між RTP та Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Параметри сервера plugin.jabberaccregwizz.CHANGE_PASSWORD=Змінити пароль -plugin.jabberaccregwizz.NEW_PASSWORD=Новий пароль -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Повторіть пароль plugin.jabberaccregwizz.PORT_FIELD_INVALID=Будь-ласка, необхідно вказати вірний порт для продовження. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Щоб змінити пароль необхідно війти на сервер. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Пароль порожній. plugin.jabberaccregwizz.TLS_REQUIRED=З’єднання не зашифрівано! Пароль не буде змінено. plugin.jabberaccregwizz.PASSWORD_CHANGED=Пароль успішно змінено plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Ваш сервер не підтримує заміну пароля. @@ -1034,21 +945,6 @@ plugin.jabberaccregwizz.RESET=Скинути plugin.jabberaccregwizz.RESET_DESCRIPTION=Скинути до глобальнхе налаштуваннь plugin.jabberaccregwizz.DISABLE_JINGLE=Вимкнути Jingle (ауіио та відеодзвінки через XMPP). -# mailbox -plugin.mailbox.OUTGOING=Вихідні повідомлення: -plugin.mailbox.INCOMING=Вхідні повідомлення: -plugin.mailbox.WAIT_TIME=Дзвінок переводиться на автоовідповідач -plugin.mailbox.MAX_MESSAGE_TIME=Максимальна тривалість вхідних повідомлень -plugin.mailbox.CONFIRM=Підтвердити -plugin.mailbox.DEFAULTS=За замовчуванням -plugin.mailbox.MAILBOX=Поштова скринька - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Протокол для підключення та чату на MSN службі. -plugin.msnaccregwizz.USERNAME=Електронна скринька: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID та пароль - # plugin manager plugin.pluginmanager.INSTALL=Встановити plugin.pluginmanager.UNINSTALL=Вилучити @@ -1077,7 +973,6 @@ plugin.sipaccregwizz.SERVER_PORT=Порт сервера plugin.sipaccregwizz.PROXY=Проксі plugin.sipaccregwizz.PROXY_PORT=Порт проксі plugin.sipaccregwizz.PREFERRED_TRANSPORT=Надавати перевагу транспорту -plugin.sipaccregwizz.ADVANCED_OPTIONS=Додаткові параметри plugin.sipaccregwizz.PROXY_OPTIONS=Налаштування проксі-сервера plugin.sipaccregwizz.PROXY_AUTO=Автоматичне налаштування проксі-сервера plugin.sipaccregwizz.ENABLE_PRESENCE=Увімкнути присутність (SIMPLE) @@ -1094,8 +989,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Автоматично вибирати між RT plugin.sipaccregwizz.DTMF_RTP=RTP (RFC2833 / RFC4733) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Перевизначити замовчувані параметри сервера plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Увімкнути підтримку шифрування дзвінків plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Повідомляти про підтримку ZRTP у протоколі сигналізації plugin.sipaccregwizz.AUTH_NAME=Ім’я для авторизації @@ -1116,10 +1009,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI для перевірки ГП plugin.sipaccregwizz.NOT_SAME_PASSWORD=Паролі не співпадають. plugin.sipaccregwizz.NO_CERTIFICATE=<не> (використовувати звичайну перевірку справжності) plugin.sipaccregwizz.SAVP_OPTION=Використання RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Вимкнено (використовувати тільки RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Обов’язково (пропонувати та приймати тільки RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Додатково (спочатку пропонувати RTP/SAVP, потім RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Увімкнути S-дескриптор (також відомий як SDES або SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Виберіть протоколи шифрування та їхній пріоритет (вгорі протокол з вищим пріоритетом): plugin.sipaccregwizz.CIPHER_SUITES=Доступні набори шифрів: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} намагатиметься автоматично захистити всі Ваши дзвінки за допомогою ZRTP. Ви будете поінформовані про це кожного разу, здійснюючи виклик. Ви можете змінювати додаткові налаштування тільки в тому випадку, якщо добре розумієте, що робите.
    @@ -1133,15 +1026,6 @@ plugin.skinmanager.DEFAULT_SKIN=Скіни замовчувані plugin.skinmanager.ADD_NEW_SKIN=Додати новий скін... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Скини додатку замовчувані. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Протокол для підключення до віддаленого комп’ютера через SSH. -plugin.sshaccregwizz.USERNAME=ID облікового запису: -plugin.sshaccregwizz.IDENTITY_FILE=Особистий файл: -plugin.sshaccregwizz.KNOWN_HOSTS=Відомі хости: -plugin.sshaccregwizz.OPTIONAL=Необов’язковий -plugin.sshaccregwizz.ACCOUNT_DETAILS=Інформація про обліковий запис - # status update plugin.autoaway.AUTO_STATUS=Авто відсутність plugin.autoaway.ENABLE_CHANGE_STATUS=Змінити статус, коли відійшов @@ -1188,22 +1072,6 @@ plugin.whiteboard.DESELECT=Відмінити plugin.whiteboard.DELETE=Вилучити plugin.whiteboard.PROPERTIES=Властивості -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Протокол Yahoo. -plugin.yahooaccregwizz.USERNAME=Ім’я користувача: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID та пароль - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Zeroconf (Bonjour) протокол. -plugin.zeroaccregwizz.FIRST_NAME=Ім’я: -plugin.zeroaccregwizz.LAST_NAME=Прізвище: -plugin.zeroaccregwizz.EMAIL=Електронна скринька: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Запам’ятати Bonjour контакти? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID та пароль -plugin.zeroaccregwizz.USERID=Ідентифікатор користувача - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Протокол Google Talk @@ -1217,19 +1085,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, портал IP Теле plugin.iptelaccregwizz.USERNAME=Ім’я користувача plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Підписатися на iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP та чат +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Ім’я користувача plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Введіть пароль еще раз plugin.sip2sipaccregwizz.EMAIL=Адреса електронної пошти -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Для отримання довідки про послугу відвідайте
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Адреса електронної пошти використовується для відправки голосових повідомлень,
    інформувань про пропущені дзвінки, а також відновлення втраченого паролю -plugin.sip2sipaccregwizz.INFO_NOTE=Для отримання довідки про послугу відвідайтеhttp://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Існуючий sip2sip.info обліковий запис -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Створити безкоштовний обліковий запис sip2sip.info - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Миттєві повідомлення plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Для отримання довідки про послугу відвідайте
    http://ippi.fr @@ -1238,6 +1098,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Існуючі ippi обліковий з plugin.ippiaccregwizz.CREATE_ACCOUNT=Створити безкоштовний обліковий запис ippi # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Закрити вікно чату plugin.keybindings.CHAT_COPY=Копіювати plugin.keybindings.CHAT_CUT=Вирізати @@ -1260,9 +1121,9 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Дія plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Поєднання клавіш plugin.keybindings.globalchooser.SHORTCUT_SECOND=Додатково plugin.keybindings.globalchooser.PRESS_BTN=Натисніть для визначення поєдняння клавіш -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Чекання plugin.keybindings.globalchooser.ENABLE_SPECIAL=Увімкнути виявлення спеціальних клавіш plugin.keybindings.PLUGIN_NAME=Поєднання клавіш +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Чат plugin.keybindings.MAIN=Основні plugin.keybindings.GLOBAL=Глобальні @@ -1290,6 +1151,7 @@ plugin.notificationconfig.tableheader.SOUND=Системний звуковий plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Звуковий сигнал через динаміки plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Звуковий сигнал через динамік ПК plugin.notificationconfig.tableheader.DESCRIPTION=Опис події +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Вхідний дзвінок plugin.notificationconfig.event.SecurityMessage=Повідомлення безпеки plugin.notificationconfig.event.IncomingFile=Отримано файл @@ -1380,6 +1242,7 @@ impl.neomedia.configform.VIDEO=Відео impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultProfile=Профіль для кодування: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Базовий impl.neomedia.configform.H264.defaultProfile.main=Основний impl.neomedia.configform.H264.preferredKeyFrameRequester=Метод запиту ключових кадрів: @@ -1407,7 +1270,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Поточний паро plugin.securityconfig.masterpassword.ENTER_PASSWORD=Введіть новий пароль: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Введіть пароль повторно: plugin.securityconfig.masterpassword.MP_TITLE=Майстер-пароль -plugin.securityconfig.masterpassword.MP_NOT_SET=(не встановлено) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Ви ввели неправильний поточний Майстер-пароль. Будь-ласка, спробуйте еще раз. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Майстер-пароль неправильний! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Замінити пароль не вдалося @@ -1486,7 +1348,6 @@ plugin.globalproxy.PROXY_PORT=Порт plugin.globalproxy.PROXY_USERNAME=Ім’я користувача plugin.globalproxy.PROXY_PASSWORD=Пароль plugin.globalproxy.DESCRIPTION={0} буде використовувати перелічені параметри проксі-сервера для всіх мереж при наступному підключенні. \nПідтримка проксі в даний час експеріментальна та працює тільки з деякими протоколами. Дивіться таблицю нижче для більш докладної інформації: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOCKS4/5SOCKS4/5+AuthHTTPHTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1520,7 +1381,6 @@ plugin.provisioning.RESTART_WARNING=Зміни вступлять в силу т plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Скопіювати UUID до буфера plugin.provisioning.CLIPBOARD_FAILED=Помилка копіювання UUID до буфера -plugin.provisioning.EXIT_ON_FAIL=Закривати Jitsi, якщо автоналаштування не виконано plugin.provisioning.CREDENTIALS=Обліковий запис для автоналаштування plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Ви дійсно хочете скинути пароль для автоналаштування? plugin.provisioning.PROV_FAILED=Автоналаштування не вдале @@ -1587,8 +1447,6 @@ util.dns.DNSSEC_WARNING=
    {0} намагався підкл #plugin spellcheck plugin.spellcheck.TITLE=Орфографія та Граматика plugin.spellcheck.MENU=Відкрити словник -plugin.spellcheck.LANG=Мова -plugin.spellcheck.EDIT_PERSONAL_DICT=Правка plugin.spellcheck.ENABLE_SPELL_CHECK=Перевірка правопису plugin.spellcheck.dialog.FIND=Знайти наступне plugin.spellcheck.dialog.REPLACE=Замінити -- cgit v1.1 From 1892a42965b793840dcf96bd8136ba8307cd449b Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:53:06 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1479 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_ru.properties | 213 ++++------------------------ 1 file changed, 28 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_ru.properties b/resources/languages/resources_ru.properties index 7021ad1..16b1206 100644 --- a/resources/languages/resources_ru.properties +++ b/resources/languages/resources_ru.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Я service.gui.ACCOUNT_REGISTRATION_WIZARD=Мастер регистрации учетных записей service.gui.ACCOUNTS=Учётные записи service.gui.ADD=&Добавить -service.gui.ADD_ACCOUNT=Добавить аккаунт service.gui.ADD_CONTACT=&Добавить контакт service.gui.ADD_AUTHORIZED_CONTACT=Добавить {0} в ваш список контактов service.gui.ADD_CONTACT_TO_CONTACTLIST=Добавить контакт в ваш список контактов @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Ошибка при добавлении к service.gui.ADD_CONTACT_EXIST_ERROR=Контакт {0} уже существует в списке контактов. service.gui.ADD_CONTACT_NETWORK_ERROR=Сервер не ответил на запрос добавления контакта: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Не удалось добавить контакт с идентификатором: {0}. Операция не поддерживается. -service.gui.ADD_CONTACT_IDENTIFIER=В поле ниже введите идентификатор контакта который вы желаете добавить. -service.gui.ADD_CONTACT_WIZARD=Мастер добавления контактов service.gui.ADD_CONTACT_NOT_CONNECTED=Вы должны быть подключены для того, чтобы добавить контакт. Пожалуйста, выполните вход и попробуйте снова. service.gui.ADD_GROUP_LOCAL_ERROR=Не удалось добавить группу с именем: {0}. Произошёл сбой во время операции ввода-вывода. service.gui.ADD_GROUP_EXIST_ERROR=Группа {0} уже существует в списке контактов. Пожалуйста, выберите другое имя. service.gui.ADD_GROUP_NET_ERROR=Не удалось добавить группу с именем: {0}. Сбой произошёл по причине отказа сети. Пожалуйста, проверьте ваше сетевое подключение и попробуйте снова. service.gui.ADD_GROUP_ERROR=Не удалось добавить группу: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Имя группы не может быть пустым. -service.gui.ADD_GROUP=Создать группу -service.gui.ADD_SUBCONTACT=&Добавить дополнительный контакт service.gui.ADDRESS=Адрес service.gui.ADMINISTRATOR=администратор service.gui.ADVANCED=&Расширенные -service.gui.ALL=&Все service.gui.ALL_CONTACTS=&Все контакты service.gui.ALTERNATE_ADDRESS=Альтернативный адрес service.gui.APPLY=&Применить @@ -65,7 +70,6 @@ service.gui.AT=время service.gui.AUTHORIZE=&Авторизовать service.gui.AUTHORIZATION_ACCEPTED={0} собеседник принял запрос на авторизацию. service.gui.AUTHENTICATION_FAILED=Проверка подлинности для {0} не удалась. Введённый вами пароль неверен. -service.gui.AUTHENTICATION_REQUESTED=Запрошена проверка подлинности service.gui.AUTHENTICATION_REQUESTED_SERVER=Сервер {0} запросил проверку подлинности. service.gui.AUTHENTICATION_REJECTED={0} собеседник отверг запрос на авторизацию. service.gui.AUTHENTICATION_WINDOW_TITLE={0} авторизация @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=В поле ниже вы можете вве service.gui.CHANGE_NICKNAME_ERROR=Не удалось изменить ник service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Такое имя уже существует service.gui.CHANGE_VIDEO_QUALITY=Изменить качество передаваемого видео -service.gui.CHAT_CONFERENCE_LABEL=Конференция service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} конференция service.gui.CHAT_ROOM_ALREADY_JOINED=Конференция {0} уже подключена. service.gui.CHAT_ROOM_CONFIGURATION=Конфигурация комнаты {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=покинул {0} service.gui.CHAT_ROOM_USER_KICKED=был исключён из {0} service.gui.CHAT_ROOM_USER_QUIT=вышел из {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Отправка сообщения запрещена (голос отозван) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Сохраняет чат-комнату для последующего использования -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Удаляет выбранную комнату из списка сохранённых service.gui.CHAT_ROOM_NAME=Имя конференции service.gui.CLEAR_CUSTOM_MESSAGES=Очистка пользовательских сообщений service.gui.ROOM_NAME=Конференция -service.gui.AUTOJOIN=Автоматический вход service.gui.CHANGE_PASSWORD=Сменить пароль service.gui.CHAT_ROOM_NAME_INFO=В поле ниже введите имя конференции, которую хотите создать. service.gui.CHAT_ROOM_NOT_EXIST=Конференция {0} не была найдена на сервере {1}. Пожалуйста, проверьте правильность введённого имени. service.gui.CHAT_ROOM_NOT_CONNECTED=Вы должны быть зарегистрированы, чтобы иметь возможность присоединиться к конференции {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Вы должны быть подключены чтобы иметь возможность выйти из конференции. -service.gui.CHAT_ROOM_NOT_JOINED=Вы должны войти в конференцию, чтобы иметь возможность совершать какие-либо операции с ней. service.gui.CHAT_ROOM_OPTIONS=Настройки конференции service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Конференция {0} требует регистрации для входа. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Конференция {0} запросила пароль. @@ -151,22 +150,18 @@ service.gui.CLEAR=Очистить service.gui.CLOSE=За&крыть service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Вы получили новое сообщение менее, чем 2 секунды назад. Вы уверены, что желаете закрыть этот чат? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=У вас имеются активные передачи файлов. Вы уверенны, что желаете прервать их? -service.gui.CONFIRM=Подтвердить service.gui.CONNECTED_STATUS=Подключен service.gui.CONNECTING=Подключение... service.gui.CONNECTING_STATUS=Подключение service.gui.CONNECTING_EARLY_MEDIA_STATUS=Подключение* service.gui.CONNECTION=Соединение -service.gui.CONNECTION_FAILED_MSG=Не удалось соединение для следующего аккаунта: Имя пользователя: {0}, Имя сервера: {1}. Пожалуйста проверьте ваше сетевое подключение или свяжитесь с вашим сетевым администратором для дополнительной информации. service.gui.CONNECTION_EXPIRED_MSG=В данный момент вы отключены от сервера {0}. service.gui.CONTACT_NAME=ID или номер -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Выбранный контакт {0} не поддерживает голосовую связь. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Выбранный контакт {0} не поддерживает чат в конференции. service.gui.CONTACT_PAUSED_TYPING={0} перестал печатать сообщение service.gui.CONTACT_TYPING={0} печатает сообщение service.gui.CONTACT_TYPING_SEND_FAILED=ой-ой... мы не смогли сообщить {0} , что вы печатаете service.gui.CONTACT_INFO=&Контактная информация -service.gui.CONTACTLIST=Список контактов service.gui.CONTACTS=Контакты service.gui.COPY=&Копировать service.gui.COPY_LINK=Копировать &ссылку @@ -176,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Создать конференцию... service.gui.CREATE_CHAT_ROOM_ERROR=Не удалось создать конференцию {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Мастер создания конференций service.gui.CREATE_CONFERENCE_CALL=&Создать многопользовательский звонок... -service.gui.CREATE_CONFERENCE_CHAT=&Создать многопользовательский чат... service.gui.CREATE_GROUP=&Создать группу... service.gui.CREATE_GROUP_NAME=В поле ниже введите имя группы, которую вы хотите создать. -service.gui.CREATE_FIRST_GROUP_WIZARD=Ваш список контактов не содержит ни одной группы. Пожалуйста, сначала создайте группу (Файл/Создать группу). service.gui.CREATE_VIDEO_BRIDGE=Создать &видео-мост... service.gui.CREATE_VIDEO_BRIDGE_MENU=Создать &видеомост service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Создать/Присоединиться к видео конференции service.gui.CREATE_VIDEO_CONFERENCE=Создать новую видео конференцию для этой комнаты service.gui.CONTACT_INFO_NOT_SUPPORTED=Данный контакт не поддерживает сетевую контактную информацию service.gui.CUT=В&ырезать -service.gui.DATE=Дата service.gui.DELETE=Удалить service.gui.DENY=&Отклонить service.gui.DESKTOP_SHARING_WARNING=Вы уверены, что хотите предоставить доступ к вашему экрану?
    Нажатие OK позволит абонентам, участвующим в разговоре, видеть содержимое вашего экрана. @@ -197,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Отключено service.gui.DND_STATUS=Не беспокоить service.gui.DO_NOT_ASK_AGAIN=Не спрашивать снова service.gui.DO_NOT_SHOW_AGAIN=Не показывать это сообщение снова -service.gui.DOWNLOAD_NOW=&Загрузить сейчас service.gui.DRAG_FOR_SHARING=Переместите сюда для предоставления общего доступа... service.gui.DURATION=длительность service.gui.DESTROY_CHATROOM=Удалить комнату @@ -218,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=От {0} получено сообщение о service.gui.ESTIMATED_TIME=Приблизительное время: service.gui.EVENTS=События service.gui.EXIT=В&ыйти -service.gui.EXTENDED_CRITERIA=Расширенный критерий service.gui.GENERAL=Общие service.gui.GENERAL_ERROR=Общая ошибка service.gui.GROUP_NAME=Имя группы @@ -260,7 +250,6 @@ service.gui.FONT_ITALIC=Курсив service.gui.FONT_SIZE=Размер service.gui.FONT_STYLE=Стиль service.gui.FONT_UNDERLINE=Подчеркивание -service.gui.FROM={0} из {1} service.gui.GRANT_OWNERSHIP=Добавить к владельцам... service.gui.GRANT_ADMIN=Добавить к администраторам... service.gui.GRANT_MODERATOR=Добавить к модераторам @@ -286,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Действительно окончат service.gui.HISTORY_REMOVE_ERROR=Ошибка удаления локально сохраненных сообщений. service.gui.HOME=На главную service.gui.HOME_PAGE=Домашняя страница -service.gui.HOUR=Время service.gui.ICE=ICE service.gui.IDENTIFIER=Идентификатор service.gui.IGNORE=&Игнорировать @@ -310,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Пригласить контакты service.gui.INVITE_REASON=Причина приглашения service.gui.IS_CALLING={0} звонит... service.gui.IS_NOW={0} теперь {1} -service.gui.JITSI_WARNING=SIP Communicator был переименован в Jitsi.
    Если Вы хотите использовать новую версию программы, пожалуйста загружайте Jitsi.

    Приносим свои извинения за возможные причиненные неудобства.

    Команда разработчиков Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator теперь стал Jitsi service.gui.JOIN=&Войти service.gui.JOIN_AS=В&ойти как service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Подключиться к существующей видеоконференции service.gui.JOIN_VIDEO=Подключиться к видео -service.gui.CLOSE_CHAT_ROOM_DIALOG=З&акрыть service.gui.JOB_TITLE=Должность service.gui.JOIN_CHAT_ROOM=&Войти в конференцию... service.gui.JOIN_CHAT_ROOM_TITLE=Войти в конференцию @@ -329,7 +314,6 @@ service.gui.KICK_FAILED=Не удалось выгнать service.gui.KICK_FAILED_GENERAL_ERROR=Не удалось выгнать {0}. Произошла общая ошибка сервера. service.gui.KICK_FAILED_NOT_ALLOWED=Не удалось выгнать {0}. Владелец и администратор конференции не может быть выгнан. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Не удалось выгнать {0}. У вас нет на это прав. -service.gui.LAST=Последний service.gui.LAST_NAME=Фамилия service.gui.LEAVE=&Покинуть service.gui.LIMIT_REACHED_FOR_IP=У вас слишком много регистраций с локального IP адреса. Сервер {0} не позволяет больше регистраций. @@ -349,7 +333,6 @@ service.gui.MESSAGE=Сообщение service.gui.MISSED_CALLS_TOOL_TIP=Пропущенные вызовы от: service.gui.MISSED_CALLS_MORE_TOOL_TIP= и {0} больше service.gui.MODERATOR=модератор -service.gui.MORE=Посмотреть больше service.gui.MORE_LABEL=Еще service.gui.MOVE=Переместить service.gui.MOVE_SUBCONTACT=П&ереместить контакт @@ -358,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Контакт, который вы выбр service.gui.MOVE_SUBCONTACT_QUESTION=Вы уверенны, что желаете переместить {0} в {1}? service.gui.MOVE_TO_GROUP=&Переместить в группу service.gui.MOVE_CONTACT=Переместить контакт -service.gui.MOVE_CONTACT_ERROR=&Контакт не может быть перемещён service.gui.MSG_DELIVERY_FAILURE=Сообщение выше не может быть доставлено service.gui.MSG_DELIVERY_NOT_SUPPORTED=Используемый вами протокол не поддерживает offline-сообщения. Вы можете попробовать связаться с {0} через другой протокол или подождать пока он/она не подключатся к сети. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Произошла внутренняя ошибка приложения. Возможно это баг. Пожалуйста, сообщите о ней сюда: https://jitsi.org/Development/BugsAndIssues. @@ -372,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Вы должны быть подклю service.gui.MULTIPLE_LOGINS=Вы подключены больше одного раза к тому же аккаунту. Следующий аккаунт: Имя пользователя: {0}, Имя сервера: {1} в данный момент отключён. service.gui.MY_CHAT_ROOMS=Добавить комнату service.gui.MY_CHAT_ROOMS_TITLE=Добавить комнату -service.gui.MUTE=Отключить звук service.gui.MUTUALLY_ON_HOLD_STATUS=Совместное удержание service.gui.NAME=Имя service.gui.NETWORK=Сеть @@ -404,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Не в списке контакто service.gui.SD_QUALITY=Стандартное качество service.gui.OFFLINE=Не в сети service.gui.OK=&OK -service.gui.OLDER_CALLS=Старые звонки service.gui.ONLINE=В сети service.gui.OPEN=Открыть service.gui.OPEN_FILE_FROM_IMAGE=Дважды щелкните, чтобы открыть файл. @@ -416,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Открыть активность service.gui.OPEN_ON_MESSAGE=Открыть только по сообщению service.gui.OPEN_ON_IMPORTANT_MESSAGE=Открывать только для важных сообщений service.gui.OR=или -service.gui.OR_ENTER_PHONE_NUMBER=Или введите номер телефона здесь... service.gui.ORGANIZATION=Организация service.gui.OTHER=Другое service.gui.chat.role.OWNER=Владелец @@ -442,7 +421,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' для предложений service.gui.PRESS_FOR_CALL_INFO=Нажмите для получения информации о звонке service.gui.PRESS_TO_OPEN_CRM=Нажмите для открытия приложения CRM service.gui.PREVIOUS=Предыдущий -service.gui.PREVIOUS_TOOLTIP=Обзор старых разговоров service.gui.PRINT=&Печать service.gui.PROACTIVE_NOTIFICATION=пишет сообщение service.gui.PROBLEMS_ENCOUNTERED=Встречающиеся проблемы @@ -458,7 +436,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Вы были отключены и по service.gui.RE_REQUEST_AUTHORIZATION=Запрос повторной авторизации service.gui.REFERRED_STATUS=Переведен service.gui.REJECT=&Отклонить -service.gui.REMIND_ME_LATER=Напомнить мне позже service.gui.REMEMBER_PASSWORD=Запомнить пароль service.gui.REMOVE=&Удалить service.gui.REMOVE_ACCOUNT=&Удалить аккаунт @@ -484,29 +461,20 @@ service.gui.REVOKE_ADMIN=Исключить из администраторов service.gui.REVOKE_MODERATOR=Исключить из модераторов service.gui.REVOKE_MEMBERSHIP=Аннулировать членство service.gui.REVOKE_VOICE=Исключить из голосования -service.gui.ROOT_GROUP=Корневая группа service.gui.SAVE=&Сохранить -service.gui.SAVE_AS_DEFAULT=Сохранить по умолчанию service.gui.SEARCH=&Поиск service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Нажмите кнопку ниже, чтобы показать все чаты, существующие на выбранном сервере. Затем выберите тот, в который хотите присоединиться и нажмите на кнопку соединения. service.gui.SEARCH_STRING_CONTACT_SOURCE=Поиск контактов service.gui.SECURITY=Безопасность -service.gui.SELECT_ACCOUNT=Выбрать аккаунт service.gui.SELECT_COLOR=Выбрать цвет service.gui.SELECT_GROUP=Выбрать группу -service.gui.SELECT_GROUP_WIZARD_MSG=Представленный ниже список содержит все группы в списке контактов. Выберите одну, которую хотите добавить новый контакт. service.gui.SELECT_NO_GROUP=Без группы -service.gui.SELECT_GROUP_WIZARD=Укажите группу service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Представленный ниже список содержит все учетные записи, которые поддерживают многопользовательский чат. Выберите тот, который хотите использовать для создания конференции. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Приведенный ниже перечень содержит все зарегистрированные учетные записи. Выберите ту, которую хотите использовать для общения с новым контактом. -service.gui.SELECT_PROVIDERS_WIZARD=Выберите аккаунт service.gui.SELECT_VIDEO_CONFERENCE=Выбрать видеоконференцию service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Выберите чат-комнату из списка и нажмите OK чтобы добавить ее service.gui.SEND=&Отправить service.gui.SEND_FILE=Отправить &файл -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Информация об этом контакте отсутствует. service.gui.SEND_MESSAGE=&Отправить сообщение -service.gui.SEND_AS_SMS=Отправить как SMS service.gui.SEND_PRIVATE_MESSAGE=Отправить личное сообщение service.gui.SEND_SMS=Отправить SMS service.gui.SEND_SMS_DETAILS=Помните, что вам нужно ввести номер телефона в международном формате, например, начиная с +7 для России, +78001112233 @@ -545,7 +513,6 @@ service.gui.STREET=Улица service.gui.SUBJECT=Тема service.gui.SUMMARY=Сводка service.gui.TELEPHONY=Телефония -service.gui.TODAY=Сегодня service.gui.TOOLS=&Инструменты service.gui.TRANSFER=Передача service.gui.TO=&Кому: @@ -555,7 +522,6 @@ service.gui.TRANSFER_CALL_TO=Перевод на: service.gui.TRANSPARENCY_NOT_ENABLED=Прозрачность не поддерживается вашей текущей конфигурацией. service.gui.TYPE_YOUR_REQUEST=Введите свой запрос здесь service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Не удалось изменить качество видео для этого вызова. -service.gui.UNMUTE=Включить звук service.gui.USER_IDENTIFIER=Идентификатор пользователя: service.gui.USER_EXISTS_ERROR=Этот пользователь уже существует в выбранной сети. Пожалуйста, выберите другого пользователя или сеть. service.gui.USERNAME_NULL=Пожалуйста, заполните свое имя пользователя и пароль. @@ -568,7 +534,6 @@ service.gui.USE_PROVISIONING=Использовать автонастройку service.gui.VALUE=Значение service.gui.VIDEO_CALL=&Видеовызов service.gui.VIA=через -service.gui.VIA_SMS=Через SMS service.gui.VIEW=&Показать service.gui.VIEW_HISTORY=Показать &историю service.gui.VIEW_SMILEYS=Показать &смайлы @@ -588,9 +553,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Регулировка громкости service.gui.WAITING_AUTHORIZATION=Ожидание авторизации service.gui.WARNING=Предупреждение service.gui.YES=Да -service.gui.YESTERDAY=Вчера -service.gui.EXISTING_ACCOUNT_ERROR=Введенный аккаунт уже установлен. -service.gui.NEW_MAIL=У Вас одно новое письмо!
    От: {0} {1}
    Тема: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Вы получили новое письмо во {0} входящие:
    service.gui.NEW_GMAIL_MANY_HEADER=Вы получили {2} новых письма во {0} входящие:
    service.gui.NEW_GMAIL_FOOTER=еще один непрочитанный разговор вовходящих.
    @@ -617,7 +579,6 @@ service.gui.SECURITY_ERROR=Ошибка безопасности service.gui.SPEED=Скорость: service.gui.SILENT_MEMBER=молчаливый участник service.gui.NON_SECURE_CONNECTION=Безопасное соединение не может быть установлено для {0}. Если Вы хотите использовать незащищенное подключение, пожалуйста, установите флажок "Разрешить незащищенные соединения" в конфигурации учетной записи -service.gui.UPDATE=Обновить service.gui.MOBILE_PHONE=Мобильный service.gui.VIDEO_PHONE=Видеовызовы service.gui.WORK_PHONE=Рабочий @@ -652,12 +613,10 @@ service.gui.callinfo.CALL_INFORMATION=Информация о вызове service.gui.callinfo.CALL_IDENTITY=Учетная запись service.gui.callinfo.PEER_COUNT=Количество участников service.gui.callinfo.IS_CONFERENCE_FOCUS=Конференция -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Шифрование включено service.gui.callinfo.CALL_TRANSPORT=Транспорт сигнализации service.gui.callinfo.CALL_DURATION=Длительность вызова service.gui.callinfo.TLS_PROTOCOL=Протокол TLS service.gui.callinfo.TLS_CIPHER_SUITE=набор шифров TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=цепочка сертификатов TLS сервера service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Содержимое сертификата TLS сервера показано ниже. service.gui.callinfo.VIEW_CERTIFICATE=Просмотр сертификата service.gui.callinfo.CODEC=Кодек / Частота @@ -667,7 +626,6 @@ service.gui.callinfo.AUDIO_INFO=Аудио поток service.gui.callinfo.VIDEO_INFO=Видео поток service.gui.callinfo.LOCAL_IP=Локальный IP / Порт service.gui.callinfo.REMOTE_IP=Удаленный IP / Порт -service.gui.callinfo.BANDWITH=Полоса пропускания service.gui.callinfo.LOSS_RATE=Потеря пакетов service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Джиттер @@ -677,10 +635,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Протокол обмена ключами service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE кандидат расширенного типа service.gui.callinfo.ICE_STATE=Состояние ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Получение кандидатов service.gui.callinfo.ICE_STATE.RUNNING=Проверка подключения service.gui.callinfo.ICE_STATE.COMPLETED=Завершено service.gui.callinfo.ICE_STATE.FAILED=Ошибка + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Локальный IP / Порт service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Локальный входящий IP / Порт service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Локальный исходящий IP / Порт @@ -701,11 +662,12 @@ service.gui.ALWAYS_TRUST=Всегда доверять этому сертифи service.gui.CERT_DIALOG_TITLE=Проверить сертификат service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} не может проверить подлинность сервера при подключении к
    {1}.

    Сертификат не является доверенным, это означает, что сервер не может быть автоматически проверен.

    Вы хотите продолжить подключение?
    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} не может проверить подлинность сертификата сервера.

    Сертификат не является доверенным. Это означает, что сервер не
    может быть автоматически проверен.Вы хотите продолжить подключение?

    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} не может проверить подлинность клиента.

    Сертификат не является доверенным, это означает, что клиент не
    может быть автоматически проверен. Вы хотите принять подключение?

    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} не может проверить подлинность клиента {1}.

    Сертификат не является доверенным, это означает, что клиент не
    может быть автоматически проверен. Вы хотите продолжить подключение?

    Для получения дополнительной информации, нажмите кнопку "Показать сертификат". service.gui.CONTINUE_ANYWAY=Все равно продолжить service.gui.CERT_INFO_CHAIN=Цепочка сертификатов: service.gui.CERT_INFO_ISSUED_TO=Выпущен для + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Имя сертификата: service.gui.CERT_INFO_O=Организация: service.gui.CERT_INFO_C=Страна: @@ -724,12 +686,10 @@ service.gui.CERT_INFO_SIGN_ALG=Алгоритм подписи: service.gui.CERT_INFO_PUB_KEY_INFO=Информация об открытом ключе service.gui.CERT_INFO_ALG=Алгоритм: service.gui.CERT_INFO_PUB_KEY=Открытый ключ: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} байт: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} бит service.gui.CERT_INFO_EXP=Экспонента: service.gui.CERT_INFO_KEY_SIZE=Размер ключа: service.gui.CERT_INFO_SIGN=Подпись: -service.gui.CONTINUE=Продолжить service.gui.SHOW_CERT=Показать сертификат service.gui.HIDE_CERT=Скрыть сертификат @@ -752,12 +712,9 @@ service.gui.security.SECURE_AUDIO=Аудиопоток защищен service.gui.security.AUDIO_NOT_SECURED=Аудиопоток не защищен service.gui.security.SECURE_VIDEO=Видеопоток защищен service.gui.security.VIDEO_NOT_SECURED=Видеопоток не защищен -service.gui.security.NO_VIDEO=Нет видео -service.gui.security.CIPHER=Шифр: {0} service.gui.security.CALL_SECURED_TOOLTIP=Разговор защищен. Для получения информации нажмите сюда. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Разговор не защищен. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Нажмите здесь, чтобы сверить ключ с собеседником. -service.gui.security.COMPARE_WITH_PARTNER=Сверьте ключ с собеседником и нажмите замочек для подтверждения. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Сверьте ключ с собеседником: service.gui.security.STRING_COMPARED=Ключ подтвержден! @@ -775,20 +732,14 @@ service.gui.avatar.imagepicker.CLICK=Сделать снимок service.gui.avatar.imagepicker.IMAGE_FILES=Файлы изображений service.gui.avatar.imagepicker.IMAGE_PICKER=Изображение service.gui.avatar.imagepicker.IMAGE_SIZE=Размер изображения -service.gui.avatar.imagepicker.INITIALIZING=Инициализация service.gui.avatar.imagepicker.RESET=Сброс service.gui.avatar.imagepicker.SET=Задать service.gui.avatar.imagepicker.TAKE_PHOTO=Сделать снимок -service.gui.avatar.imagepicker.WEBCAM_ERROR=Ошибка вебкамеры service.gui.security.encryption.required=Требуется шифрование! service.protocol.ICE_FAILED=Невозможно установить подключение (сбой ICE, не найдено трансляции) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Ошибка в адресной книге SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Ресурс не может быть прочитан {0}. Для {1} @@ -818,9 +769,7 @@ impl.ldap.QUERY_CUSTOM=Индивидуальный запрос impl.ldap.QUERY_CUSTOM_HINT=Используйте {0} в качестве шаблона для поиска термина. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Автоматически добавить метасимволы в текст запроса impl.ldap.QUERY_PHOTO_INLINE=Получать фото вместе с остальными атрибутами -impl.ldap.NEW=Новый impl.ldap.EDIT=изменить -impl.ldap.REMOVE=Удалить impl.ldap.ENABLED=Активен impl.ldap.SERVER_NAME=Краткое имя impl.ldap.SERVER_NAME_EXAMPLE=Адресная книга LDAP @@ -853,6 +802,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Телефонный префикс impl.ldap.PHONE_PREFIX_EXAMPLE=Например: +7 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Адресная книга plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Включить поиск в адресной книге MacOSX @@ -867,9 +820,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Сделать Outlook почт # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Контакты Google -impl.googlecontacts.NEW=Новый impl.googlecontacts.EDIT=изменить -impl.googlecontacts.REMOVE=Удалить impl.googlecontacts.ENABLED=Активен impl.googlecontacts.ACCOUNT_NAME=Аккаунт impl.googlecontacts.SAVE=Сохранить @@ -908,11 +859,8 @@ plugin.accountinfo.ORGANIZATION=Организация: plugin.accountinfo.JOB_TITLE=Должность: plugin.accountinfo.ABOUT_ME=Обо мне: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Фотографии пользователя plugin.accountinfo.GLOBAL_ICON=Использовать общий значок plugin.accountinfo.LOCAL_ICON=Использовать следующий значок: -plugin.accountinfo.CHANGE=Изменить -plugin.accountinfo.ONLY_MESSAGE=Только сообщения # connection info plugin.connectioninfo.TITLE=Информация о соединении @@ -932,52 +880,14 @@ plugin.aimaccregwizz.USERNAME=AIM Имя: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Идентификатор пользователя и пароль plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Регистрация новой учетной записи plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=В случае, если вы не имеете учетной записи AIM, нажмите на эту кнопку, чтобы создать новую. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Переопределить параметры сервера по умолчанию # branding plugin.branding.ABOUT_WINDOW_TITLE=О нас {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Обмен мгновенными сообщениями -plugin.branding.LOADING=Загрузка plugin.branding.ABOUT_MENU_ENTRY=&О программе -plugin.branding.WELCOME_MESSAGE=
    {1} в настоящее время в стадии активной разработки. Версия, запущенная вами, экспериментальная и может работать НЕ ТАК как вы ожидаете. Пожалуйста, обратитесь к {2} для получения дополнительной информации.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Все права защищены. Посетите https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi распространяется по лицензии LGPL (http://www.gnu.org).
    plugin.busylampfield.PICKUP=Поднять трубку -# Dict protocol -service.protocol.DICTIONARIES=Словари -plugin.dictaccregwizz.ANY_DICTIONARY=Любой словарь -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Любой словарь от {0} -plugin.dictaccregwizz.FIRST_MATCH=Первое совпадение -plugin.dictaccregwizz.NO_MATCH=Нет совпадений -plugin.dictaccregwizz.MATCH_RESULT=Определений для "{0}" не найдено, может быть, вы имеете в виду:\n -plugin.dictaccregwizz.INVALID_DATABASE=Текущего словаря "{0}" не существует на сервере. -plugin.dictaccregwizz.INVALID_STRATEGY=Нынешняя стратегия отсутствует на сервере. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=DICT протокол -plugin.dictaccregwizz.HOST=Хост -plugin.dictaccregwizz.SERVER_INFO=Информация о сервере -plugin.dictaccregwizz.STRATEGY_SELECTION=Выбор метода -plugin.dictaccregwizz.STRATEGY_LIST=Список методов: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Поиск методов -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Использовать метод для поиска похожих слов, если перевод не был найден, благодаря разным методам. Например, номера стратегии будет искать слова, которые начинаются, как слово, которое вы бы перевести. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Информация об учетной записи -plugin.dictaccregwizz.FIRST_ACCOUNT=Этот мастер поможет создать ваш первый аккаунт на сайте dict.org.\n\nВы можете добавить новый словарь пройдя регистрацию учетной записи в мастере. Заполните поля словаря который вы хотели бы добавить. -plugin.dictaccregwizz.THREAD_CONNECT=Попытка подключения к серверу -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Попытка подключения не удалась, это не сервер словарей или сервер недоступен -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Получение метода -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Метод не найден на сервере -plugin.dictaccregwizz.POPULATE_LIST=Заполнение списка -plugin.dictaccregwizz.CLOSING_CONNECTION=Закрытие соединения - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Для того, чтобы использовать Facebook чат необходимо создать "Имя пользователя"
    в "Настройках аккаунта " на Facebook.


    Примечание: При создании имени пользователя необходимо выйти из страницы
    и может потребоваться некоторое время, прежде чем вы сможете войти с вашим новым именем пользователя!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Протокол чата Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Имя пользователя: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Имя пользователя и пароль - # generalconfig plugin.generalconfig.AUTO_START=Автоматический запуск {0} при загрузке компьютера plugin.generalconfig.CHATALERTS_ON_MESSAGE=Использовать панель задач / область уведомлений для входящих звонков и бесед @@ -987,9 +897,6 @@ plugin.generalconfig.SHOW_HISTORY=Показывать plugin.generalconfig.HISTORY_SIZE=последних сообщений в новом чате plugin.generalconfig.SEND_MESSAGES_WITH=Отправлять сообщения при нажатии: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Переносить окно чата поверх всех окон при входящем сообщении -plugin.generalconfig.ERROR_PERMISSION=У вас нет достаточных привилегий для отключения автозапуска -plugin.generalconfig.TRANSPARENCY=Прозрачность -plugin.generalconfig.ENABLE_TRANSPARENCY=Включить прозрачность plugin.generalconfig.DEFAULT_LANGUAGE=Язык интерфейса plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Изменения вступят в силу при следующем запуске Jitsi. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% переведено @@ -1056,11 +963,9 @@ plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=Вышеупомянутый IRC п plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Всегда разрешать DNS имена через прокси # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Протокол XMPP plugin.jabberaccregwizz.USERNAME=Имя пользователя XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Подтвердите пароль -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID и пароль plugin.jabberaccregwizz.CSERVER=Сервер plugin.jabberaccregwizz.SERVER=Подключение к серверу plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Поддерживать подключение @@ -1076,13 +981,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Комментарий plugin.jabberaccregwizz.RESOURCE=Ресурс plugin.jabberaccregwizz.AUTORESOURCE=Автоматическое создание ресурса plugin.jabberaccregwizz.PRIORITY=Приоритет -plugin.jabberaccregwizz.XMPP_ERROR=Ошибка XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Неизвестная ошибка XMPP ({0)}. Убедитесь, что имя сервера является правильным. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Пароли не совпадают. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Переопределить параметры сервера по умолчанию -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Дополнительные параметры plugin.jabberaccregwizz.USE_ICE=Использовать ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Использовать Google Jingle/ICE (экспериментальная функция) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Автоматически обнаруживать STUN/TURN сервера plugin.jabberaccregwizz.SUPPORT_TURN=Поддерживать TURN plugin.jabberaccregwizz.TURN_USERNAME=Имя пользователя TURN @@ -1110,11 +1011,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Отключить мультиклиен plugin.jabberaccregwizz.DTMF_AUTO=Автоматически выбирать между RTP и Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Параметры сервера plugin.jabberaccregwizz.CHANGE_PASSWORD=Изменить пароль -plugin.jabberaccregwizz.NEW_PASSWORD=Новый пароль -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Повторите пароль plugin.jabberaccregwizz.PORT_FIELD_INVALID=Пожалуйста, необходимо указать верный порт для продолжения. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Для смены пароля необходимо выполнить вход на сервер. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Пароль пустой. plugin.jabberaccregwizz.TLS_REQUIRED=Соединение не использует TLS, пароль не будет изменен. plugin.jabberaccregwizz.PASSWORD_CHANGED=Пароль успешно изменен plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Ваш XMPP сервер не поддерживает изменение пароля. @@ -1128,25 +1026,9 @@ plugin.jabberaccregwizz.RESET=Сброс plugin.jabberaccregwizz.RESET_DESCRIPTION=Сброс на глобальные настройки plugin.jabberaccregwizz.DISABLE_JINGLE=Отключить Jingle (аудио и видеозвонки через XMPP). -# mailbox -plugin.mailbox.OUTGOING=Исходящее сообщение: -plugin.mailbox.INCOMING=Входящие сообщение: -plugin.mailbox.WAIT_TIME=Звонок переводиться на автоответчик -plugin.mailbox.MAX_MESSAGE_TIME=Максимальная продолжительность входящих сообщений -plugin.mailbox.CONFIRM=Подтвердить -plugin.mailbox.DEFAULTS=По умолчанию -plugin.mailbox.MAILBOX=Почтовый ящик - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Протокол для подключения и чата на MSN службе. -plugin.msnaccregwizz.USERNAME=Электронный ящик: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID и пароль - # plugin manager plugin.pluginmanager.INSTALL=Установить plugin.pluginmanager.UNINSTALL=Удалить -plugin.pluginmanager.UPDATE=Обновить plugin.pluginmanager.PLUGINS=Плагины plugin.pluginmanager.URL=Ссылка plugin.pluginmanager.CHOOSE_FILE=Выбор файла @@ -1171,7 +1053,6 @@ plugin.sipaccregwizz.SERVER_PORT=Порт сервера plugin.sipaccregwizz.PROXY=Прокси plugin.sipaccregwizz.PROXY_PORT=Порт прокси plugin.sipaccregwizz.PREFERRED_TRANSPORT=Предпочтительный вид транспорта -plugin.sipaccregwizz.ADVANCED_OPTIONS=Дополнительные параметры plugin.sipaccregwizz.PROXY_OPTIONS=Настройки прокси-сервера plugin.sipaccregwizz.PROXY_AUTO=Автоматическая настройка прокси-сервера plugin.sipaccregwizz.ENABLE_PRESENCE=Включить присутствие (SIMPLE) @@ -1191,8 +1072,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Автоматически выбирать ме plugin.sipaccregwizz.DTMF_RTP=RTP (RFC2833 / RFC4733) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Переопределить параметры сервера по умолчанию plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Включить поддержку шифрования звонков plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Сообщать о поддержке ZRTP в протоколе сигнализации plugin.sipaccregwizz.AUTH_NAME=Имя для авторизации @@ -1213,10 +1092,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI для проверки ГП plugin.sipaccregwizz.NOT_SAME_PASSWORD=Пароли не совпадают. plugin.sipaccregwizz.NO_CERTIFICATE= (использовать обычную проверку подлинности) plugin.sipaccregwizz.SAVP_OPTION=Использование RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Выключено (использовать только RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Обязательно (предлагать и принимать только RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Опционально (сначала предлагать RTP/SAVP, затем RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Включить S-дескриптор (также известный как SDES или SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Выберите протоколы шифрования и их приоритет (сверху протокол с наибольшим приоритетом): plugin.sipaccregwizz.CIPHER_SUITES=Доступные наборы шифров: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} будет пытаться автоматически защитить все Ваши звонки с помощью ZRTP. Вы будете уведомлены об этом каждый раз, осуществляя вызов. Вы можете изменять дополнительные настройки только в том случае, если хорошо понимаете, что делаете.
    @@ -1230,15 +1109,6 @@ plugin.skinmanager.DEFAULT_SKIN=Оболочка по умолчанию plugin.skinmanager.ADD_NEW_SKIN=Добавить новую оболочку... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Оболочка приложения по умолчанию. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Протокол для подключения к удаленным компьютерам через SSH. -plugin.sshaccregwizz.USERNAME=ID учетной записи: -plugin.sshaccregwizz.IDENTITY_FILE=Личный файл: -plugin.sshaccregwizz.KNOWN_HOSTS=Известные хосты: -plugin.sshaccregwizz.OPTIONAL=Необязательный -plugin.sshaccregwizz.ACCOUNT_DETAILS=Информация об учетной записи - # status update plugin.autoaway.AUTO_STATUS=Авто отсуствие plugin.autoaway.ENABLE_CHANGE_STATUS=Изменить статус, когда отошел @@ -1286,22 +1156,6 @@ plugin.whiteboard.DESELECT=Отменить plugin.whiteboard.DELETE=Удалить plugin.whiteboard.PROPERTIES=Свойства -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Протокол для подключения и общения на Yahoo! Service. -plugin.yahooaccregwizz.USERNAME=Имя пользователя: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID и пароль - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Zeroconf (Bonjour) протокол. -plugin.zeroaccregwizz.FIRST_NAME=Имя: -plugin.zeroaccregwizz.LAST_NAME=Фамилия: -plugin.zeroaccregwizz.EMAIL=Электронный ящик: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Запомнить Bonjour контакты? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID и пароль -plugin.zeroaccregwizz.USERID=Пользовательский ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Протокол Google Talk @@ -1315,19 +1169,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, портал IP Теле plugin.iptelaccregwizz.USERNAME=Имя пользователя plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Подписаться на iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP и чат +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Имя пользователя plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Введите пароль еще раз plugin.sip2sipaccregwizz.EMAIL=Адрес электронной почты -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Для получения справки об услуге посетите
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Адрес электронной почты используется для отправки голосовых сообщений,
    уведомлений о пропущенных звонках, а также восстановления утерянного пароля -plugin.sip2sipaccregwizz.INFO_NOTE=Для получения справки об услуге посетитеhttp://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Существующий sip2sip.info аккаунт -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Создать бесплатный аккаунт sip2sip.info - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Мгновенные сообщения plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Для получения справки об услуге посетите
    http://ippi.fr @@ -1336,6 +1182,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Существующие ippi аккау plugin.ippiaccregwizz.CREATE_ACCOUNT=Создать бесплатную учетную запись ippi # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Закрыть окно чата plugin.keybindings.CHAT_COPY=Копировать plugin.keybindings.CHAT_CUT=Вырезать @@ -1358,10 +1205,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Действие plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Сочетание клавиш plugin.keybindings.globalchooser.SHORTCUT_SECOND=Дополнительно plugin.keybindings.globalchooser.PRESS_BTN=Нажмите для назначения сочетания клавиш -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Ожидание plugin.keybindings.globalchooser.PUSH_TO_TALK=Нажмите, чтобы говорить plugin.keybindings.globalchooser.ENABLE_SPECIAL=Включить обнаружение специальных клавиш plugin.keybindings.PLUGIN_NAME=Сочетания клавиш +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Чат plugin.keybindings.MAIN=Основные plugin.keybindings.GLOBAL=Глобальные @@ -1389,6 +1236,7 @@ plugin.notificationconfig.tableheader.SOUND=Системный звуковой plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Звуковой сигнал через динамики plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Звуковой сигнал через динамик ПК plugin.notificationconfig.tableheader.DESCRIPTION=Описание события +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Входящий звонок plugin.notificationconfig.event.SecurityMessage=Сообщение безопасности plugin.notificationconfig.event.IncomingFile=Получен файл @@ -1490,6 +1338,7 @@ impl.neomedia.configform.VIDEO=Видео impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Периодическое обновление интра-данных impl.neomedia.configform.H264.defaultProfile=Профиль для кодирования: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Базовый impl.neomedia.configform.H264.defaultProfile.high=Высокое impl.neomedia.configform.H264.defaultProfile.main=Основной @@ -1520,7 +1369,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Текущий парол plugin.securityconfig.masterpassword.ENTER_PASSWORD=Введите новый пароль: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Введите пароль повторно: plugin.securityconfig.masterpassword.MP_TITLE=Мастер-пароль -plugin.securityconfig.masterpassword.MP_NOT_SET=(не установлено) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Вы ввели неправильный текущий мастер-пароль. Пожалуйста, попробуйте еще раз. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Мастер-пароль неправильный! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Изменение пароля не удалось @@ -1536,7 +1384,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Пароль plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(неизвестно) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(не могу расшифровать) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Сохраненные пароли -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Удалить plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Удалить все plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Вы уверены, что хотите удалить все пароли? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Удалить все пароли @@ -1632,7 +1479,6 @@ plugin.globalproxy.PROXY_PORT=Порт plugin.globalproxy.PROXY_USERNAME=Имя пользователя plugin.globalproxy.PROXY_PASSWORD=Пароль plugin.globalproxy.DESCRIPTION={0} будет использовать перечисленные параметры прокси-сервера для всех сетей при следующем подключении. \nПоддержка прокси в настоящее время экспериментальная и работает только с некоторыми протоколами. Смотрите таблицу ниже для более подробной информации: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Также проксифицировать DNS plugin.globalproxy.FWD_DNS_NOTE=Полезно с Тор. Помогает избежать утечки DNS, направляя весь DNS трафик через Тор прокси. Требуется перезагрузка. @@ -1670,7 +1516,6 @@ plugin.provisioning.RESTART_WARNING=Изменения вступят в сил plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Скопировать UUID в буфер plugin.provisioning.CLIPBOARD_FAILED=Ошибка при копировании UUID в буфер -plugin.provisioning.EXIT_ON_FAIL=Закрывать Jitsi, если автонастройка не удалась plugin.provisioning.CREDENTIALS=Учетная запись для автонастройки plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Вы действительно хотите сбросить пароль для автонастройки? plugin.provisioning.PROV_FAILED=Автонастройка не удалась @@ -1737,8 +1582,6 @@ util.dns.DNSSEC_WARNING=
    {0} попытался подкл #plugin spellcheck plugin.spellcheck.TITLE=Орфография и Грамматика plugin.spellcheck.MENU=Открыть словарь -plugin.spellcheck.LANG=Язык -plugin.spellcheck.EDIT_PERSONAL_DICT=Правка plugin.spellcheck.ENABLE_SPELL_CHECK=Проверка правописания plugin.spellcheck.dialog.FIND=Найти далее plugin.spellcheck.dialog.REPLACE=Заменить -- cgit v1.1 From 643c2bd6840418ec14d84b2d07090b5fecd43b1b Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:53:13 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 871 of 1505 strings translated (17 fuzzy). --- resources/languages/resources_pl.properties | 250 +++++++++++----------------- 1 file changed, 95 insertions(+), 155 deletions(-) diff --git a/resources/languages/resources_pl.properties b/resources/languages/resources_pl.properties index 04611e8..a5fac15 100644 --- a/resources/languages/resources_pl.properties +++ b/resources/languages/resources_pl.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -26,36 +37,30 @@ # ant -Duser.language=xx run service.gui.ABOUT=&O programie -service.gui.ACCEPT=&Zaakceptuj +service.gui.ACCEPT=&Akceptuj service.gui.ACCOUNT=Konto service.gui.ACCOUNT_ME=Ja -service.gui.ACCOUNT_REGISTRATION_WIZARD=Kreator rejestracji konta +service.gui.ACCOUNT_REGISTRATION_WIZARD=Asystent tworzenia konta service.gui.ACCOUNTS=Konta service.gui.ADD=&Dodaj -service.gui.ADD_ACCOUNT=Dodaj konto service.gui.ADD_CONTACT=&Dodaj kontakt -service.gui.ADD_AUTHORIZED_CONTACT=Dodaj {0} do listy kontaktów +service.gui.ADD_AUTHORIZED_CONTACT=Dodaj {0} do swojej listy kontaktów service.gui.ADD_CONTACT_TO_CONTACTLIST=Dodaj ten kontakt do mojej listy kontaktów service.gui.ADD_CONTACT_TO=&Dodaj kontakt do service.gui.ADD_CONTACT_ERROR=Nie udało się dodać kontaktu o identyfikatorze: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Błąd przy dodawaniu kontaktu -service.gui.ADD_CONTACT_EXIST_ERROR=Ten kontakt już jest na liście kontaktów. -service.gui.ADD_CONTACT_NETWORK_ERROR=Serwer nie odpowiedział na żądanie dodania kontaktu o identyfikatorze: {0} -service.gui.ADD_CONTACT_NOT_SUPPORTED=Próba dodania kontaktu o identyfikatorze {0} została zakończona niepowodzeniem. Operacja nie jest obsługiwana. -service.gui.ADD_CONTACT_IDENTIFIER=W polu poniżej wprowadź identyfikator kontaktu, którego chcesz dodać. -service.gui.ADD_CONTACT_WIZARD=Kreator dodawania kontaktu +service.gui.ADD_CONTACT_EXIST_ERROR=Kontakt {0} już jest na Twojej liście kontaktów. +service.gui.ADD_CONTACT_NETWORK_ERROR=Serwer nie odpowiedział na żądanie dodania kontaktu o identyfikatorze: {0}. +service.gui.ADD_CONTACT_NOT_SUPPORTED=Próba dodania kontaktu o identyfikatorze: {0} zakończona niepowodzeniem. Operacja nie jest obsługiwana. service.gui.ADD_CONTACT_NOT_CONNECTED=Musisz być połączony aby dodać kontakt. Zaloguj się do wybranego dostawcy i spróbuj ponownie. service.gui.ADD_GROUP_LOCAL_ERROR=Nie udało się dodać grupy o nazwie: {0}. Wystąpił błąd lokalnej operacji wejścia/wyjścia. service.gui.ADD_GROUP_EXIST_ERROR=Grupa {0} już jest na twojej liście kontaktów. Wybierz inną nazwę. service.gui.ADD_GROUP_NET_ERROR=Nie udało się dodać grupy o nazwie: {0}. Problem wystąpił z powodu awarii sieci. Sprawdź połączenie z Internetem i spróbuj ponownie. service.gui.ADD_GROUP_ERROR=Nie udało się dodać grupy o nazwie: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Nazwa grupy nie może być pusta. -service.gui.ADD_GROUP=Utwórz grupę -service.gui.ADD_SUBCONTACT=&Dodaj kontakt podrzędny service.gui.ADDRESS=Adres service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Zaawansowane -service.gui.ALL=&Wszystkie service.gui.ALL_CONTACTS=&Wszystkie kontakty service.gui.ALTERNATE_ADDRESS=Adres alternatywny service.gui.APPLY=&Zastosuj @@ -63,9 +68,8 @@ service.gui.ARE_CALLING={0} dzwonią... service.gui.ARE_NOW=Jesteś teraz {0} service.gui.AT=w service.gui.AUTHORIZE=&Autoryzuj -service.gui.AUTHORIZATION_ACCEPTED=Użytkownik {0} zaakceptował twoją prośbę o autoryzację. +service.gui.AUTHORIZATION_ACCEPTED={0} zaakceptował twoją prośbę o autoryzację. service.gui.AUTHENTICATION_FAILED=Błąd uwierzytelniania dla {0}. Wprowadzone hasło jest nieprawidłowe. -service.gui.AUTHENTICATION_REQUESTED=Prośba o Uwierzytelnienie service.gui.AUTHENTICATION_REQUESTED_SERVER=Serwer {0} zażądał uwierzytelnienia. service.gui.AUTHENTICATION_REJECTED={0} odrzucił twoją prośbę o autoryzację. service.gui.AUTHENTICATION_WINDOW_TITLE=uwierzytelnianie {0} @@ -74,32 +78,32 @@ service.gui.AUTHORIZATION_REQUESTED_INFO=Kontakt {0} zażądał autoryzacji. service.gui.AUTHORIZATION_RESPONSE=Odpowiedź na autoryzację service.gui.AWAY_STATUS=Zaraz wracam service.gui.EXTENDED_AWAY_STATUS=Nieobecny na dłużej -service.gui.BAN=&Zabroń wstępu +service.gui.BAN=Za&blokuj service.gui.BANNED=Zablokowany -service.gui.BAN_FAILED=Niepowodzenie blokady +service.gui.BAN_FAILED=Nieudana blokada service.gui.BAN_FAILED_GENERAL_ERROR=Niepowodzenie blokady {0}. Ogólny błąd serwera. service.gui.BAN_FAILED_NOT_ALLOWED=Niepowodzenie blokady {0}. Właściciel/administrator pokoju nie mogą być zablokowani. service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS=Niepowodzenie blokady {0}. Nie masz wystarczających uprawnień. -service.gui.BRB_MESSAGE=Zaraz wracam. +service.gui.BRB_MESSAGE=Nie ma mnie, ale za niedługo wrócę service.gui.BROWSE=Przeglądaj service.gui.BUSY_MESSAGE=Przepraszam, jestem zajęty. service.gui.BUSY_STATUS=Zajęty -service.gui.CALL=Telefon +service.gui.CALL=Zadzwoń service.gui.CALL_CONTACT=Zadzwoń do kontaktu service.gui.CALL_FAILED=Połączenie nieudane -service.gui.CALL_HISTORY_TOOL_TIP=Kliknij tu, by zobaczyć historię połączeń. +service.gui.CALL_HISTORY_TOOL_TIP=Kliknij tutaj, aby zobaczyć historię połączeń. service.gui.CALL_HISTORY_GROUP_NAME=Historia połączeń service.gui.CALL_VIA=Zadzwoń przez: service.gui.CALL_NAME_OR_NUMBER=Wprowadź nazwę kontaktu lub numer service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=To połączenie obsługuje tylko uczestników z sieci {0} i twoje konto {1}. {2} nie zawiera żadnych adresów z tej sieci ani konta. -service.gui.CALL_WITH=Zadzwoń z +service.gui.CALL_WITH=Zadzwoń za pomocą service.gui.CALL_NO_AUDIO_DEVICE=Karta dźwiękowa nie została skonfigurowana. service.gui.CALL_NO_AUDIO_CODEC=Nie włączyłeś żadnych kodeków dźwiękowych. -service.gui.CALL_NO_DEVICE_CODECS_Q=Czy chcesz kontynuować rozmowę ? +service.gui.CALL_NO_DEVICE_CODECS_Q=Czy chcesz kontynuować rozmowę? service.gui.CANCEL=&Anuluj service.gui.CHAT=Czat service.gui.CHANGE_FONT=Zmień czcionkę -service.gui.CHANGE_ROOM_SUBJECT=Zmień temat pokoju... +service.gui.CHANGE_ROOM_SUBJECT=Zmień temat rozmowy service.gui.CHANGE_ROOM_SUBJECT_LABEL=W polu poniżej możesz wprowadzić nowy temat dla tego pokoju. service.gui.CHANGE_NICK=Zmień pseudonim service.gui.CHANGE_NICKNAME=Zmień pseudonim... @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=W polu poniżej możesz wprowadzić twój nowy service.gui.CHANGE_NICKNAME_ERROR=Błąd podczas zmieniania nazwy użytkownika service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Ta nazwa użytkownika już istnieje service.gui.CHANGE_VIDEO_QUALITY=Zmień jakość zdalnego video -service.gui.CHAT_CONFERENCE_LABEL=Konferencje service.gui.CHAT_CONFERENCE_ITEM_LABEL=Konferencja {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Już przyłączyłeś się do pokoju rozmów {0}. service.gui.CHAT_ROOM_CONFIGURATION=Konfiguracja pokoju czatu {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT={0} wyszedł service.gui.CHAT_ROOM_USER_KICKED=został wyrzucony z {0} service.gui.CHAT_ROOM_USER_QUIT={0} wyszedł service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Wysyłanie wiadomości zostało zablokowane(ograniczono uprawnienia). -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Zapamiętuje pokój rozmów. -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Usuwa wybrany pokój z listy zapisanych pokoi. service.gui.CHAT_ROOM_NAME=Nazwa pokoju rozmów service.gui.CLEAR_CUSTOM_MESSAGES=Wyczyść własne wiadomości service.gui.ROOM_NAME=Pokoje czatu -service.gui.AUTOJOIN=Autodołączanie service.gui.CHANGE_PASSWORD=Zmień hasło service.gui.CHAT_ROOM_NAME_INFO=W poniższym polu wprowadź nazwę grupy, którą chcesz utworzyć. service.gui.CHAT_ROOM_NOT_EXIST=Pokój {0} nie został znaleziony na serwerze {1}. Zweryfikuj czy wprowadziłeś poprawną nazwę. service.gui.CHAT_ROOM_NOT_CONNECTED=Musisz być zalogowany aby dołączyć do pokoju czatowego {0} service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Musisz być zalogowany aby opuścić pokój czatowy. -service.gui.CHAT_ROOM_NOT_JOINED=Musisz być połączony z pokojem rozmów, aby móc wykonywać dalsze operacje z nim związane. service.gui.CHAT_ROOM_OPTIONS=Opcje pokojów czatu service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Ten pokój czatu {0} wymaga rejestracji. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Pokój czatu {0} poprosił o hasło. @@ -151,21 +150,18 @@ service.gui.CLEAR=Wyczyść service.gui.CLOSE=&Zamknij service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Odebrano nową wiadomość mniej niż 2 sekundy temu. Czy na pewno chcesz zamknąć ten czat? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Masz aktywne transfery plików. Czy na pewno chcesz je przerwać? -service.gui.CONFIRM=Potwierdź service.gui.CONNECTED_STATUS=Połączono service.gui.CONNECTING=Łączę... service.gui.CONNECTING_STATUS=Łączenie service.gui.CONNECTING_EARLY_MEDIA_STATUS=Łączę* service.gui.CONNECTION=Połączenie -service.gui.CONNECTION_FAILED_MSG=Nieudana próba połączenia z serwerem dla konta: {0}, nazwa serwera: {1}. Sprawdź połączenie sieciowe lub skontaktuj się z administratorem sieci, aby uzyskać więcej informacji. service.gui.CONNECTION_EXPIRED_MSG=Nie masz połączenia z serwerem {0}. service.gui.CONTACT_NAME=Identyfikator użytkownika lub numer telefonu -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Wybrany kontakt {0} nie obsługuje telefonii. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Wybrany kontakt {0} nie obsługuje czatu podczas konferencji. service.gui.CONTACT_PAUSED_TYPING={0} przerwał pisanie service.gui.CONTACT_TYPING={0} pisze +service.gui.CONTACT_TYPING_SEND_FAILED=uh-oh...nie możemy poinformować {0} że pisałeś service.gui.CONTACT_INFO=&O kontakcie -service.gui.CONTACTLIST=Lista kontaktów service.gui.CONTACTS=Kontakty service.gui.COPY=&Kopiuj service.gui.COPY_LINK=&Kopiuj link @@ -175,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Utwórz pokój czatu... service.gui.CREATE_CHAT_ROOM_ERROR=Nie udało się utworzyć pokoju czatu {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Kreator tworzenia pokoju czatu service.gui.CREATE_CONFERENCE_CALL=&Utwórz telekonferencję... -service.gui.CREATE_CONFERENCE_CHAT=&Utwórz czat grupowy... service.gui.CREATE_GROUP=&Utwórz grupę... service.gui.CREATE_GROUP_NAME=W poniższym polu wprowadź nazwę grupy, którą chcesz utworzyć. -service.gui.CREATE_FIRST_GROUP_WIZARD=Twoja lista kontaktów nie zawiera żadnej grupy. Najpierw utwórz grupę (Plik/Utwórz grupę). service.gui.CREATE_VIDEO_BRIDGE=Utwórz most &video service.gui.CREATE_VIDEO_BRIDGE_MENU=Utwórz most &wideo. service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Stwórz/przyłącz się do wideokonferencji service.gui.CREATE_VIDEO_CONFERENCE=Utwórz wideokonferencję dla tego pokoju rozmów service.gui.CONTACT_INFO_NOT_SUPPORTED=Ten kontakt nie obsługuje sieciowej informacji o kontakcie service.gui.CUT=&Wytnij -service.gui.DATE=Data service.gui.DELETE=Usuń service.gui.DENY=O&dmów service.gui.DESKTOP_SHARING_WARNING=Czy na pewno chcesz włączyć udostępnianie ekranu?
    Kliknięcie OK pozwoli obecnym rozmówcom zobaczyć twój ekran. @@ -196,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Rozłączony service.gui.DND_STATUS=Nie przeszkadzać service.gui.DO_NOT_ASK_AGAIN=Nie pytaj więcej service.gui.DO_NOT_SHOW_AGAIN=Nie wyświetlaj więcej tej wiadomości -service.gui.DOWNLOAD_NOW=&Pobierz teraz service.gui.DRAG_FOR_SHARING=Przeciągnij tutaj, aby udostępnić... service.gui.DURATION=czas trwania rozmowy service.gui.DESTROY_CHATROOM=Skasuj pokój rozmów @@ -217,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Otrzymano błąd od {0} service.gui.ESTIMATED_TIME=Przewidywany czas: service.gui.EVENTS=Zdarzenia service.gui.EXIT=&Wyjście -service.gui.EXTENDED_CRITERIA=Rozszerzone kryteria service.gui.GENERAL=Ogólne service.gui.GENERAL_ERROR=Błąd ogólny service.gui.GROUP_NAME=Nazwa grupy @@ -259,7 +250,6 @@ service.gui.FONT_ITALIC=Kursywa service.gui.FONT_SIZE=Rozmiar service.gui.FONT_STYLE=Styl service.gui.FONT_UNDERLINE=Podkreślenie -service.gui.FROM={0} z {1} service.gui.GRANT_OWNERSHIP=Przyznaj prawa właściciela... service.gui.GRANT_ADMIN=Przyznaj prawa administratora... service.gui.GRANT_MODERATOR=Przyznaj prawa moderatora... @@ -285,14 +275,14 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Czy na pewno chcesz trwale usunąć wszys service.gui.HISTORY_REMOVE_ERROR=Błąd przy usuwaniu wiadomości. service.gui.HOME=Telefon domowy service.gui.HOME_PAGE=Strona domowa -service.gui.HOUR=Godzina service.gui.ICE=ICE service.gui.IDENTIFIER=Identyfikator service.gui.IGNORE=&Ignoruj service.gui.INSERT_SMILEY=Wstaw emotikonę service.gui.INCOMING_CALL=Rozmowa przychodząca od: {0} -service.gui.INCOMING_SCREEN_SHARE=Rozmowa przychodząca od: {0} +service.gui.INCOMING_SCREEN_SHARE=Przychodzący ekran współdzielony otrzymany od: {0} service.gui.INCOMING_CALL_STATUS=Połączenie przychodzące +service.gui.INSTANT_MESSAGINGS=Komunikatory Internetowe service.gui.IM=IM service.gui.INITIATING_CALL_STATUS=Nawiązuję połączenie service.gui.INVITATION=Tekst zaproszenia @@ -305,15 +295,12 @@ service.gui.INVITE_CONTACT_TO_CHAT=Zaproś kontakty do czatu. service.gui.INVITE_CONTACT_TO_CALL=Zaproś kontakty do rozmowy. service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Zaproś kontakty do mostu wideo service.gui.INVITE_REASON=Powód zaproszenia -service.gui.IS_CALLING=dzwoni... +service.gui.IS_CALLING={0} dzwoni... service.gui.IS_NOW={0} jest teraz {1} -service.gui.JITSI_WARNING=SIP Communicator zmienił nazwę na Jitsi.
    Jeśli chcesz, aby Twoja wersja w dalszym ciągu była aktualizowana pobierz Jitsi teraz.
    Przepraszamy za wszelkie niedogodności.
    Jitsi dev Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator staje się Jitsi service.gui.JOIN=&Dołącz się service.gui.JOIN_AS=D&ołącz się jako service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Dołącz do istniejącej konferencji wideo service.gui.JOIN_VIDEO=Połącz z wideo -service.gui.CLOSE_CHAT_ROOM_DIALOG=Z&amknij service.gui.JOB_TITLE=Zawód service.gui.JOIN_CHAT_ROOM=&Dołącz do kanału... service.gui.JOIN_CHAT_ROOM_TITLE=Dołącz do kanału @@ -326,28 +313,33 @@ service.gui.KICK_FAILED=Wyrzucenie nie powiodło się service.gui.KICK_FAILED_GENERAL_ERROR=Wyrzucenie nie powiodło się {0}. Wystąpił ogólny błąd serwera. service.gui.KICK_FAILED_NOT_ALLOWED=Wyrzucenie nie powiodło się {0}. Właściciel i administrator pokoju nie mogą zostać wyrzuceni. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Wyrzucenie nie powiodło się {0}. Nie masz wystarczających praw, by to zrobić. -service.gui.LAST=Ostatni service.gui.LAST_NAME=Nazwisko service.gui.LEAVE=&Wyjdź service.gui.LIMIT_REACHED_FOR_IP=Masz zbyt wiele istniejących połączeń z lokalnego adresu IP i serwer {0} nie pozwala na utworzenie kolejnych. service.gui.LIST=Lista service.gui.LOADING_ROOMS=Wczytuję kanały... +service.gui.LOADING=Ładowanie... +service.gui.LOCALLY_ON_HOLD_STATUS=Lokalnie zawieszone +service.gui.LOGIN_NETWORK_ERROR=Nie można zalogować się na konto: Nazwa użytkownika: {0}, nazwa serwera: {1}, z powodu awarii sieci. Proszę sprawdzić swoje połączenie sieciowe. service.gui.LOGIN_GENERAL_ERROR=Wystąpił błąd podczas logowania na konto: nazwa użytkownika: {0}, nazwa serwera: {1}:{2}. +service.gui.LOGIN_INTERNAL_ERROR=Wystąpił błąd podczas logowania się na konto: Nazwa użytkownika: {0}, nazwa serwera: {1}. Jest to najprawdopodobniej wewnętrzny błąd aplikacji. Proszę zgłosić problem do naszych programistów (dev@jitsi.java.net). +service.gui.LOGIN_INVALID_PROPERTIES_ERROR=Nie można zalogować się na konto: Nazwa użytkownika: {0}, nazwa serwera: {1}, ze względu na problem z konfiguracją konta. Proszę sprawdzić konfigurację swojego konta. service.gui.LOGOFF_NOT_SUCCEEDED=Wystąpił błąd podczas wylogowywania z konta: nazwa użytkownika: {0}, nazwa serwera: {1}. +service.gui.LOW_QUALITY=Niska jakość service.gui.MEMBER=członek +service.gui.MERGE_TO_CALL=Złącz wszystkie połączenia service.gui.MESSAGE=Wiadomość service.gui.MISSED_CALLS_TOOL_TIP=Nieodebrane rozmowy od: service.gui.MISSED_CALLS_MORE_TOOL_TIP= i {0} innych service.gui.MODERATOR=moderator -service.gui.MORE=Pokaż więcej -service.gui.MORE_LABEL=Przenieś +service.gui.MORE_LABEL=Więcej service.gui.MOVE=Przenieś service.gui.MOVE_SUBCONTACT=&Przenieś kontakt service.gui.MOVE_SUBCONTACT_MSG=Zaznacz kontakt lub grupę, do których chcesz przenieść wybrany kontakt. +service.gui.MOVE_SUBCONTACT_FAILED=Kontakt wybrany przez ciebie jest taki sam jak \n źródłowy. Proszę wybrać inny kontakt! service.gui.MOVE_SUBCONTACT_QUESTION=Czy na pewno chcesz przenieść {0} do {1}? service.gui.MOVE_TO_GROUP=&Przenieś do grupy service.gui.MOVE_CONTACT=&Przenieś kontakt -service.gui.MOVE_CONTACT_ERROR=&Kontakt nie może zostać przeniesiony service.gui.MSG_DELIVERY_FAILURE=Powyższa wiadomość nie może być dostarczona service.gui.MSG_DELIVERY_NOT_SUPPORTED=Protokół, którego używasz nie obsługuje wiadomości w trybie offline. Należy poczekać, aż {0} będzie znowu dostępny. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Wystąpił błąd wewnętrzny. Możesz pomóc go naprawić zgłaszając go tutaj http://jitsi.org/Developement/BugsAndIssues. @@ -361,7 +353,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Musisz mieć połączenie z siecią, że service.gui.MULTIPLE_LOGINS=Jesteś zalogowany więcej niż jeden raz z tego samego konta. Użytkownik: {0}, serwer: {1} jest aktualnie odłączony. service.gui.MY_CHAT_ROOMS=Dodaj pokój rozmów service.gui.MY_CHAT_ROOMS_TITLE=Moje pokoje rozmów -service.gui.MUTE=Wycisz service.gui.MUTUALLY_ON_HOLD_STATUS=Obustronnie zawieś połączenie service.gui.NAME=Nazwa service.gui.NETWORK=Sieć @@ -376,6 +367,10 @@ service.gui.NICKNAME=Nick: service.gui.NO=Nie service.gui.NONE=Brak service.gui.NO_CAMERA_AVAILABLE=Brak dostępnej kamery +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=Udostępnianie pulpitu nie jest obsługiwane przez ten protokół +service.gui.NO_VIDEO_ENCODINGS=Brak kodeka wideo dla wybranej konfiguracji +service.gui.NO_VIDEO_FOR_PROTOCOL=Wideo nie jest wspierane przez ten protokół +service.gui.NO_AVAILABLE_ROOMS=Lista pokoi dla tego serwera nie jest aktualnie dostępna. service.gui.NO_CONTACTS_FOUND=Nie znaleziono pasujących kontaktów. Naciśnij Ctrl+Enter, aby zadzwonić do {0} lub użyj poniższych przycisków. service.gui.NO_CONTACTS_FOUND_SHORT=Nie znaleziono pasujących kontaktów. service.gui.NO_MESSAGE=Brak wiadomości @@ -384,7 +379,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Spoza listy kontaktów service.gui.SD_QUALITY=Standartowa jakość service.gui.OFFLINE=Niedostępny service.gui.OK=&OK -service.gui.OLDER_CALLS=Starsze połączenia service.gui.ONLINE=Dostępny service.gui.OPEN=Otwórz service.gui.OPEN_FILE_FROM_IMAGE=Podwójne kliknięcie otworzy plik. @@ -396,30 +390,40 @@ service.gui.OPEN_ON_ACTIVITY=otwórz kiedy aktywny service.gui.OPEN_ON_MESSAGE=Tylko dla wiadomości service.gui.OPEN_ON_IMPORTANT_MESSAGE=Tylko dla ważnych wiadomości service.gui.OR=lub -service.gui.OR_ENTER_PHONE_NUMBER=Lub wprowadź tu number telefonu... service.gui.ORGANIZATION=Organizacja service.gui.OTHER=Inne service.gui.chat.role.OWNER=Właściciel service.gui.chat.role.ADMINISTRATOR=administrator -service.gui.chat.role.MODERATOR=moderator -service.gui.chat.role.MEMBER=członek +service.gui.chat.role.MODERATOR=Moderator +service.gui.chat.role.MEMBER=Członek +service.gui.chat.role.GUEST=Gość service.gui.OWNER=właściciel pokoju service.gui.PASSWORD=Hasło service.gui.PASSWORD_CHANGE_FAILURE=Zmiana hasła nie powiodła się service.gui.PASSWORD_CHANGE_SUCCESS=Hasło główne zostało zmienione service.gui.PASTE=&Wklej +service.gui.PERSONAL=Osobiste service.gui.PORT=Port +service.gui.POSTAL_CODE=Kod pocztowy service.gui.PREFERENCES=Ustawienia +service.gui.PREFIX=Przedrostek service.gui.PRESENCE=Dostępność service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' wyświetli propozycje +service.gui.PRESS_FOR_CALL_INFO=Naciśnij aby uzyskać informację o połączeniu service.gui.PREVIOUS=Poprzedni -service.gui.PREVIOUS_TOOLTIP=Przeglądaj starsze połączenia service.gui.PRINT=&Drukuj service.gui.PROACTIVE_NOTIFICATION=pisze wiadomość +service.gui.PROBLEMS_ENCOUNTERED=Napotkane problemy service.gui.PROTOCOL=Protokół +service.gui.PUT_OFF_HOLD=Zawieś +service.gui.PUT_ON_HOLD=Zawieś service.gui.QUIT=&Zakończ service.gui.READY=Gotowe +service.gui.RECENT_MESSAGES=Ostatnie konwersacje/rozmowy service.gui.REASON=Powód +service.gui.RECEIVED={0} otrzymał +service.gui.RE_REQUEST_AUTHORIZATION=Ponownie poproś o autoryzację +service.gui.REFERRED_STATUS=Odnosi się service.gui.REJECT=&Odrzuć service.gui.REMEMBER_PASSWORD=Zapamiętaj hasło service.gui.REMOVE=&Usuń @@ -427,28 +431,30 @@ service.gui.REMOVE_ACCOUNT=&Usuń konto service.gui.REMOVE_ACCOUNT_MESSAGE=Czy na pewno chcesz usunąć to konto? service.gui.REMOVE_CONTACT=&Usuń kontakt service.gui.REMOVE_CONTACT_TEXT=
    Czy na pewno chcesz usunąć {0}
    z listy kontaktów?
    +service.gui.REMOVE_CONTACT_NOT_CONNECTED=Musisz być połączony w celu usunięcia tego kontaktu. Zaloguj się i spróbuj ponownie. service.gui.REMOVE_GROUP=&Usuń grupę +service.gui.REMOTELY_ON_HOLD_STATUS=Zdalnie zawieszony service.gui.RENAME=&Zmień nazwę service.gui.RENAME_CONTACT=&Zmień nazwę kontaktu service.gui.RENAME_CONTACT_WIZARD=W poniższym polu wpisz nazwę, którą chcesz używać dla tego kontaktu. service.gui.RENAME_GROUP=&Zmień nazwę grupy service.gui.RENAME_GROUP_INFO=W poniższym polu wpisz nazwę, którą chcesz używać dla tej grupy. +service.gui.RENAME_CLEAR_USER_DEFINED=Przywróć +service.gui.RINGING_STATUS=Dzwoni +service.gui.REQUEST=&Żądanie +service.gui.REQUEST_AUTHORIZATION=&Poproś o autoryzację service.gui.RETRY=Ponów service.gui.SAVE=&Zapisz service.gui.SEARCH=&Wyszukiwanie +service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Kliknij przycisk poniżej, aby zobaczyć wszystkie czaty istniejące na wybranym serwerze. Następnie wybierz jeden do którego chcesz dołączyć i kliknij przycisk połącz. +service.gui.SEARCH_STRING_CONTACT_SOURCE=Wyszukane kontakty service.gui.SECURITY=Zabezpieczenia -service.gui.SELECT_ACCOUNT=Wybierz konto service.gui.SELECT_COLOR=Wybierz kolor service.gui.SELECT_GROUP=Wybierz grupę -service.gui.SELECT_GROUP_WIZARD_MSG=Poniższa lista zawiera wszystkie grupy z twojej listy kontaktów. Wybierz tę, do której chcesz dodać nowy kontakt. service.gui.SELECT_NO_GROUP=Brak grup -service.gui.SELECT_GROUP_WIZARD=Określ grupę -service.gui.SELECT_PROVIDERS_WIZARD=Wybierz konto service.gui.SEND=&Wyślij service.gui.SEND_FILE=Wyślij &plik -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Brak informacji o tym kontakcie. service.gui.SEND_MESSAGE=&Wyślij wiadomość -service.gui.SEND_AS_SMS=Wyślij jako SMS service.gui.SEND_SMS=W&yślij SMS service.gui.SEND_SMS_DETAILS=Pamiętaj, że należy wpisywać numery z kodem kraju; dla Polski +48 (np. +48777000000) service.gui.SEND_SMS_NOT_SUPPORTED=Wybrany protokół nie obsługuje SMS-ów. @@ -468,6 +474,11 @@ service.gui.TOOLS=Na&rzędzia service.gui.TO=&Do: service.gui.UNKNOWN=Nieznany użytkownik service.gui.VIDEO_CALL=&Rozmowa wideo +service.gui.VIEW=&Widok +service.gui.VIEW_HISTORY=Pokaż &historię +service.gui.VIEW_SMILEYS=Pokaz &buźki +service.gui.VIEW_TOOLBAR=Pokaż &pasek narzedzi +service.gui.VIEW_SIMPLE_CHAT_THEME=prosty motyw/widok czatu service.gui.VOICEMAIL_NEW_OLD_RECEIVED={0} nowych i {1} starych wiadomości service.gui.VOICEMAIL_NEW_RECEIVED={0} nowych wiadomości service.gui.VOICEMAIL_OLD_RECEIVED={0} starych wiadomości @@ -475,15 +486,12 @@ service.gui.VOICEMAIL_NO_MESSAGES=Brak wiadomości. service.gui.VOLUME_CONTROL_TOOL_TIP=Reguluj głośność service.gui.WARNING=Ostrzeżenie service.gui.YES=Tak -service.gui.YESTERDAY=Wczoraj -service.gui.EXISTING_ACCOUNT_ERROR=Wybrane konto zostało już zainstalowane. service.gui.ACTIVATE=Włącz service.gui.DEACTIVATE=Wyłącz service.gui.NEW=Nowa service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Włącz tryb pełnoekranowy service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Wyłącz tryb pełnoekranowy service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Pokaż/ukryj lokalne wideo -service.gui.UPDATE=Aktualizuj service.gui.VIDEO_PHONE=Wideo service.gui.PHONE=Telefon service.gui.PHONES=Telefony @@ -502,10 +510,15 @@ service.gui.OCTOBER=PAŹ service.gui.NOVEMBER=LIS service.gui.DECEMBER=GRU -service.gui.callinfo.VIEW_CERTIFICATE=Pokaż certyfikat +service.gui.callinfo.VIEW_CERTIFICATE=Wyświetl certyfikat service.gui.callinfo.MEDIA_STREAM_RTP=RTP service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_O=Organizacja: service.gui.CERT_INFO_C=Kraj: service.gui.CERT_INFO_ST=Region: @@ -518,11 +531,9 @@ service.gui.CERT_INFO_VER=Wersja: service.gui.CERT_INFO_SIGN_ALG=Algorytm podpisu: service.gui.CERT_INFO_ALG=Algorytm: service.gui.CERT_INFO_PUB_KEY=Klucz publiczny: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bajtów: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bitów service.gui.CERT_INFO_KEY_SIZE=Długość klucza: service.gui.CERT_INFO_SIGN=Podpis: -service.gui.CONTINUE=Kontynuuj service.gui.SHOW_CERT=Pokaż certyfikat service.gui.HIDE_CERT=Ukryj certyfikat @@ -541,14 +552,9 @@ service.gui.avatar.imagepicker.IMAGE_PICKER=Obraz service.gui.avatar.imagepicker.RESET=Resetuj service.gui.avatar.imagepicker.SET=Ustaw service.gui.avatar.imagepicker.TAKE_PHOTO=Zrób zdjęcie -service.gui.avatar.imagepicker.WEBCAM_ERROR=Błąd kamery internetowej -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ # systray @@ -562,9 +568,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=wybierz sieć # LDAP impl.ldap.CONFIG_FORM_TITLE=Konfiguracja LDAP impl.ldap.GENERAL=Ogólne -impl.ldap.NEW=Nowy impl.ldap.EDIT=edytuj -impl.ldap.REMOVE=Usuń impl.ldap.ENABLED=Włączony impl.ldap.SERVER_NAME=Nazwa serwera impl.ldap.SERVER_NAME_EXAMPLE=Mój serwer LDAP @@ -580,6 +584,10 @@ impl.ldap.PASSWORD=Hasło impl.ldap.MAIL_FIELD_EXAMPLE=E-mail: impl.ldap.MAILSUFFIX_FIELD_EXAMPLE=@domena.org (nie zapomnij dodać '@') +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Książka adresowa plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Włącz wyszukiwanie w książce adresowej MacOSX @@ -587,9 +595,7 @@ plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK=Włącz wyszukiwanie Microsoft Outlook # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Kontakty Google -impl.googlecontacts.NEW=Nowy impl.googlecontacts.EDIT=edytuj -impl.googlecontacts.REMOVE=Usuń impl.googlecontacts.ENABLED=Włączony impl.googlecontacts.ACCOUNT_NAME=Nazwa konta impl.googlecontacts.SAVE=Zapisz @@ -607,11 +613,12 @@ plugin.accountinfo.NICKNAME=Nick: plugin.accountinfo.AGE=Wiek: plugin.accountinfo.BDAY=Data urodzenia: plugin.accountinfo.GENDER=Płeć: +plugin.accountinfo.CITY=Miasto +plugin.accountinfo.POST=Kod pocztowy +plugin.accountinfo.COUNTRY=Kraj plugin.accountinfo.EMAIL=E-mail: plugin.accountinfo.PHONE=Telefon: -plugin.accountinfo.USER_PICTURES=Zdjęcia użytkownika -plugin.accountinfo.CHANGE=Zmień -plugin.accountinfo.ONLY_MESSAGE=Tylko wiadomości +plugin.accountinfo.JOB_TITLE=Zawód # connection info @@ -626,27 +633,11 @@ plugin.aimaccregwizz.USERNAME=Nazwa ekranowa AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nazwa użytkownika i hasło plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Zarejestruj nowe konto: plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Jeżeli nie masz konta AIM, kliknij ten przycisk, żeby je utworzyć. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Nie uwzględniaj domyślnych opcji serwera # branding plugin.branding.ABOUT_WINDOW_TITLE=O {0} plugin.branding.ABOUT_MENU_ENTRY=&O programie -# Dict protocol -service.protocol.DICTIONARIES=Słowniki -plugin.dictaccregwizz.ANY_DICTIONARY=Dowolny słownik -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Dowolny słownik z {0} -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Protokół Dict -plugin.dictaccregwizz.SERVER_INFO=Informacje o serwerze -plugin.dictaccregwizz.STRATEGY_SELECTION=Wybór strategii -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informacje o koncie Dict - -# facebookaccregwizz -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protokół czatu Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nazwa użytkownika: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nazwa użytkownika i hasło # generalconfig plugin.generalconfig.AUTO_START=Uruchom automatycznie {0} po uruchomieniu systemu @@ -654,8 +645,6 @@ plugin.generalconfig.LOG_HISTORY=Zapisuj historię czatów plugin.generalconfig.SHOW_HISTORY=Wyświetl plugin.generalconfig.HISTORY_SIZE=ostatnich wiadomości w nowym czacie plugin.generalconfig.SEND_MESSAGES_WITH=Wysyłaj wiadomości po naciśnięciu: -plugin.generalconfig.TRANSPARENCY=Przezroczystość -plugin.generalconfig.ENABLE_TRANSPARENCY=Włącz przezroczystość plugin.generalconfig.DEFAULT_LANGUAGE=Język interfejsu plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Zmiany zostaną zastosowane po ponownym uruchomieniu programu. plugin.generalconfig.SIP_CLIENT_PORT=Port klienta SIP @@ -686,11 +675,12 @@ plugin.ircaccregwizz.INFO_PASSWORD=Większość serwerów IRC nie wymaga hasła. plugin.ircaccregwizz.USE_DEFAULT_PORT=Używaj domyślnego portu plugin.ircaccregwizz.HOST=Nazwa hosta: plugin.ircaccregwizz.IRC_SERVER=Serwer +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=uwierzytelnianie {0} +plugin.ircaccregwizz.SASL_USERNAME=Nazwa użytkownika # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Protokół XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Potwierdź hasło -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=Nazwa użytkownika i hasło plugin.jabberaccregwizz.CSERVER=Serwer plugin.jabberaccregwizz.NEW_ACCOUNT_TITLE=Rejestracja nowego konta XMPP plugin.jabberaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Utwórz darmowe konto XMPP @@ -699,13 +689,9 @@ plugin.jabberaccregwizz.CHOOSE=&Wybierz plugin.jabberaccregwizz.SERVER_COLUMN=Serwer plugin.jabberaccregwizz.COMMENT_COLUMN=Komentarz plugin.jabberaccregwizz.PRIORITY=Priorytet -plugin.jabberaccregwizz.XMPP_ERROR=Błąd XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Nieznany błąd XMPP. Sprawdź, czy nazwa serwera jest poprawna. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Podane hasła nie są takie same. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Przestaw domyślne opcje serwera -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Opcje zaawansowane plugin.jabberaccregwizz.USE_ICE=Używaj ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Używaj Google Jingle/ICE (funkcja eksperymentalna) plugin.jabberaccregwizz.TURN_USERNAME=Nazwa użytkownika TURN plugin.jabberaccregwizz.IP_ADDRESS=Adres IP plugin.jabberaccregwizz.ADD_STUN_SERVER=Dodaj serwer STUN @@ -716,29 +702,14 @@ plugin.jabberaccregwizz.NO_STUN_USERNAME=Wpisz ważną nazwę użytkownika serwe plugin.jabberaccregwizz.JID_ADDRESS=Adres JID plugin.jabberaccregwizz.USE_UPNP=Używaj UPnP plugin.jabberaccregwizz.EXISTING_ACCOUNT=Istniejące konto XMPP -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Potwierdź nowe hasło plugin.jabberaccregwizz.ENCODINGS=Kodowania plugin.jabberaccregwizz.AUDIO=Audio plugin.jabberaccregwizz.VIDEO=Wideo plugin.jabberaccregwizz.RESET=Resetuj -# mailbox -plugin.mailbox.OUTGOING=Wiadomość wychodząca: -plugin.mailbox.INCOMING=Wiadomości przychodzące: -plugin.mailbox.CONFIRM=Potwierdź -plugin.mailbox.DEFAULTS=Domyślne -plugin.mailbox.MAILBOX=Skrzynka pocztowa - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protokół do połączeń i czatu w usłudze MSN. -plugin.msnaccregwizz.USERNAME=E-mail: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Nazwa użytkownika i hasło - # plugin manager plugin.pluginmanager.INSTALL=Zainstaluj plugin.pluginmanager.UNINSTALL=Odinstaluj -plugin.pluginmanager.UPDATE=Aktualizuj plugin.pluginmanager.PLUGINS=Wtyczki plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Wybierz plik @@ -761,10 +732,8 @@ plugin.sipaccregwizz.REGISTRAR=Rejestrator plugin.sipaccregwizz.SERVER_PORT=Port serwera plugin.sipaccregwizz.PROXY=Serwer pośredniczący plugin.sipaccregwizz.PROXY_PORT=Port serwera pośredniczącego -plugin.sipaccregwizz.ADVANCED_OPTIONS=Opcje zaawansowane plugin.sipaccregwizz.PROXY_OPTIONS=Opcje serwera plugin.sipaccregwizz.PROXY_AUTO=Konfiguruj pośrednika automatycznie -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Uchyl domyślne opcje serwera plugin.sipaccregwizz.DISPLAY_NAME=Wyświetlana nazwa plugin.sipaccregwizz.EXISTING_ACCOUNT=Istniejące konto SIP plugin.sipaccregwizz.CREATE_ACCOUNT=Utwórz darmowe konto SIP @@ -773,6 +742,7 @@ plugin.sipaccregwizz.CLIST_TYPE=Typ plugin.sipaccregwizz.XCAP_USER=Użytkownik plugin.sipaccregwizz.XCAP_PASSWORD=Hasło plugin.sipaccregwizz.NOT_SAME_PASSWORD=Podane hasła nie są takie same. +#used from SecurityPanel # skin manager plugin.skinmanager.SKINS=Skórki @@ -780,13 +750,6 @@ plugin.skinmanager.DEFAULT_SKIN=Skórka domyślna plugin.skinmanager.ADD_NEW_SKIN=Dodaj nową skórkę... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Skórka domyślna programu. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Protokół nawiązywania połączeń ze zdalnymi maszynami przez SSH. -plugin.sshaccregwizz.USERNAME=Identyfikator konta: -plugin.sshaccregwizz.OPTIONAL=Opcjonalny -plugin.sshaccregwizz.ACCOUNT_DETAILS=Szczegóły konta - # status update plugin.autoaway.AUTO_STATUS=Automatyczny status "nie ma mnie" plugin.autoaway.ENABLE_CHANGE_STATUS=Zmień status, kiedy odejdę od komputera @@ -825,21 +788,6 @@ plugin.whiteboard.DESELECT=Odznacz plugin.whiteboard.DELETE=Usuń plugin.whiteboard.PROPERTIES=Właściwości -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protokół czatu w usłudze Yahoo. -plugin.yahooaccregwizz.USERNAME=Nazwa użytkownika: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Nazwa użytkownika i hasło - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Protokół usługi Zeroconf (Bonjour) -plugin.zeroaccregwizz.FIRST_NAME=Imię: -plugin.zeroaccregwizz.LAST_NAME=Nazwisko: -plugin.zeroaccregwizz.EMAIL=E-mail: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Zapamiętać kontakty Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Nazwa użytkownika i hasło -plugin.zeroaccregwizz.USERID=Nazwa użytkownika - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Protokół Google Talk plugin.googletalkaccregwizz.USERNAME=Nazwa użytkownika Google Talk @@ -852,18 +800,10 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, portal IP Telecommunicati plugin.iptelaccregwizz.USERNAME=Nazwa użytkownika plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Zarejestruj się na iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP i czat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Nazwa użytkownika plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Wprowadź hasło ponownie plugin.sip2sipaccregwizz.EMAIL=Adres e-mail -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Informacje o tej usłudze pod adresem
    http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.INFO_NOTE=Informacje o tej usłudze znajdziesz pod adresem http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Istniejące konto sip2sip.info -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Utwórz konto sip2sip.info - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && komunikator internetowy plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Informacje o tej usłudze pod adresem
    http://ippi.fr @@ -872,6 +812,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Istniejące konto ippi plugin.ippiaccregwizz.CREATE_ACCOUNT=Utwórz darmowe konto ippi # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Zamknij okno czatu plugin.keybindings.CHAT_COPY=Kopiuj plugin.keybindings.CHAT_CUT=Wytnij @@ -887,6 +828,7 @@ plugin.keybindings.OPEN_HISTORY=Wyświetl historię plugin.keybindings.OPEN_SMILIES=Pokaż emotikony plugin.keybindings.globalchooser.SHORTCUT_NAME=Nazwa plugin.keybindings.PLUGIN_NAME=Skróty klawiszowe +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Czat plugin.keybindings.MAIN=Główne @@ -902,6 +844,7 @@ plugin.notificationconfig.EXEC_PROG=Uruchom program: plugin.notificationconfig.DISPLAY_POPUP=Wyświetl wiadomość w wyskakującym oknie plugin.notificationconfig.POPUP_NOTIF_HANDLER=Typ wyskakujących powiadomień plugin.notificationconfig.tableheader.EXECUTE=Uruchom program +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Połączenie przychodzące plugin.notificationconfig.event.IncomingFile=Połączenie przychodzące plugin.notificationconfig.event.IncomingMessage=Wiadomości przychodzące @@ -950,6 +893,7 @@ impl.neomedia.configform.AUDIO=Audio impl.neomedia.configform.VIDEO=Wideo impl.neomedia.configform.H264=H.264 +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.main=Główne impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTCP @@ -974,7 +918,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Obecne hasło: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Wprowadź nowe hasło: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Wprowadź hasło ponownie: plugin.securityconfig.masterpassword.MP_TITLE=Hasło główne -plugin.securityconfig.masterpassword.MP_NOT_SET=(nieustawione) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Nie wprowadzono poprawnego hasła głównego. Spróbuj ponownie. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Hasło główne nie jest poprawne. plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Zmiana hasła nie powiodła się @@ -988,7 +931,6 @@ plugin.securityconfig.masterpassword.COL_NAME=Nazwa plugin.securityconfig.masterpassword.COL_PASSWORD=Hasło plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(nieznany) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nie mogę rozszyfrować) -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Usuń plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Usuń wszystkie plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Czy na pewno chcesz usunąć wszystkie hasła? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Usuń wszystkie hasła @@ -1034,7 +976,6 @@ plugin.globalproxy.PROXY_ADDRESS=Serwer proxy plugin.globalproxy.PROXY_PORT=Port proxy plugin.globalproxy.PROXY_USERNAME=Login proxy plugin.globalproxy.PROXY_PASSWORD=Hasło proxy -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1077,10 +1018,9 @@ plugin.dnsconfig.PARALLEL_DNS=Równoległy DNS plugin.dnsconfig.lblBackupResolver.text=Nazwa hosta plugin.dnsconfig.lblBackupPort.text=Port net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Ignoruj +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=O&dmów #plugin spellcheck -plugin.spellcheck.LANG=Język -plugin.spellcheck.EDIT_PERSONAL_DICT=Edycja plugin.spellcheck.ENABLE_SPELL_CHECK=Włącz sprawdzanie pisowni plugin.spellcheck.dialog.FIND=Znajdź następny plugin.spellcheck.dialog.REPLACE=Zastąp -- cgit v1.1 From 5bea30507968b63123b9f6a8647aabf1a6ae04b2 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:53:52 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1463 of 1505 strings translated (4 fuzzy). --- resources/languages/resources_ast.properties | 219 +++++---------------------- 1 file changed, 34 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_ast.properties b/resources/languages/resources_ast.properties index 980daac..bfba5d9 100644 --- a/resources/languages/resources_ast.properties +++ b/resources/languages/resources_ast.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Yo service.gui.ACCOUNT_REGISTRATION_WIZARD=Encontu pal rexistru de cuentes service.gui.ACCOUNTS=Cuentes service.gui.ADD=&Amestar -service.gui.ADD_ACCOUNT=Amestar cuenta service.gui.ADD_CONTACT=&Amestar contautu service.gui.ADD_AUTHORIZED_CONTACT=Amestar a {0} a la to llista contautos service.gui.ADD_CONTACT_TO_CONTACTLIST=Amestar el contautu a la to llista contautos @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Fallu al amestar el contautu service.gui.ADD_CONTACT_EXIST_ERROR=El contautu {0} yá esiste na to llista contautos. service.gui.ADD_CONTACT_NETWORK_ERROR=El sirvidor nun respondió la nuesa petición d'amestar el contautu cola ID: {0} . service.gui.ADD_CONTACT_NOT_SUPPORTED=Fallu al amestar contautu cola ID: {0} . Operación non sofitada. -service.gui.ADD_CONTACT_IDENTIFIER=Nel campu d'embaxo, pon l'identificador del contautu que te prestaría amestar. -service.gui.ADD_CONTACT_WIZARD=Encontu p'amestar contautos service.gui.ADD_CONTACT_NOT_CONNECTED=Necesites tar coneutáu p'amestar un contautu. Por favor, rexístrate nel fornidor esbilláu ya intentalo de nueves. service.gui.ADD_GROUP_LOCAL_ERROR=Fallu al amestar el grupu col nome: {0} . La torga asocedió nuna operación E/S llocal. service.gui.ADD_GROUP_EXIST_ERROR=El grupu {0} yá esiste na to llista contautos. Por favor, escueyi otru nome. service.gui.ADD_GROUP_NET_ERROR=Fallu al amestar el grupu col nome: {0} . El problema asocedió pola mor d'un fallu de rede. Por favor, comprueba la to conexón ya intentalo de nueves. service.gui.ADD_GROUP_ERROR=Fallu al amestar el grupu col nome: {0}. service.gui.ADD_GROUP_EMPTY_NAME=El nome del grupu nun tien de tar baleru. -service.gui.ADD_GROUP=Crear grupu -service.gui.ADD_SUBCONTACT=&Amestar socontautu service.gui.ADDRESS=Direición service.gui.ADMINISTRATOR=alministrador service.gui.ADVANCED=&Avanzáu -service.gui.ALL=&Too service.gui.ALL_CONTACTS=&Tolos contautos service.gui.ALTERNATE_ADDRESS=Alternar direición service.gui.APPLY=&Aplicar @@ -65,7 +70,6 @@ service.gui.AT=a les service.gui.AUTHORIZE=&Autorizar service.gui.AUTHORIZATION_ACCEPTED={0} aceutó la to solicitú d'autorización. service.gui.AUTHENTICATION_FAILED=Falló l''autenticación pa {0} . La contraseña que punxesti nun ye válida. -service.gui.AUTHENTICATION_REQUESTED=Autenticación riquida service.gui.AUTHENTICATION_REQUESTED_SERVER=El sirvidor {0} solicitó la to autenticación. service.gui.AUTHENTICATION_REJECTED={0} refugó la to solicitú d'autorización. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autenticación @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Nel campu d'embaxo, pues poner el to nomatu nu service.gui.CHANGE_NICKNAME_ERROR=Fallu camudando'l nomatu service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Yá esiste'l nomatu service.gui.CHANGE_VIDEO_QUALITY=Camudar calidá de vidéu remota -service.gui.CHAT_CONFERENCE_LABEL=Conferencies service.gui.CHAT_CONFERENCE_ITEM_LABEL=Conferencia de {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Yá s'alcuentra na sala de charra {0} . service.gui.CHAT_ROOM_CONFIGURATION=Configuración de la sala de charra {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT={0} coló service.gui.CHAT_ROOM_USER_KICKED=fosti espulsáu de {0} service.gui.CHAT_ROOM_USER_QUIT=coló {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Ta prohibíu'l dunviu de mensaxes (voz revocada) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Atroxa la sala de charra pa un usu futuru -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Desanicia la sala esbillada de la llista de sales atroxaes service.gui.CHAT_ROOM_NAME=Nome de la sala de charra service.gui.CLEAR_CUSTOM_MESSAGES=Llimpiar mensaxes personalizaos service.gui.ROOM_NAME=Sala de charra -service.gui.AUTOJOIN=Xunise automáticamente service.gui.CHANGE_PASSWORD=Camudar contraseña service.gui.CHAT_ROOM_NAME_INFO=Nel campu d'embaxo pon el nome de la sala de charra que te prestaría crear. service.gui.CHAT_ROOM_NOT_EXIST=La sala {0} nun fo alcontrada nel sirvidor {1}. Por favor, verifica si'l nome qu'escribiesti ye'l correutu. service.gui.CHAT_ROOM_NOT_CONNECTED=Necesites aniciar sesión pa xunite a la sala de charra {0} . service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Necesites aniciar sesión pa colar de la sala de charra. -service.gui.CHAT_ROOM_NOT_JOINED=Necesites xunite a la sala de charra pa cola fin de faer operaciones con ella. service.gui.CHAT_ROOM_OPTIONS=Opciones de la sala de charra service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=La sala de charra {0} rique d'un rexistru pa xunise. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=La sala de charra {0} solicitó una contraseña. @@ -151,22 +150,18 @@ service.gui.CLEAR=Llimpiar service.gui.CLOSE=Za&rrar service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Recibiesti fai menos de 2 segundos un mensax nuevu. ¿De xuru quies zarrar esta charra? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Tienes tresferencies de ficheros actives. ¿De xuru quies encaboxales toes? -service.gui.CONFIRM=Confirmar service.gui.CONNECTED_STATUS=Coneutáu service.gui.CONNECTING=Coneutando… service.gui.CONNECTING_STATUS=Coneutando service.gui.CONNECTING_EARLY_MEDIA_STATUS=Coneutando* service.gui.CONNECTION=Conexón -service.gui.CONNECTION_FAILED_MSG=Conexón fallida cola siguiente cuenta: Nome d'usuariu: {0} , Nome'l sirvidor: {1} . Por favor, comprueba la to conexón de rede o contauta col to alministrador de redes pa más información. service.gui.CONNECTION_EXPIRED_MSG=Anguaño tas desconeutáu del sirvidor {0} . service.gui.CONTACT_NAME=ID o númberu -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=El contautu escoyíu {0} nun sofita telefonía. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=El contautu escoyíu {0} nun sofita conferencies. service.gui.CONTACT_PAUSED_TYPING={0} posó d''escribir el mensax service.gui.CONTACT_TYPING={0} ta escribiendo un mensax service.gui.CONTACT_TYPING_SEND_FAILED=¡Fo!... nun pudimos dici-y a {0} que tabes escribiendo service.gui.CONTACT_INFO=&Información de contautu -service.gui.CONTACTLIST=Llista contautos service.gui.CONTACTS=Contautos service.gui.COPY=&Copiar service.gui.COPY_LINK=Copiar &enllaz @@ -176,27 +171,24 @@ service.gui.CREATE_CHAT_ROOM=&Crear sala de charra... service.gui.CREATE_CHAT_ROOM_ERROR=Fallu al crear la sala de cahrra {0} . service.gui.CREATE_CHAT_ROOM_WIZARD=Encontu pa la criación de sales de charra service.gui.CREATE_CONFERENCE_CALL=&Crear una llamada de conferencia... -service.gui.CREATE_CONFERENCE_CHAT=&Crear una charra de conferencia... service.gui.CREATE_GROUP=&Crear grupu... service.gui.CREATE_GROUP_NAME=Nel campu d'embaxo pon el nome'l grupu que te prestaría crear. -service.gui.CREATE_FIRST_GROUP_WIZARD=La to llista contautos nun tien dengún grupu. Por favor, crea un grupu primero (Ficheru/Crear grupu). service.gui.CREATE_VIDEO_BRIDGE=Crear una ponte &vidéu... service.gui.CREATE_VIDEO_BRIDGE_MENU=Crear una ponte &vidéu service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Crear / Xunise a una conferencia de vidéu service.gui.CREATE_VIDEO_CONFERENCE=Crear una videoconferencia nueva nesta sala de charra service.gui.CONTACT_INFO_NOT_SUPPORTED=Esti contautu nun sofita información de contautu web service.gui.CUT=F&rañir -service.gui.DATE=Data service.gui.DELETE=Desaniciar service.gui.DENY=&Refugar service.gui.DESKTOP_SHARING_WARNING=¿De xuru quies entamar la compartición de pantalla?
    Primi Val pa dexar a la xente nesta llamada ver la to pantalla. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Tas compartiendo la to pantalla service.gui.DIALPAD=Tecláu numbéricu service.gui.DISPLAY_NAME=Amosar nome service.gui.DISCONNECTED_STATUS=Desconeutáu service.gui.DND_STATUS=Nun cafiar service.gui.DO_NOT_ASK_AGAIN=Nun entrugar más service.gui.DO_NOT_SHOW_AGAIN=Nun amosar esti mensax más -service.gui.DOWNLOAD_NOW=&Baxar agora service.gui.DRAG_FOR_SHARING=Arrastra equí tolo que quies compartir... service.gui.DURATION=duración service.gui.DESTROY_CHATROOM=Destruyir sala de charra @@ -217,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Fallu recibíu de {0} service.gui.ESTIMATED_TIME=Tiempu estimáu: service.gui.EVENTS=Eventos service.gui.EXIT=C&olar -service.gui.EXTENDED_CRITERIA=Criteriu estendíu service.gui.GENERAL=Xeneral service.gui.GENERAL_ERROR=Fallu xeneral service.gui.GROUP_NAME=Nome del grupu @@ -259,7 +250,6 @@ service.gui.FONT_ITALIC=Cursiva service.gui.FONT_SIZE=Tamañu service.gui.FONT_STYLE=Estilu service.gui.FONT_UNDERLINE=Solliñar -service.gui.FROM={0} de {1} service.gui.GRANT_OWNERSHIP=Faer propietariu... service.gui.GRANT_ADMIN=Faer alministrador... service.gui.GRANT_MODERATOR=Faer llendador @@ -285,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=¿De xuru quies desaniciar dafechu tolos service.gui.HISTORY_REMOVE_ERROR=Fallu desaniciando los mensaxes atroxaos llocalmente. service.gui.HOME=Llar service.gui.HOME_PAGE=Páxina d'aniciu -service.gui.HOUR=Hora service.gui.ICE=ICE service.gui.IDENTIFIER=Identificador service.gui.IGNORE=&Inorar @@ -309,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Convidar contautos a la ponte de vid service.gui.INVITE_REASON=Razón d'invitación service.gui.IS_CALLING={0} ta llamando... service.gui.IS_NOW={0} ye agora {1} -service.gui.JITSI_WARNING=SIP Communicator fo renomáu apocayá como Jitsi.
    Si quies que la to versión tea anovada, entós baxa Jitsi agora.

    Sentimos cualaquier inconveniencia que puea causate ésto.

    L'equipu Jitsi Dev -service.gui.JITSI_WARNING_TITLE=SIP Communicator ye agora Jitsi service.gui.JOIN=&Xunise service.gui.JOIN_AS=X&unise como service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Xunise a una videoconferencia esistente service.gui.JOIN_VIDEO=Xunir vidéu -service.gui.CLOSE_CHAT_ROOM_DIALOG=Z&arrar service.gui.JOB_TITLE=Títulu'l trabayu service.gui.JOIN_CHAT_ROOM=&Xunise a la charra de charra... service.gui.JOIN_CHAT_ROOM_TITLE=Xunise a la sala de charra @@ -328,7 +314,6 @@ service.gui.KICK_FAILED=Espulsión fallida service.gui.KICK_FAILED_GENERAL_ERROR=Fallu al espulsar a {0} . Asocedió un fallu xeneral del sirvidor. service.gui.KICK_FAILED_NOT_ALLOWED=Fallu al espulsar a {0} . Nun puen espulsase al dueñu y l'alministrador la sala. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Fallu al espulsar a {0} . Nun tienes abondos privilexos pa fer esto. -service.gui.LAST=Caberu service.gui.LAST_NAME=Apellíos service.gui.LEAVE=&Colar service.gui.LIMIT_REACHED_FOR_IP=Tienes milenta rexistros esistentes dende la to direción IP llocal y el sirvidor {0} nun almite abrir dengún más d'ellos. @@ -348,7 +333,6 @@ service.gui.MESSAGE=Mensax service.gui.MISSED_CALLS_TOOL_TIP=Llamaes perdíes de: service.gui.MISSED_CALLS_MORE_TOOL_TIP= y {0} más service.gui.MODERATOR=llendador -service.gui.MORE=Ver más service.gui.MORE_LABEL=Más service.gui.MOVE=Mover service.gui.MOVE_SUBCONTACT=M&over contautu @@ -357,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=El contautu qu'escoyesti ye'l mesmu que\nl'or service.gui.MOVE_SUBCONTACT_QUESTION=¿De xuru quies mover {0} a {1} ? service.gui.MOVE_TO_GROUP=&Mover al grupu service.gui.MOVE_CONTACT=Mover contautu -service.gui.MOVE_CONTACT_ERROR=&El contautu nun pue movese service.gui.MSG_DELIVERY_FAILURE=Nun pudo entregase'l mensax d'enriba service.gui.MSG_DELIVERY_NOT_SUPPORTED=El protocolu que tas usando nun sofita mensaxes fuera de llinia. Pues intentar contautar con {0} pente medies d'otru protocolu o esperar fasta qu'elli/ella tea en llinia. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Asocedió un fallu internu. Esto pue ser de xuru un problema. Por favor, repórtalu equí: https://jitsi.org/Development/BugsAndIssues. @@ -371,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Deberíes tar coneutáu pa poder dunviar service.gui.MULTIPLE_LOGINS=Aniciesti sesión más d'una vegada cola mesma cuenta. La siguiente cuenta: Nome d'usuariu: {0} , Nome'l sirvidor: {1} ta anguaño desconeutada. service.gui.MY_CHAT_ROOMS=Amestar sala de charra service.gui.MY_CHAT_ROOMS_TITLE=Amestar sala de charra -service.gui.MUTE=Silenciar service.gui.MUTUALLY_ON_HOLD_STATUS=Dambos n'espera service.gui.NAME=Nome service.gui.NETWORK=Rede @@ -403,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Nun ta na llista contautos service.gui.SD_QUALITY=Calidá estándar service.gui.OFFLINE=Fuera de llinia service.gui.OK=&Val -service.gui.OLDER_CALLS=Llamaes más vieyes service.gui.ONLINE=En llinia service.gui.OPEN=Abrir service.gui.OPEN_FILE_FROM_IMAGE=Clic doblu p'abrir el ficheru. @@ -415,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Abrir al tar activu service.gui.OPEN_ON_MESSAGE=Abrir namái nel mensax service.gui.OPEN_ON_IMPORTANT_MESSAGE=Abrir namái en mensaxes importantes service.gui.OR=o -service.gui.OR_ENTER_PHONE_NUMBER=O pon equí'l númberu de teléfonu... service.gui.ORGANIZATION=Organización service.gui.OTHER=Otru service.gui.chat.role.OWNER=Dueñu @@ -440,7 +420,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Intru' pa suxerencies service.gui.PRESS_FOR_CALL_INFO=Primi pa información de la llamada service.gui.PRESS_TO_OPEN_CRM=Primi p'abrir l'aplicación CRM service.gui.PREVIOUS=Previu -service.gui.PREVIOUS_TOOLTIP=Restolar charres más vieyes service.gui.PRINT=&Imprentar service.gui.PROACTIVE_NOTIFICATION=ta escribiendo un mensax service.gui.PROBLEMS_ENCOUNTERED=Problemes alcontraos @@ -456,7 +435,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Tuviesti desconeutándote y reconeutánd service.gui.RE_REQUEST_AUTHORIZATION=Solicitar autorización de nueves service.gui.REFERRED_STATUS=Referíu service.gui.REJECT=&Refugar -service.gui.REMIND_ME_LATER=Recuérdamelo sero service.gui.REMEMBER_PASSWORD=Recordar contraseña service.gui.REMOVE=&Desaniciar service.gui.REMOVE_ACCOUNT=&Desaniciar cuenta @@ -482,29 +460,20 @@ service.gui.REVOKE_ADMIN=Revocar almin service.gui.REVOKE_MODERATOR=Revocar llendador service.gui.REVOKE_MEMBERSHIP=Revocar membresía service.gui.REVOKE_VOICE=Revocar voz -service.gui.ROOT_GROUP=Grupu raigañu service.gui.SAVE=&Atroxar -service.gui.SAVE_AS_DEFAULT=Atroxar como predetermináu service.gui.SEARCH=&Guetar service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Primi'l botón d'embaxo p'amosar toles sales de charra esistentes nel sirvidor esbilláu. Dempués esbilla a la que te prestaría xunite primiendo nel botón Xunise. service.gui.SEARCH_STRING_CONTACT_SOURCE=Contautu guetáu service.gui.SECURITY=Seguranza -service.gui.SELECT_ACCOUNT=Esbillar cuenta service.gui.SELECT_COLOR=Esbillar color service.gui.SELECT_GROUP=Esbillar grupu -service.gui.SELECT_GROUP_WIZARD_MSG=La llista d'embaxo contien tolos grupos na to llista contautos. Esbilla a la que te prestaría amestar el contautu nuevu. service.gui.SELECT_NO_GROUP=Ensin grupu -service.gui.SELECT_GROUP_WIZARD=Especificar grupu service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=La llista d'embaxo contien toles cuentes que sofiten la carauteristica de charra multi usuariu. Esbilla la que te prestaría usar pa criar la to sala de charres. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=La llista d'embaxo contien toles cuentes rexistraes. Esbilla cola que te prestaría comunicate col contautu nuevu. -service.gui.SELECT_PROVIDERS_WIZARD=Esbillar cuenta service.gui.SELECT_VIDEO_CONFERENCE=Esbillar conferencia de vidéu service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Esbilla una sala de charra de la llista y primi Val p'amestala. service.gui.SEND=&Dunviar service.gui.SEND_FILE=Dunviar &ficheru -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Nun hai información pa esti contautu. service.gui.SEND_MESSAGE=&Dunviar un mensax -service.gui.SEND_AS_SMS=Dunviar como SMS service.gui.SEND_PRIVATE_MESSAGE=Dunviar un mensax priváu service.gui.SEND_SMS=D&unviar SMS service.gui.SEND_SMS_DETAILS=Alcuérdate que necesites poner el númberu en formatu internacional. Exemp.: entamando per +34 pa ES por exemplu, +34999999999 @@ -543,7 +512,6 @@ service.gui.STREET=Cai service.gui.SUBJECT=Asuntu service.gui.SUMMARY=Resume service.gui.TELEPHONY=Telefonía -service.gui.TODAY=Güei service.gui.TOOLS=&Ferramientes service.gui.TRANSFER=Tres&ferir service.gui.TO=&A: @@ -553,7 +521,6 @@ service.gui.TRANSFER_CALL_TO=Tresferir a: service.gui.TRANSPARENCY_NOT_ENABLED=La tresparencia nun ta sofitada anguaño pola to configuración. service.gui.TYPE_YOUR_REQUEST=Escribi equí la to petición service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Nun podemos camudar la calidá de vidéu d'esta llamada. -service.gui.UNMUTE=Quitar silenciu service.gui.USER_IDENTIFIER=Indentificador d'usuariu: service.gui.USER_EXISTS_ERROR=Esti usuariu yá esiste na rede esbillada. Por favor, escueyi otru usuariu o rede. service.gui.USERNAME_NULL=Por favor, enllena'l to nome d'usuariu y contraseña. @@ -566,7 +533,6 @@ service.gui.USE_PROVISIONING=Usar aprovisionamientu en llinia service.gui.VALUE=Valor service.gui.VIDEO_CALL=&Llamada de vidéu service.gui.VIA=per -service.gui.VIA_SMS=Per SMS service.gui.VIEW=&Ver service.gui.VIEW_HISTORY=Ver &historia service.gui.VIEW_SMILEYS=Ver &fustaxes @@ -586,9 +552,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Axustar volume service.gui.WAITING_AUTHORIZATION=Esperando pola autorización service.gui.WARNING=Avisu service.gui.YES=Sí -service.gui.YESTERDAY=Ayeri -service.gui.EXISTING_ACCOUNT_ERROR=Yá ta intalada a cuenta que punxesti. -service.gui.NEW_MAIL=¡Tienes un corréu nuevu!
    De: {0} {1}
    Asuntu: {2}
    {3} ; service.gui.NEW_GMAIL_HEADER=Recibiesti un corréu nuevu na to bandexa d'entrada:
    {0} service.gui.NEW_GMAIL_MANY_HEADER=Recibiesti {2} correos nuevos na to bandexa d'entrada:
    {0} service.gui.NEW_GMAIL_FOOTER=ún o más correos ensin lleer na to bandexa d'entrada.
    @@ -612,7 +575,6 @@ service.gui.SECURITY_ERROR=Fallu de seguranza service.gui.SPEED=Velocidá: service.gui.SILENT_MEMBER=silenciar miembru service.gui.NON_SECURE_CONNECTION=Nun pue asegurase la conexón pa la cuenta {0} . Si quies coneutate a un sirvidor non seguru, por favor conseña "Almitir conexones non segures" nos axustes de la to cuenta -service.gui.UPDATE=Anovar service.gui.MOBILE_PHONE=Móvil service.gui.VIDEO_PHONE=Vidéu service.gui.WORK_PHONE=Trabayu @@ -647,12 +609,10 @@ service.gui.callinfo.CALL_INFORMATION=Información de llamada service.gui.callinfo.CALL_IDENTITY=Identidá service.gui.callinfo.PEER_COUNT=Participación service.gui.callinfo.IS_CONFERENCE_FOCUS=Enfocar charra -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Cifráu habilitáu service.gui.callinfo.CALL_TRANSPORT=Señalización de tresporte de llamada service.gui.callinfo.CALL_DURATION=Duración de llamada service.gui.callinfo.TLS_PROTOCOL=Protocolu TLS service.gui.callinfo.TLS_CIPHER_SUITE=Suit de cifráu TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Cadena del certificáu TLS del sirvidor service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Ta amosáu embaxo'l conteníu'l certificáu TLS. service.gui.callinfo.VIEW_CERTIFICATE=Ver certificáu service.gui.callinfo.CODEC=Codificador / Frecuencia @@ -662,7 +622,6 @@ service.gui.callinfo.AUDIO_INFO=Información d'audiu service.gui.callinfo.VIDEO_INFO=Información de vidéu service.gui.callinfo.LOCAL_IP=IP llocal / puertu service.gui.callinfo.REMOTE_IP=IP remota / puertu -service.gui.callinfo.BANDWITH=Anchor de banda service.gui.callinfo.LOSS_RATE=Tasa de perda service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -672,10 +631,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocolu d'intercambéu claves service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Candidatu ICE de triba estendida service.gui.callinfo.ICE_STATE=Estáu de procesamientu ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Axuntando candidatos service.gui.callinfo.ICE_STATE.RUNNING=Comprobaciones de conectividá service.gui.callinfo.ICE_STATE.COMPLETED=Completáu service.gui.callinfo.ICE_STATE.FAILED=Falló + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP llocal d'agospiu / Puertu service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=IP llocal reflexiva / Puertu service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=IP llocal tresmitida / Puertu @@ -696,10 +658,11 @@ service.gui.ALWAYS_TRUST=Confiar siempres nesti certificáu service.gui.CERT_DIALOG_TITLE=Verificar certificáu service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} nun pue verificar la identidá''l sirvidor al coneutase a
    {1}.

    Nun pue confiase nel certificáu, lo que quier dicir que la identida''l sirvidor nun pue verificase automáticamente.

    ¿Quies siguir coneutándote?
    Pa más información primi n'"Amosar certificáu". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} nun pue verificar la identidá del certificáu del sirvidor.

    Nun pue confiase nel certificáu, lo que quier dicir que la identida''l sirvidor nun pue
    verificase automáticamente. ¿Quies siguir coneutándote?

    Pa más información primi n''"Amosar certificáu". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} nun pue verificar la identidá''l veceru coneutáu.

    Nun pue confiase nel certificáu, lo que quier dicir que la identida''l sirvidor nun pue
    verificase automáticamente. ¿Quies siguir coneutándote?

    Pa más información primi n'"Amosar certificáu". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} nun pue verificar la identidá''l veceru {1}.

    Nun pue confiase nel certificáu, lo que quier dicir que la identida''l sirvidor nun pue
    verificase automáticamente. ¿Quies siguir coneutándote?

    Pa más información primi n''"Amosar certificáu". service.gui.CONTINUE_ANYWAY=Siguir de toes toes service.gui.CERT_INFO_CHAIN=Cadena del certificáu: + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nome común: service.gui.CERT_INFO_O=Organización: service.gui.CERT_INFO_C=Nome'l país: @@ -717,12 +680,10 @@ service.gui.CERT_INFO_SIGN_ALG=Algoritmu de robla: service.gui.CERT_INFO_PUB_KEY_INFO=Información de clave pública service.gui.CERT_INFO_ALG=Algoritmu: service.gui.CERT_INFO_PUB_KEY=Clave pública: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Esponente: service.gui.CERT_INFO_KEY_SIZE=Tamañu la clave: service.gui.CERT_INFO_SIGN=Robla: -service.gui.CONTINUE=Siguir service.gui.SHOW_CERT=Amosar certificáu service.gui.HIDE_CERT=Anubrir certificáu @@ -745,12 +706,9 @@ service.gui.security.SECURE_AUDIO=Audiu seguru service.gui.security.AUDIO_NOT_SECURED=Audiu non seguru service.gui.security.SECURE_VIDEO=Vidéu seguru service.gui.security.VIDEO_NOT_SECURED=Vidéu non seguru -service.gui.security.NO_VIDEO=Ensin vidéu -service.gui.security.CIPHER=Cifráu: {0} service.gui.security.CALL_SECURED_TOOLTIP=Llamada asegurada. Pa más información primi equí. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Llamada non asegurada. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Primi equí pa comparar el secretu de seguranza col to collaciu. -service.gui.security.COMPARE_WITH_PARTNER=Compara col to collaciu y primi nel candáu pa confirmar. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparar col collaciu: service.gui.security.STRING_COMPARED=¡Cadena comparada! @@ -768,20 +726,14 @@ service.gui.avatar.imagepicker.CLICK=Primi y sorrí service.gui.avatar.imagepicker.IMAGE_FILES=Ficheros d'imaxes service.gui.avatar.imagepicker.IMAGE_PICKER=Semeya service.gui.avatar.imagepicker.IMAGE_SIZE=Tamañu d'imax -service.gui.avatar.imagepicker.INITIALIZING=Aniciando service.gui.avatar.imagepicker.RESET=Reafitar service.gui.avatar.imagepicker.SET=Definir service.gui.avatar.imagepicker.TAKE_PHOTO=Fer una semeya -service.gui.avatar.imagepicker.WEBCAM_ERROR=Fallu de cámara web service.gui.security.encryption.required=¡Cifráu riquíu! service.protocol.ICE_FAILED=Nun pudo afitase la conexón (nun s'alcontró rempuesta y fallu d'ICE) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Fallu nel almacenamientu de llista contautos SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Nun puen lleese los recursos {0} . De {1} @@ -811,9 +763,7 @@ impl.ldap.QUERY_CUSTOM=Consulta automática impl.ldap.QUERY_CUSTOM_HINT=Usa {0} como un marcador pal terminu de gueta. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Amestar automáticamente comodines al términu de gueta impl.ldap.QUERY_PHOTO_INLINE=Amesta una foto con otros atributos -impl.ldap.NEW=Nuevu impl.ldap.EDIT=editar -impl.ldap.REMOVE=Desaniciar impl.ldap.ENABLED=Habilitáu impl.ldap.SERVER_NAME=Nome'l sirvidor impl.ldap.SERVER_NAME_EXAMPLE=El mio sirvidor LDAP @@ -846,6 +796,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=TeléfonuLlar impl.ldap.PHONE_PREFIX=Prefixu de teléfonu impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Llibreta de direiciones plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Habilitar gueta na llibreta de direiciones MacOSX @@ -860,9 +814,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Faer Outlook el to veceru de co # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google Contacs -impl.googlecontacts.NEW=Nuevu impl.googlecontacts.EDIT=editar -impl.googlecontacts.REMOVE=Desaniciar impl.googlecontacts.ENABLED=Habilitáu impl.googlecontacts.ACCOUNT_NAME=Nome de cuenta impl.googlecontacts.SAVE=Atroxar @@ -901,11 +853,8 @@ plugin.accountinfo.ORGANIZATION=Nome d'organización: plugin.accountinfo.JOB_TITLE=Títulu'l trabayu: plugin.accountinfo.ABOUT_ME=Tocante a min: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Semeyes d'usuariu plugin.accountinfo.GLOBAL_ICON=Usar iconu global plugin.accountinfo.LOCAL_ICON=Usar esti iconu: -plugin.accountinfo.CHANGE=Camudar -plugin.accountinfo.ONLY_MESSAGE=Namái mensaxes # connection info plugin.connectioninfo.TITLE=Información de conexón @@ -925,49 +874,12 @@ plugin.aimaccregwizz.USERNAME=Usuariu AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Usuariu y contraseña plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Rexistrar cuenta nueva plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Nel casu que nun tengas una cuenta AIM, primi nesti botón pa crear una nueva. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Trocar les opciones predeterminaes del sirvidor # branding plugin.branding.ABOUT_WINDOW_TITLE=Tocante a {0} plugin.branding.LOGO_MESSAGE=VoIP y mensaxeru nel intre de códigu llibre -plugin.branding.LOADING=Cargando plugin.branding.ABOUT_MENU_ENTRY=&Tocante a -plugin.branding.WELCOME_MESSAGE=
    {1} ta anguaño baxo desendolcu activu. La versión que tas executando ye namái esperimental y PUE QUE NUN furrule como s'espera. Por favor, consulta a {2} pa más información.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Tolos drechos reservaos. Visita https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi ta distribuyíu baxo los terminos de llicencia LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Diccionarios -plugin.dictaccregwizz.ANY_DICTIONARY=Cualaquier diccionariu -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Cualaquier diccionariu de {0} -plugin.dictaccregwizz.FIRST_MATCH=Primera coincidencia -plugin.dictaccregwizz.NO_MATCH=Nun hai coincidencies -plugin.dictaccregwizz.MATCH_RESULT=Nun hai definiciones alcontraes pa "{0}", quiciabes quixesti dicir:\n -plugin.dictaccregwizz.INVALID_DATABASE=El diccionariu "{0}" d'anguaño nun esiste nel sirvidor. -plugin.dictaccregwizz.INVALID_STRATEGY=La estratexa d'anguaño nun ta disponible nel sirvidor. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=El serviciu de protocolu Dict -plugin.dictaccregwizz.HOST=Agospiu -plugin.dictaccregwizz.SERVER_INFO=Informaciones del sirvidor -plugin.dictaccregwizz.STRATEGY_SELECTION=Esbilla d'estratexa -plugin.dictaccregwizz.STRATEGY_LIST=Llista d'estratexes: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Guetar estratexa -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=La estratexa úsase pa guetar pallabres asemeyaes, si nun s'alcuentra una torna, ye gracies a los diferentes enfoques. Por exemplu, les estratexes de prefixos guetarán pallabres qu'entamen como la pallabra que te prestaría tornar. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Información de cuenta Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Esti encontu creará la primer cuenta Dict pa tigo en dict.org.\n\nPues amestar un diccionariu nuevu diendo al encontu pal rexistru cuentes. Enllena'l campu l'agospiu col diccionariu que te prestaría amestar. -plugin.dictaccregwizz.THREAD_CONNECT=Intentando coneutase al sirvidor -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Intentu de conexón fallíu, esti nun ye un sirvidor dict o'l sirvidor ta fuera de llinia -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Recibiendo estratexes -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Nun s'alcuentra estratexa dala nel sirvidor -plugin.dictaccregwizz.POPULATE_LIST=Xenerando llista -plugin.dictaccregwizz.CLOSING_CONNECTION=
    Pa usar el Facebook Chat tienes de crear un "nome d'usuariu"
    dende la páxina d'"Axustes de cuenta" na páxina de Faceook.


    Nota: ¡Cuando crees l'usuariu tienes d'aniciar sesión dende la páxina web
    y esperar un pocoñín enantes de poder aniciar sesión col to nome d'usuariu nuevu!
    - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Pa usar el Facebook Chat tienes de crear un usuariu
    dende la páxina d'"Axustes de cuenta" en Faceook.


    Nota: ¡Cuando crees l'usuariu tienes d'aniciar sesión dende la páxina web
    y esperar un pocoñín enantes de poder aniciar sesión col to usuariu nuevu!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=El protocolu Facebook Chat -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nome d'usuariu: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nome d'usuariu y contraseña + # generalconfig plugin.generalconfig.AUTO_START=Aniciar {0} cuando l''ordenador se reanicie o prenda @@ -978,9 +890,6 @@ plugin.generalconfig.SHOW_HISTORY=Amosar plugin.generalconfig.HISTORY_SIZE=mensaxes recientes en charres nueves plugin.generalconfig.SEND_MESSAGES_WITH=Dunviar mensaxes con: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Trayer la ventana la charra al frente -plugin.generalconfig.ERROR_PERMISSION=Nun tienes abondos premisos pa desaniciar l'aniciu automáticu -plugin.generalconfig.TRANSPARENCY=Tresparencia -plugin.generalconfig.ENABLE_TRANSPARENCY=Habilitar tresparencia plugin.generalconfig.DEFAULT_LANGUAGE=Llingua d'interfaz plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Les tos camudancies fadrán efeutu nel prósimu reaniciu. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% tornáu @@ -1037,13 +946,15 @@ plugin.ircaccregwizz.HOST=Nome d'agospiu: plugin.ircaccregwizz.IRC_SERVER=Sirvidor plugin.ircaccregwizz.EXAMPLE_SERVER=Exem: chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Usar conexón segura +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autenticación +plugin.ircaccregwizz.SASL_USERNAME=Nome d'usuariu +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=La contraseña d'IRC d'enriba úsase pa l'autenticación SASL +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Resolver siempres nomes DNS pente proxy # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=El protocolu XMPP plugin.jabberaccregwizz.USERNAME=Nome d'usuariu XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmar contraseña -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID y contraseña plugin.jabberaccregwizz.CSERVER=Sirvidor plugin.jabberaccregwizz.SERVER=Coneutar al sirvidor plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Habilitar caltener vivu @@ -1059,13 +970,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Comentariu plugin.jabberaccregwizz.RESOURCE=Recursu plugin.jabberaccregwizz.AUTORESOURCE=Xenerar recursu automáticamente plugin.jabberaccregwizz.PRIORITY=Prioridá -plugin.jabberaccregwizz.XMPP_ERROR=Fallu XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Fallu XMPP ({0}) desconocíu. Verifica que'l nome'l sirvidor ye correutu. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Les tos contraseñes nun concasen. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Trocar opciones predeterminaes del sirvidor -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Opciones avanzaes plugin.jabberaccregwizz.USE_ICE=Usar ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Usar el Jingle/ICE de Google (esperimental) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Escubrir sirvidores STUN/TURN automáticamente plugin.jabberaccregwizz.SUPPORT_TURN=Sofitu TURN plugin.jabberaccregwizz.TURN_USERNAME=Nome d'usuariu TURN @@ -1093,11 +1000,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Deshabilitar copies de mensaxes plugin.jabberaccregwizz.DTMF_AUTO=Auto: Escoyer automáticamente ente RTP y en banda plugin.jabberaccregwizz.SERVER_OPTIONS=Opciones del sirivdor plugin.jabberaccregwizz.CHANGE_PASSWORD=Camudar contraseña de cuenta -plugin.jabberaccregwizz.NEW_PASSWORD=Contraseña nueva -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirmar contraseña nueva plugin.jabberaccregwizz.PORT_FIELD_INVALID=Por favor, rellena con un númberu de puertu válidu pa siguir. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=La cuenta tien de tar roblada enantes de camudar la contraseña. -plugin.jabberaccregwizz.PASSWORD_EMPTY=La contraseña ta balera. plugin.jabberaccregwizz.TLS_REQUIRED=La conexón nun utiliza TLS, nun s'intentará una camudancia de contraseña. plugin.jabberaccregwizz.PASSWORD_CHANGED=La contraseña camudóse con ésitu plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=El to sirvidor XMPP nun sofita camudancies de contraseña. @@ -1111,25 +1015,9 @@ plugin.jabberaccregwizz.RESET=Reafitar plugin.jabberaccregwizz.RESET_DESCRIPTION=Reafitar axustes globales plugin.jabberaccregwizz.DISABLE_JINGLE=Deshabilitar Jingle (audiu y llamaes de vidéu con XMPP). -# mailbox -plugin.mailbox.OUTGOING=Mensax saliente: -plugin.mailbox.INCOMING=Mensaxes entrantes: -plugin.mailbox.WAIT_TIME=Esperar fasta que la llamada s'unvie al buzón de voz -plugin.mailbox.MAX_MESSAGE_TIME=Duración másima de mensax entrante -plugin.mailbox.CONFIRM=Confirmar -plugin.mailbox.DEFAULTS=Por defeutu -plugin.mailbox.MAILBOX=Buzón - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Un protocolu pa coneutar y charrar nel serviciu MSN. -plugin.msnaccregwizz.USERNAME=Corréu: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID y contraseña - # plugin manager plugin.pluginmanager.INSTALL=Instalar plugin.pluginmanager.UNINSTALL=Desinstalar -plugin.pluginmanager.UPDATE=Anovar plugin.pluginmanager.PLUGINS=Complementos plugin.pluginmanager.URL=Enllaz plugin.pluginmanager.CHOOSE_FILE=Esbillar ficheru @@ -1154,7 +1042,6 @@ plugin.sipaccregwizz.SERVER_PORT=Puertu'l sirvidor plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Puertu'l proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Tresporte preferíu -plugin.sipaccregwizz.ADVANCED_OPTIONS=Opciones avanzaes plugin.sipaccregwizz.PROXY_OPTIONS=Opciones de proxy plugin.sipaccregwizz.PROXY_AUTO=Configurar proxy automáticamente plugin.sipaccregwizz.ENABLE_PRESENCE=Habilitar presencia (SIMPLE) @@ -1174,8 +1061,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Escueyi automáticamente ente RTP y en band plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=En banda -plugin.sipaccregwizz.REGISTER=REGISTRU -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Trocar les opciones por defeutu''l sirvidor plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Habilitar sofitu pa llamaes cifraes plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indica'l sofitu de ZRTP nel protocolu de señalización plugin.sipaccregwizz.AUTH_NAME=Nome d'autorización @@ -1196,10 +1081,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Comprobar URI de corréu de voz plugin.sipaccregwizz.NOT_SAME_PASSWORD=Les tos contraseñes nun concasen. plugin.sipaccregwizz.NO_CERTIFICATE= (usa autenticación regular) plugin.sipaccregwizz.SAVP_OPTION=Indicador RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Apagáu (indica RTP/AVP solo) plugin.sipaccregwizz.SAVP_OPTION_1=Obligatoriu (ufre y aceuta namái RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Opcional (ufre primero RTP/SAVP, y dempués RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Habilitar S-Descriptor (conocíu tamién como SDES o SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Escueyi protocolos con cifráu habilitáu y la so prioridá (primero'l protocolu cimeru): plugin.sipaccregwizz.CIPHER_SUITES=Suits de cifráu habilitaes: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} intentará asegurar automáticamente toles tos llamaes con ZRTP. Oyirás y verás una notificación cuando s''asegure la conexón afitada. Deberíes camudar namái los axustes avanzaos d'embaxo si tas bien seguru de lo que tas faciendo.
    @@ -1213,15 +1098,6 @@ plugin.skinmanager.DEFAULT_SKIN=Tema por defeutu plugin.skinmanager.ADD_NEW_SKIN=Amestar tema nuevu... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Tema por defeutu de l'aplicación. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Un protocolu pa coneutar máquines remotes per SSH. -plugin.sshaccregwizz.USERNAME=ID de cuenta: -plugin.sshaccregwizz.IDENTITY_FILE=Ficheru d'identidá: -plugin.sshaccregwizz.KNOWN_HOSTS=Agospios conocíos: -plugin.sshaccregwizz.OPTIONAL=Opcional -plugin.sshaccregwizz.ACCOUNT_DETAILS=Detalles de cuenta - # status update plugin.autoaway.AUTO_STATUS=Ausencia automática plugin.autoaway.ENABLE_CHANGE_STATUS=Camudar l'estáu entrín nun tea @@ -1269,22 +1145,6 @@ plugin.whiteboard.DESELECT=Deseleicionar plugin.whiteboard.DELETE=Desaniciar plugin.whiteboard.PROPERTIES=Propiedaes -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Un protocolu pa coneutase y charrar nel servicu Yahoo!. -plugin.yahooaccregwizz.USERNAME=Nome d'usuariu: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID y contraseña - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=El protocolu del serviciu Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Nome: -plugin.zeroaccregwizz.LAST_NAME=Apellíos: -plugin.zeroaccregwizz.EMAIL=Corréu: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=¿Recordar contautos Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID y contraseña -plugin.zeroaccregwizz.USERID=ID d'usuariu - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=El protocolu Google Talk @@ -1298,19 +1158,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, el portal de telecomunica plugin.iptelaccregwizz.USERNAME=Nome d'usuariu plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Soscribise a iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP y charra +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Nome d'usuariu plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Escribi la contraseña otra vegada plugin.sip2sipaccregwizz.EMAIL=Direición de corréu -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=P'aida tocante a esti serviciu visita
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=La direición de corréu úsase pa dunviar mensaxes del corréu de voz,
    notificaciones de llamaes perdíes y pa recuperar una contraseña escaecida -plugin.sip2sipaccregwizz.INFO_NOTE=P'aida tocante a esti serviciu visita http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Cuenta sip2sip.info esistente -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Crear una cuenta sip2sip.info de baldre - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP y mensaxería nel intre plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=P'aida tocante a esti serviciu visita
    http://ippi.fr @@ -1319,6 +1171,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Cuenta ippi esistente plugin.ippiaccregwizz.CREATE_ACCOUNT=Crear una cuenta ippi de baldre # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Zarrar ventana de charra plugin.keybindings.CHAT_COPY=Copiar plugin.keybindings.CHAT_CUT=Frañir @@ -1341,10 +1194,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Nome plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Atayu primariu plugin.keybindings.globalchooser.SHORTCUT_SECOND=Atayu secundariu plugin.keybindings.globalchooser.PRESS_BTN=Primi p'afitar un atayu -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Esperando plugin.keybindings.globalchooser.PUSH_TO_TALK=Primi pa falar plugin.keybindings.globalchooser.ENABLE_SPECIAL=Habilitar deteición de tecles especiales plugin.keybindings.PLUGIN_NAME=Combinaciones de tecles +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Charra plugin.keybindings.MAIN=Principal plugin.keybindings.GLOBAL=Atayos globales @@ -1372,6 +1225,7 @@ plugin.notificationconfig.tableheader.SOUND=Reproducir un soníu pente medies d' plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Repoducir un soníu pente medies d'un preséu de reproducción plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Reproducir un soníu pente medies d'unos altavoces plugin.notificationconfig.tableheader.DESCRIPTION=Descripción del eventu +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Llamada entrante plugin.notificationconfig.event.SecurityMessage=Mensax de seguranza plugin.notificationconfig.event.IncomingFile=Ficheru entrante @@ -1473,6 +1327,7 @@ impl.neomedia.configform.VIDEO=Vidéu impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Anovamientu periódicu d'Intra impl.neomedia.configform.H264.defaultProfile=Perfil por defeutu pa codificar en: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Llinia bas impl.neomedia.configform.H264.defaultProfile.high=Alta impl.neomedia.configform.H264.defaultProfile.main=Principal @@ -1503,7 +1358,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Contraseña d'anguaño: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Pon la contraseña nueva: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Escribi la contraseña de nueves: plugin.securityconfig.masterpassword.MP_TITLE=Contraseña maestra -plugin.securityconfig.masterpassword.MP_NOT_SET=(ensin afitar) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Nun punxesti la contraseña maesta correuta. Por favor, inténtalo de nueves. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=¡La contraseña maestra nun ye correuta! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Fallu al camudar contraseña @@ -1519,7 +1373,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Contraseña plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(desconocíu) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nun pue descifrase) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Contraseñes atroxaes -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Desaniciar plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Desaniciar too plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=¿De xuru quies desaniciar toles contraseñes? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Desaniciar toles contraseñes @@ -1615,7 +1468,6 @@ plugin.globalproxy.PROXY_PORT=Puertu proxy plugin.globalproxy.PROXY_USERNAME=Usuariu proxy plugin.globalproxy.PROXY_PASSWORD=Contraseña proxy plugin.globalproxy.DESCRIPTION={0} usará la configuración de proxy d'enriba pa toles redes a les que te coneutes o reconeutes dende agora. \nEl sofitu de proxy ye anguaño esperimental y namái furrula con dalgunos protocolos. Comprueba la tabla pa más detalles: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Tamién proxy DNS plugin.globalproxy.FWD_DNS_NOTE=Útil con Tor. Aida a evitar fugues de DNS direicionando tol tráficu DNS al proxy Tor. Requier reaniciar. @@ -1650,7 +1502,6 @@ plugin.provisioning.RESTART_WARNING=¡Alcuerdate que les camudancies fadrán efe plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Copiar UUID al cartafueyu plugin.provisioning.CLIPBOARD_FAILED=Fallu al copiar UUID al cartafueyu -plugin.provisioning.EXIT_ON_FAIL=Colar de l'aplicación si l'aprovisionamientu falla plugin.provisioning.CREDENTIALS=Caberes credenciales d'aprovisionamientu atroxaes plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=¿De xuru quies desaniciar la contraseña d'aprovisionamientu? plugin.provisioning.PROV_FAILED=Aprovisionamientu fallíu @@ -1717,8 +1568,6 @@ util.dns.DNSSEC_WARNING=
    {0} intentó coneutase al sirvido #plugin spellcheck plugin.spellcheck.TITLE=Ortografía y gramática plugin.spellcheck.MENU=Amosar ortografía y gramática -plugin.spellcheck.LANG=Llingua -plugin.spellcheck.EDIT_PERSONAL_DICT=Editar plugin.spellcheck.ENABLE_SPELL_CHECK=Activar revisión ortográfica plugin.spellcheck.dialog.FIND=Alcontrar siguiente plugin.spellcheck.dialog.REPLACE=Trocar -- cgit v1.1 From 329f77aee503498be072dff8313fc7dadf9d20d2 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:00 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 32 of 1505 strings translated (14 fuzzy). --- resources/languages/resources_hi.properties | 68 +++++++++++++++++++---------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/resources/languages/resources_hi.properties b/resources/languages/resources_hi.properties index 37df92d..1089715 100644 --- a/resources/languages/resources_hi.properties +++ b/resources/languages/resources_hi.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -25,13 +36,27 @@ # from your system's language, pass the language code to ant: # ant -Duser.language=xx run +service.gui.ABOUT=बारे में +service.gui.ACCEPT=स्वीकारें (&A) service.gui.ACCOUNT=खाता +service.gui.ACCOUNT_ME=मैं service.gui.ACCOUNT_REGISTRATION_WIZARD=खाता पंजीकरण service.gui.ACCOUNTS=खाता -service.gui.ADD_ACCOUNT=खाता जोड़ो +service.gui.ADD=जोड़ें +service.gui.ADD_CONTACT=संपर्क जोड़ें +service.gui.ADD_AUTHORIZED_CONTACT=अपनी सम्पर्क सूची में जोड़ें +service.gui.ADD_CONTACT_TO_CONTACTLIST=इस सम्पर्क को मेरी सम्पर्क सूची में जोड़ें +service.gui.ADD_CONTACT_ERROR=आईडी के साथ संपर्क जोड़ने में विफल: {0} service.gui.ADD_CONTACT_ERROR_TITLE=संपर्क जोड़ने में त्रुटि -service.gui.ADD_GROUP=समूह बनाये +service.gui.ADD_CONTACT_EXIST_ERROR=संपर्क {0} पहले से ही आपकी संपर्क सूची में मौजूद है। +service.gui.ADD_GROUP_ERROR=नाम के साथ समूह जोड़ने में विफल: {0}। +service.gui.ADD_GROUP_EMPTY_NAME=समूह का नाम खाली नहीं होना चाहिए। +service.gui.ADDRESS=पता service.gui.ADMINISTRATOR=प्रशासक +service.gui.ADVANCED=विस्तृत +service.gui.ALL_CONTACTS=सभी संपर्कों +service.gui.ALTERNATE_ADDRESS=वैकल्पिक पता +service.gui.APPLY=लागू करें service.gui.ARE_NOW=आप अभी service.gui.AWAY_STATUS=दूर service.gui.BROWSE=ढूंढना @@ -42,27 +67,30 @@ service.gui.CHANGE_NICK=उपनाम परिवर्तन service.gui.CHANGE_NICKNAME=उपनाम परिवर्तन service.gui.ROOM_NAME=गपशप के कमरे service.gui.CHAT_ROOMS=गपशप के कमरे +service.gui.CHAT_ROOM=गपशप के कमरे service.gui.CONTACTS=संपर्क service.gui.CREATE_GROUP=समूह बनाये -service.gui.DATE=तिथि service.gui.DELETE=मिटाएँ service.gui.DO_NOT_ASK_AGAIN=फिर ना पूछें service.gui.DURATION=अवधि +service.gui.chat.role.ADMINISTRATOR=प्रशासक + +#enum values from IceProcessingState +#service.gui.CERT_INFO_ are combined from Rdn names + + # keep the following string short # service.gui.avatar.imagepicker -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -71,6 +99,10 @@ service.gui.DURATION=अवधि # LDAP +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -85,9 +117,6 @@ service.gui.DURATION=अवधि # branding -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -99,20 +128,15 @@ service.gui.DURATION=अवधि # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -122,22 +146,19 @@ service.gui.DURATION=अवधि # whiteboard plugin.whiteboard.DELETE=मिटाएँ -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +#Enum KeybindingSet.Category plugin.keybindings.CHAT=गपशप # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -150,6 +171,7 @@ impl.media.security.zrtp.TITLE=कॉल +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. -- cgit v1.1 From 7a2da07b2596b0e6efd600410ea8b7b7f963b338 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:07 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1479 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_it.properties | 243 +++++++--------------------- 1 file changed, 54 insertions(+), 189 deletions(-) diff --git a/resources/languages/resources_it.properties b/resources/languages/resources_it.properties index b70e7c0..b8ac264 100644 --- a/resources/languages/resources_it.properties +++ b/resources/languages/resources_it.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Me service.gui.ACCOUNT_REGISTRATION_WIZARD=Creazione guidata account service.gui.ACCOUNTS=Account service.gui.ADD=&Aggiungi -service.gui.ADD_ACCOUNT=Aggiungi account service.gui.ADD_CONTACT=&Aggiungi contatto service.gui.ADD_AUTHORIZED_CONTACT=Aggiungi {0} ai tuoi contatti service.gui.ADD_CONTACT_TO_CONTACTLIST=Aggiungi alla lista contatti @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Errore durante la creazione del contatto service.gui.ADD_CONTACT_EXIST_ERROR=Il contatto {0} esiste già nella tua rubrica. service.gui.ADD_CONTACT_NETWORK_ERROR=Il server non ha risposto alla richiesta di aggiunta del contatto con id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Errore durante la creazione del contatto con id: {0}. Operazione non supportata. -service.gui.ADD_CONTACT_IDENTIFIER=Inserisci l'identificativo del contatto che vuoi aggiungere nel campo sottostante. -service.gui.ADD_CONTACT_WIZARD=Creazione guidata contatto service.gui.ADD_CONTACT_NOT_CONNECTED=È necessario essere connessi per aggiungere un contatto. Effettua il login al provider selezionato e tenta di nuovo. service.gui.ADD_GROUP_LOCAL_ERROR=Errore durante la creazione del gruppo {0}. Il problema si è verificato durante un'operazione I/O locale. service.gui.ADD_GROUP_EXIST_ERROR=Il gruppo {0} esiste già nella tua rubrica. Scegli un altro nome. service.gui.ADD_GROUP_NET_ERROR=Errore durante la creazione del gruppo {0}. Il problema si è verificato a causa di un errore di rete. Verifica la connessione e riprova. service.gui.ADD_GROUP_ERROR=Errore durante la creazione del gruppo {0}. service.gui.ADD_GROUP_EMPTY_NAME=Il nome del gruppo non può essere vuoto. -service.gui.ADD_GROUP=Crea gruppo -service.gui.ADD_SUBCONTACT=&Aggiungi sottocontatto service.gui.ADDRESS=Indirizzo service.gui.ADMINISTRATOR=amministratore service.gui.ADVANCED=&Avanzate -service.gui.ALL=&Tutti service.gui.ALL_CONTACTS=&Tutti i contatti service.gui.ALTERNATE_ADDRESS=Indirizzo alternativo service.gui.APPLY=&Applica @@ -65,7 +70,6 @@ service.gui.AT=alle service.gui.AUTHORIZE=&Autorizza service.gui.AUTHORIZATION_ACCEPTED={0} ha accettato la tua richiesta di autorizzazione. service.gui.AUTHENTICATION_FAILED=Autenticazione fallita per {0}. La password inserita non è valida. -service.gui.AUTHENTICATION_REQUESTED=Richiesta autenticazione service.gui.AUTHENTICATION_REQUESTED_SERVER=Il server {0} ha richiesto la tua autenticazione. service.gui.AUTHENTICATION_REJECTED={0} ha rifiutato la tua richiesta di autorizzazione. service.gui.AUTHENTICATION_WINDOW_TITLE=autenticazione di {0} @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Inserisci il tuo nuovo nickname nel campo sott service.gui.CHANGE_NICKNAME_ERROR=Si è verificato un errore nel cambio del nickname service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Il nickname è già esistente service.gui.CHANGE_VIDEO_QUALITY=Cambia la qualità del video ricevuto -service.gui.CHAT_CONFERENCE_LABEL=Conferenze service.gui.CHAT_CONFERENCE_ITEM_LABEL=Conferenza di {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Sei già entrato nella chatroom {0}. service.gui.CHAT_ROOM_CONFIGURATION=Configurazione della chatroom {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=è uscito dalla chatroom {0} service.gui.CHAT_ROOM_USER_KICKED=è stato espulso dalla chatroom {0} service.gui.CHAT_ROOM_USER_QUIT=è uscito dalla chatroom {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Invio di messaggi non possibile (voce bloccata) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Salva la chatroom per usi futuri -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Rimuovi la chatroom selezionata dalla lista delle chatroom salvate service.gui.CHAT_ROOM_NAME=Nome della chatroom service.gui.CLEAR_CUSTOM_MESSAGES=Cancella i messaggi personalizzati service.gui.ROOM_NAME=Chatroom -service.gui.AUTOJOIN=Entra automaticamente service.gui.CHANGE_PASSWORD=Cambia password service.gui.CHAT_ROOM_NAME_INFO=Inserisci il nome della nuova chatroom nel campo sottostante. service.gui.CHAT_ROOM_NOT_EXIST=Impossibile trovare la chatroom {0} sul server {1}. Verificare che il nome sia corretto. service.gui.CHAT_ROOM_NOT_CONNECTED=Devi essere connesso per poter entrare nella chatroom {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Devi essere connesso per poter uscire da una chatroom. -service.gui.CHAT_ROOM_NOT_JOINED=Devi essere nella chatroom per poter effettuare ulteriori operazioni con essa. service.gui.CHAT_ROOM_OPTIONS=Opzioni della chatroom service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Per accedere alla chatroom {0} devi essere registrato. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Per accedere alla chatroom {0} devi conoscerne la password. @@ -151,22 +150,18 @@ service.gui.CLEAR=Cancella service.gui.CLOSE=C&hiudi service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Hai ricevuto un nuovo messaggio meno di 2 secondi fa. Sei sicuro di volere chiudere? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Hai trasferimenti di file in corso. Sei sicuro di volerli annullare? -service.gui.CONFIRM=Conferma service.gui.CONNECTED_STATUS=Connesso service.gui.CONNECTING=Connessione in corso... service.gui.CONNECTING_STATUS=Connessione in corso service.gui.CONNECTING_EARLY_MEDIA_STATUS=Connessione in corso... service.gui.CONNECTION=Connessione -service.gui.CONNECTION_FAILED_MSG=Errore durante la connessione con il seguente account: Nome utente: {0}, Server: {1}. Controlla la tua connessione di rete o contatta il tuo amministratore di rete per maggiori informazioni. service.gui.CONNECTION_EXPIRED_MSG=Sei attualmente disconnesso dal server {0}. service.gui.CONTACT_NAME=ID o Numero -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Il contatto selezionato {0} non supporta le chiamate vocali. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Il contatto {0} non supporta le chat multiutente. service.gui.CONTACT_PAUSED_TYPING={0} ha interrotto la digitazione service.gui.CONTACT_TYPING={0} sta digitando service.gui.CONTACT_TYPING_SEND_FAILED=ops... non abbiamo potuto dire a {0} che stavi scrivendo service.gui.CONTACT_INFO=&Informazioni sul contatto -service.gui.CONTACTLIST=Rubrica service.gui.CONTACTS=Contatti service.gui.COPY=&Copia service.gui.COPY_LINK=Copia il &link @@ -176,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Crea chatroom service.gui.CREATE_CHAT_ROOM_ERROR=Errore durante la creazione della chatroom {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Creazione guidata chatroom service.gui.CREATE_CONFERENCE_CALL=&Crea chiamata vocale multiutente -service.gui.CREATE_CONFERENCE_CHAT=&Crea chat multiutente service.gui.CREATE_GROUP=&Crea gruppo service.gui.CREATE_GROUP_NAME=Inserisci il nome del nuovo gruppo nel campo sottostante. -service.gui.CREATE_FIRST_GROUP_WIZARD=La tua rubrica non contiene alcun gruppo. Creare prima un gruppo (File/Crea gruppo). service.gui.CREATE_VIDEO_BRIDGE=Crea &videoconferenza... service.gui.CREATE_VIDEO_BRIDGE_MENU=Crea &videoconferenza service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Crea o unisciti a una videoconferenza service.gui.CREATE_VIDEO_CONFERENCE=Crea una nuova videoconferenza per questa chatroom service.gui.CONTACT_INFO_NOT_SUPPORTED=Questo contatto non supporta la trasmissione delle sue informazioni service.gui.CUT=Taglia -service.gui.DATE=Data service.gui.DELETE=Rimuovi service.gui.DENY=&Nega service.gui.DESKTOP_SHARING_WARNING=Sei sicuro di voler iniziare la condivisione dello schermo?
    Premendo OK i contatti presenti in questa chiamata vedranno il tuo schermo. @@ -197,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Disconnesso service.gui.DND_STATUS=Non disturbare service.gui.DO_NOT_ASK_AGAIN=Non chiedere in futuro service.gui.DO_NOT_SHOW_AGAIN=Non mostrare questo messaggio in futuro -service.gui.DOWNLOAD_NOW=&Scarica ora service.gui.DRAG_FOR_SHARING=Trascina qui ciò che vuoi condividere... service.gui.DURATION=Durata service.gui.DESTROY_CHATROOM=Elimina la chatroom @@ -218,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Errore ricevuto da {0} service.gui.ESTIMATED_TIME=Tempo stimato: service.gui.EVENTS=Eventi service.gui.EXIT=&Esci -service.gui.EXTENDED_CRITERIA=Criteri avanzati service.gui.GENERAL=Generale service.gui.GENERAL_ERROR=Errore generico service.gui.GROUP_NAME=Nome gruppo @@ -260,7 +250,6 @@ service.gui.FONT_ITALIC=Corsivo service.gui.FONT_SIZE=Dimensione service.gui.FONT_STYLE=Stile service.gui.FONT_UNDERLINE=Sottolineato -service.gui.FROM={0} da {1} service.gui.GRANT_OWNERSHIP=Concedi stato di proprietario service.gui.GRANT_ADMIN=Concedi stato di amministratore service.gui.GRANT_MODERATOR=Concedi stato di moderatore @@ -286,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Sei sicuro di voler rimuovere permanentem service.gui.HISTORY_REMOVE_ERROR=Errore nella rimozione dei messaggi salvati. service.gui.HOME=Casa service.gui.HOME_PAGE=Home page -service.gui.HOUR=Ora service.gui.ICE=ICE service.gui.IDENTIFIER=Identificativo service.gui.IGNORE=&Ignora @@ -294,6 +282,7 @@ service.gui.INSERT_SMILEY=Inserisci smiley service.gui.INCOMING_CALL=Ricevuta chiamata in entrata da: {0} service.gui.INCOMING_SCREEN_SHARE=Ricevuto un invito per la condivisione dello schermo da: {0} service.gui.INCOMING_CALL_STATUS=Chiamata in arrivo +service.gui.INCOMING_SCREEN_SHARE_STATUS=Condivisione schermo in arrivo service.gui.INSTANT_MESSAGINGS=IM service.gui.IM=IM service.gui.INITIATING_CALL_STATUS=Inizializzazione della chiamata @@ -309,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Invita contatti per una videoconferen service.gui.INVITE_REASON=Motivo dell'invito service.gui.IS_CALLING={0} sta chiamando... service.gui.IS_NOW={0} è ora {1} -service.gui.JITSI_WARNING=SIP Communicator è stato recentemente rinominato in Jitsi.
    Se vuoi che la tua versione rimanga aggiornata, scarica Jitsi ora.

    Ci scusiamo per ogni inconveniente che questo possa causarti.

    Il team di sviluppatori di Jitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator è diventato Jitsi service.gui.JOIN=&Entra service.gui.JOIN_AS=E&ntra come -service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Unisciti ad una sessione di videoconferenza esistente +service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Unisciti ad una videoconferenza in corso service.gui.JOIN_VIDEO=Unisciti con il video -service.gui.CLOSE_CHAT_ROOM_DIALOG=C&hiudi service.gui.JOB_TITLE=Titolo professionale service.gui.JOIN_CHAT_ROOM=&Entra in una chatroom service.gui.JOIN_CHAT_ROOM_TITLE=Entra in una chatroom @@ -328,7 +314,6 @@ service.gui.KICK_FAILED=Espulsione fallita service.gui.KICK_FAILED_GENERAL_ERROR=Impossibile espellere {0}. Si è verificato un errore generico sul server. service.gui.KICK_FAILED_NOT_ALLOWED=Impossibile espellere {0}. Il proprietario e l''amministratore della chatroom non possono essere espulsi. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Impossibile espellere {0}. Non hai privilegi sufficienti per farlo. -service.gui.LAST=Ultimo service.gui.LAST_NAME=Cognome service.gui.LEAVE=&Esci service.gui.LIMIT_REACHED_FOR_IP=Limite registrazioni per il tuo indirizzo IP raggiunto sul server {0}. @@ -348,7 +333,6 @@ service.gui.MESSAGE=Messaggio service.gui.MISSED_CALLS_TOOL_TIP=Chiamate perse da: service.gui.MISSED_CALLS_MORE_TOOL_TIP= e altri {0} service.gui.MODERATOR=moderatore -service.gui.MORE=Vedi altro service.gui.MORE_LABEL=Ancora service.gui.MOVE=Sposta service.gui.MOVE_SUBCONTACT=Sp&osta contatto @@ -357,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Il contatto selezionato coincide con quello \ service.gui.MOVE_SUBCONTACT_QUESTION=Sei sicuro di voler spostare {0} in {1}? service.gui.MOVE_TO_GROUP=&Sposta nel gruppo service.gui.MOVE_CONTACT=Sposta contatto -service.gui.MOVE_CONTACT_ERROR=Il contatto non può essere spostato service.gui.MSG_DELIVERY_FAILURE=Impossibile consegnare il messaggio service.gui.MSG_DELIVERY_NOT_SUPPORTED=Il protocollo che stai utilizzando non supporta i messaggi offline. Puoi provare a raggiungere {0} attraverso un altro account o aspettare che torni online. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Errore interno. Questo è quasi sicuramente un bug. Riportalo qui: https://jitsi.org/Development/BugsAndIssues. @@ -371,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Devi essere connesso per poter inviare m service.gui.MULTIPLE_LOGINS=Impossibile effettuare login multipli per il seguente account: Nome utente: {0}, Server: {1}. Esso è attualmente disconnesso. service.gui.MY_CHAT_ROOMS=Aggiungi chat room service.gui.MY_CHAT_ROOMS_TITLE=Aggiungi chat room -service.gui.MUTE=Silenzioso service.gui.MUTUALLY_ON_HOLD_STATUS=Chiamata messa in attesa reciprocamente service.gui.NAME=Nome service.gui.NETWORK=Rete @@ -403,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Non nella lista contatti service.gui.SD_QUALITY=Qualità normale service.gui.OFFLINE=Disconnesso service.gui.OK=&OK -service.gui.OLDER_CALLS=Chiamate precedenti service.gui.ONLINE=Connesso service.gui.OPEN=Apri service.gui.OPEN_FILE_FROM_IMAGE=Doppio click per aprire il file. @@ -415,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Apri in caso di attività service.gui.OPEN_ON_MESSAGE=Apri in caso di nuovi messaggi service.gui.OPEN_ON_IMPORTANT_MESSAGE=Apri solo in caso di messaggi importanti service.gui.OR=o -service.gui.OR_ENTER_PHONE_NUMBER=Oppure inserisci qui il numero di telefono service.gui.ORGANIZATION=Organizzazione service.gui.OTHER=Altro service.gui.chat.role.OWNER=Proprietario @@ -424,6 +404,7 @@ service.gui.chat.role.MODERATOR=Moderatore service.gui.chat.role.MEMBER=Membro service.gui.chat.role.GUEST=Ospite service.gui.chat.role.SILENT_MEMBER=Membro silenzioso +service.gui.chat.role.OUTCAST=Bandito dalla partecipazione service.gui.OWNER=proprietario della chatroom service.gui.ON_MOBILE_TOOLTIP=(su dispositivo mobile) service.gui.PASSWORD=Password @@ -440,7 +421,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Invio' per suggerimenti service.gui.PRESS_FOR_CALL_INFO=Premere per informazioni sulla chiamata service.gui.PRESS_TO_OPEN_CRM=Premi per aprire l'applicazione CRM service.gui.PREVIOUS=Precedente -service.gui.PREVIOUS_TOOLTIP=Sfoglia conversazioni più vecchie service.gui.PRINT=&Stampa service.gui.PROACTIVE_NOTIFICATION=sta scrivendo un messaggio service.gui.PROBLEMS_ENCOUNTERED=Sono stati incontrati dei problemi @@ -456,7 +436,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Ti sei disconnesso e riconnesso al serve service.gui.RE_REQUEST_AUTHORIZATION=Richiedi nuovamente l'autorizzazione service.gui.REFERRED_STATUS=Inoltrata service.gui.REJECT=&Rifiuta -service.gui.REMIND_ME_LATER=Ricorda in seguito service.gui.REMEMBER_PASSWORD=Ricorda password service.gui.REMOVE=&Rimuovi service.gui.REMOVE_ACCOUNT=&Rimuovi account @@ -482,29 +461,20 @@ service.gui.REVOKE_ADMIN=Revoca status di amministratore service.gui.REVOKE_MODERATOR=Revoca status di moderatore service.gui.REVOKE_MEMBERSHIP=Revoca stato di membro service.gui.REVOKE_VOICE=Revoca voce -service.gui.ROOT_GROUP=Gruppo radice service.gui.SAVE=&Salva -service.gui.SAVE_AS_DEFAULT=Salva come predefiniti service.gui.SEARCH=&Cerca service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Clicca il bottone sottostante per mostrare tutte le chatroom disponibili nel server selezionato. Seleziona la chatroom in cui intendi entrare e premi il bottone entra. service.gui.SEARCH_STRING_CONTACT_SOURCE=Contatti cercati service.gui.SECURITY=Sicurezza -service.gui.SELECT_ACCOUNT=Seleziona account service.gui.SELECT_COLOR=Seleziona colore service.gui.SELECT_GROUP=Seleziona gruppo -service.gui.SELECT_GROUP_WIZARD_MSG=La lista sottostante contiene tutti i gruppi presenti nella tua rubrica. Seleziona quello in cui vuoi inserire il nuovo contatto. service.gui.SELECT_NO_GROUP=Nessun gruppo -service.gui.SELECT_GROUP_WIZARD=Specifica gruppo service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=La lista sottostante contiene tutti gli account che supportano chat multiutente. Seleziona quella che vuoi utilizzare per creare la nuova chatroom. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=La lista sottostante contiene tutti gli account registrati. Seleziona quello che vuoi utilizzare per comunicare con il nuovo contatto. -service.gui.SELECT_PROVIDERS_WIZARD=Seleziona account service.gui.SELECT_VIDEO_CONFERENCE=Seleziona la videoconferenza service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Seleziona una chat room dall'elenco e premi OK per aggiungerla service.gui.SEND=&Invia service.gui.SEND_FILE=Invia &file -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Nessuna informazione disponibile per questo contatto. service.gui.SEND_MESSAGE=&Invia un messaggio -service.gui.SEND_AS_SMS=Invia come SMS service.gui.SEND_PRIVATE_MESSAGE=Invia messaggio privato service.gui.SEND_SMS=Invia &SMS service.gui.SEND_SMS_DETAILS=Ricorda che devi inserire il numero in formato internazionale, anteponendo, ad esempio, il prefisso +44 nel caso dell'UK (es. +447777000000) @@ -543,7 +513,6 @@ service.gui.STREET=Via service.gui.SUBJECT=Oggetto service.gui.SUMMARY=Sommario service.gui.TELEPHONY=Telefonia -service.gui.TODAY=Oggi service.gui.TOOLS=&Strumenti service.gui.TRANSFER=Tras&ferisci service.gui.TO=&A: @@ -553,7 +522,6 @@ service.gui.TRANSFER_CALL_TO=Trasferisci a: service.gui.TRANSPARENCY_NOT_ENABLED=La trasparenza non è supportata dalla configurazione attuale. service.gui.TYPE_YOUR_REQUEST=Inserisci la richiesta qui service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Non è stato possibile cambiare la qualità del video per questa chiamata. -service.gui.UNMUTE=Disabilita silenzioso service.gui.USER_IDENTIFIER=Identificativo utente: service.gui.USER_EXISTS_ERROR=Questo utente esiste già nella rete selezionata. Scegliere un altro utente o un'altra rete. service.gui.USERNAME_NULL=Devi riempire i campi relativi a Nome utente e password. @@ -566,7 +534,6 @@ service.gui.USE_PROVISIONING=Usa il provisioning di rete service.gui.VALUE=Valore service.gui.VIDEO_CALL=Chiamata &video service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Visualizza service.gui.VIEW_HISTORY=Visualizza &cronologia service.gui.VIEW_SMILEYS=Visualizza &smiley @@ -586,9 +553,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Imposta volume service.gui.WAITING_AUTHORIZATION=In attesa di autorizzazione service.gui.WARNING=Avviso service.gui.YES=Sì -service.gui.YESTERDAY=Ieri -service.gui.EXISTING_ACCOUNT_ERROR=L'account inserito è già installato. -service.gui.NEW_MAIL=Hai una nuova Mail!
    Da: {0} {1}
    Oggetto: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Hai ricevuto un nuovo messaggio di posta nella tua casella {0}:
    service.gui.NEW_GMAIL_MANY_HEADER=Hai ricevuto {2} nuovi messaggi di posta nella tua casella {0}:
    service.gui.NEW_GMAIL_FOOTER=un''altra conversazione non letta nella tua casella.
    @@ -600,7 +564,10 @@ service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Entra nella modalità a tutto schermo service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Esci dalla modalità a tutto schermo service.gui.HOLD_BUTTON_TOOL_TIP=Commuta stato di attesa service.gui.MUTE_BUTTON_TOOL_TIP=Attiva/disattiva audio o mantieni premuto per cambiare il volume del microfono -service.gui.RECORD_BUTTON_TOOL_TIP=Attiva/disattiva registrazione chiamata +service.gui.PARK=Parcheggia +service.gui.PARKING_SLOT=Numero del parcheggio: +service.gui.PARK_BUTTON_TOOL_TIP=Inoltra chiamata +service.gui.RECORD_BUTTON_TOOL_TIP=Parcheggia la chiamata service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=Video on/off service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Mostra/nascondi video locale service.gui.SHOW_HIDE_PEERS_TOOL_TIP=Mostra/nascondi la lista dei partecipanti @@ -612,7 +579,6 @@ service.gui.SECURITY_ERROR=Errore di sicurezza service.gui.SPEED=Velocità: service.gui.SILENT_MEMBER=membro silenzioso service.gui.NON_SECURE_CONNECTION=Non è stato possibile instaurare una connessione sicura per l''account {0}. Se vuoi connetterti ad un server non sicuro abilita "Permetti connessioni insicure" nelle impostazioni dell'account -service.gui.UPDATE=Aggiorna service.gui.MOBILE_PHONE=Cellulare service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Lavoro @@ -647,7 +613,6 @@ service.gui.callinfo.CALL_INFORMATION=Informazioni sulla chiamata service.gui.callinfo.CALL_IDENTITY=Identità service.gui.callinfo.PEER_COUNT=Numero di partecipanti service.gui.callinfo.IS_CONFERENCE_FOCUS=Controllore della conferenza -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Cifratura attivata service.gui.callinfo.CALL_TRANSPORT=Trasporto segnali di chiamata service.gui.callinfo.CALL_DURATION=Durata service.gui.callinfo.TLS_PROTOCOL=Protocollo TLS @@ -661,7 +626,6 @@ service.gui.callinfo.AUDIO_INFO=Informazioni sull'audio service.gui.callinfo.VIDEO_INFO=Informazioni sul video service.gui.callinfo.LOCAL_IP=IP / Porta locali service.gui.callinfo.REMOTE_IP=IP / Porta remoti -service.gui.callinfo.BANDWITH=Larghezza di banda service.gui.callinfo.LOSS_RATE=Tasso di perdita service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -671,10 +635,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocollo di scambio della chiave service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Tipo esteso del candidato ICE service.gui.callinfo.ICE_STATE=Stato del processamento ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Raccolta dei canditati service.gui.callinfo.ICE_STATE.RUNNING=Controlli di connettività service.gui.callinfo.ICE_STATE.COMPLETED=Completato service.gui.callinfo.ICE_STATE.FAILED=Fallito + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP / Porta locali service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Indirizzo (IP / Porta) reflexive dell'host locale service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Indirizzo (IP / Porta) relayed dell'host locale @@ -695,15 +662,18 @@ service.gui.ALWAYS_TRUST=Accetta sempre questo certificato service.gui.CERT_DIALOG_TITLE=Verifica certificato service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} non può verificare l''identità del server durante la connessione a
    {1}.

    Il certificato non è affidabile, questo significa che l''identità del server non può essere verificata automaticamente.

    Desideri continuare?
    Per maggiori informazioni, clicca su "Mostra certificato". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} non può verificare l''identità del certificato del server.

    Il certificato non è affidabile, questo significa che l''identità del server non può
    essere verificata automaticamente. Desideri continuare?

    Per maggiori informazioni, clicca su "Mostra certificato". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} non può verificare l''identità del client che si sta collegando.

    Il certificato non è affidabile, questo significa che l''identità del client non può
    essere verificata automaticamente. Desideri accettare la connessione?

    Per maggiori informazioni, clicca su "Mostra certificato". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} non può verificare l''identità del nodo {1}.

    Il certificato non è affidabile, questo significa che l''identità del nodo non può
    essere verificata automaticamente. Desideri continuare la connessione?

    Per maggiori informazioni, clicca su "Mostra certificato". service.gui.CONTINUE_ANYWAY=Continua comunque service.gui.CERT_INFO_CHAIN=Catena dei certificati: +service.gui.CERT_INFO_ISSUED_TO=Emesso a + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nome comune: service.gui.CERT_INFO_O=Organizzazione: service.gui.CERT_INFO_C=Nazione: service.gui.CERT_INFO_ST=Stato o provincia: service.gui.CERT_INFO_L=Località: +service.gui.CERT_INFO_ISSUED_BY=Emesso da service.gui.CERT_INFO_OU=Unità organizzativa: service.gui.CERT_INFO_VALIDITY=Validità service.gui.CERT_INFO_ISSUED_ON=Rilasciato il: @@ -716,12 +686,10 @@ service.gui.CERT_INFO_SIGN_ALG=Algoritmo firma: service.gui.CERT_INFO_PUB_KEY_INFO=Informazioni sulla chiave pubblica service.gui.CERT_INFO_ALG=Algoritmo: service.gui.CERT_INFO_PUB_KEY=Chiave pubblica: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Esponente: service.gui.CERT_INFO_KEY_SIZE=Dimensione chiave: service.gui.CERT_INFO_SIGN=Firma certificato: -service.gui.CONTINUE=Continua service.gui.SHOW_CERT=Mostra certificato service.gui.HIDE_CERT=Nascondi certificato @@ -744,12 +712,9 @@ service.gui.security.SECURE_AUDIO=Audio protetto service.gui.security.AUDIO_NOT_SECURED=Audio non protetto service.gui.security.SECURE_VIDEO=Video protetto service.gui.security.VIDEO_NOT_SECURED=Video non protetto -service.gui.security.NO_VIDEO=Video assente -service.gui.security.CIPHER=Cifrario: {0} service.gui.security.CALL_SECURED_TOOLTIP=Chiamata protetta. Per maggiori informazioni clicca qui. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Chiamata non sicura. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Premi qui per confrontare le chiavi di codifica con il tuo partner. -service.gui.security.COMPARE_WITH_PARTNER=Confronta il codice con il tuo interlocutore e clicca sul lucchetto per confermare. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Confronta con l'interlocutore: service.gui.security.STRING_COMPARED=Stringa confrontata! @@ -767,20 +732,14 @@ service.gui.avatar.imagepicker.CLICK=Clicca e Sorridi service.gui.avatar.imagepicker.IMAGE_FILES=File di immagine service.gui.avatar.imagepicker.IMAGE_PICKER=Foto service.gui.avatar.imagepicker.IMAGE_SIZE=Dimensione immagine -service.gui.avatar.imagepicker.INITIALIZING=Inizializzazione service.gui.avatar.imagepicker.RESET=Ripristina service.gui.avatar.imagepicker.SET=Imposta service.gui.avatar.imagepicker.TAKE_PHOTO=Scatta una foto -service.gui.avatar.imagepicker.WEBCAM_ERROR=Errore della webcam service.gui.security.encryption.required=Cifratura necessaria! service.protocol.ICE_FAILED=Impossibile stabilire una connessione (ICE fallito e nessun Relay trovato) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Errore nell'archiviazione della lista contatti SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=La risorsa non può essere letta {0}. Per {1} @@ -810,9 +769,7 @@ impl.ldap.QUERY_CUSTOM=Query personalizzata impl.ldap.QUERY_CUSTOM_HINT=Usa {0} come segnaposto per il termine di ricerca impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Aggiungi automaticamente i caratteri jolly ai termini della query impl.ldap.QUERY_PHOTO_INLINE=Recupera la foto assieme agli altri attributi -impl.ldap.NEW=Nuovo impl.ldap.EDIT=modifica -impl.ldap.REMOVE=Rimuovi impl.ldap.ENABLED=Abilitato impl.ldap.SERVER_NAME=Nome del server impl.ldap.SERVER_NAME_EXAMPLE=Il mio server LDAP @@ -845,6 +802,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=telefonoCasa impl.ldap.PHONE_PREFIX=Prefisso telefonico impl.ldap.PHONE_PREFIX_EXAMPLE=Es.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Rubrica plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Abilita la ricerca nella Rubrica di MacOSX @@ -854,14 +815,12 @@ plugin.addrbook.DEFAULT_IM_APP=Imposta Jitsi come programma di messaggistica pre plugin.addrbook.PREFIX=Specifica un prefisso per i numeri telefonici plugin.addrbook.PREFIX_EXAMPLE=Es.: 00 plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT_TITLE=Errore nell'accesso ai contatti di Microsoft Outlook. -plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT={0} non può accedere ai contatti di Microsoft Outlook perchè Outlook non è impostato come applicazione di posta predefinita. +plugin.addrbook.OUTLOOK_IS_NOT_DEFAULT_MAIL_CLIENT={0} non può accedere ai contatti di Microsoft Outlook perché Outlook non è impostato come applicazione di posta predefinita. plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Imposta Outlook come applicazione di posta predefinita # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Contatti Google -impl.googlecontacts.NEW=Nuovo impl.googlecontacts.EDIT=modifica -impl.googlecontacts.REMOVE=Rimuovi impl.googlecontacts.ENABLED=Abilitato impl.googlecontacts.ACCOUNT_NAME=Nome account impl.googlecontacts.SAVE=Salva @@ -900,11 +859,8 @@ plugin.accountinfo.ORGANIZATION=Nome organizzazione: plugin.accountinfo.JOB_TITLE=Qualifica: plugin.accountinfo.ABOUT_ME=Informazioni su di me: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Foto dell'utente plugin.accountinfo.GLOBAL_ICON=Usa icona globale plugin.accountinfo.LOCAL_ICON=Usa questa icona -plugin.accountinfo.CHANGE=Cambia -plugin.accountinfo.ONLY_MESSAGE=Solo messaggi # connection info plugin.connectioninfo.TITLE=Informazioni sulla connessione @@ -924,49 +880,13 @@ plugin.aimaccregwizz.USERNAME=Nome utente AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nome utente e password plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registra nuovo account plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Se non hai un account AIM, premi questo bottone per crearne uno nuovo. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Sovrascrivi le opzioni predefinite del server # branding plugin.branding.ABOUT_WINDOW_TITLE=Informazioni su {0} plugin.branding.LOGO_MESSAGE=VoIP && Messaggistica Istantanea Open Source -plugin.branding.LOADING=Caricamento in corso plugin.branding.ABOUT_MENU_ENTRY=&Informazioni su... -plugin.branding.WELCOME_MESSAGE=
    {1} è sotto attivo sviluppo. La versione che stai utilizzando è sperimentale e POTREBBE NON funzionare come previsto. Consulta {2} per maggiori informazioni.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Tutti i diritti riservati. Visita https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi è distribuito sotto i termini della LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Dizionari -plugin.dictaccregwizz.ANY_DICTIONARY=Qualunque dizionario -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Qualunque dizionario da {0} -plugin.dictaccregwizz.FIRST_MATCH=Prima corrispondenza -plugin.dictaccregwizz.NO_MATCH=Nessuna corrispondenza -plugin.dictaccregwizz.MATCH_RESULT=Nessuna definizione trovata per "{0}", forse intendevi:\n -plugin.dictaccregwizz.INVALID_DATABASE=Il dizionario attuale "{0}" non esiste più sul server. -plugin.dictaccregwizz.INVALID_STRATEGY=La strategia attuale non è disponibile sul server. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Il protocollo Dict -plugin.dictaccregwizz.HOST=Server -plugin.dictaccregwizz.SERVER_INFO=Informazioni server -plugin.dictaccregwizz.STRATEGY_SELECTION=Seleziona strategia -plugin.dictaccregwizz.STRATEGY_LIST=Lista strategie: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Cerca strategie -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Una strategia è utilizzata per cercare parole simili, se una traduzione non è stata trovata, grazie a differenti approcci. Ad esempio le strategie Prefix cercano parole che iniziano come la parola che vuoi tradurre. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informazione account Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Questa procedura guidata creerà il tuo primo account Dict per te su dict.org.\n\nPuoi aggiungere nuovi dizionari entrando nella Procedura guidata di registrazione account. Riempi il campo host con il dizionario che vuoi aggiungere. -plugin.dictaccregwizz.THREAD_CONNECT=Sto tentando di connettermi al server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Connessione fallita: questo non è un server dict oppure il server è offline -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Scaricamento strategie in corso -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Nessuna strategia trovata sul server -plugin.dictaccregwizz.POPULATE_LIST=Sto popolando la lista -plugin.dictaccregwizz.CLOSING_CONNECTION=Chiusura connessione in corso - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Per poter utilizzare la chat di Facebook devi creare un nome utente
    dalla pagina "Impostazioni account" su Facebook.


    Nota: Quando hai creato un nome utente devi effetturare il logout dalla pagina web
    e potrebbe passare del tempo prima che tu possa effettuare il login con il nuovo nome utente!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Il protocollo Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nome utente: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nome utente e Password + +plugin.busylampfield.PICKUP=Raccogli chiamata # generalconfig plugin.generalconfig.AUTO_START=Esegui automaticamente {0} quando il computer viene avviato @@ -977,9 +897,6 @@ plugin.generalconfig.SHOW_HISTORY=Mostra plugin.generalconfig.HISTORY_SIZE=messaggi recenti nelle nuove chat plugin.generalconfig.SEND_MESSAGES_WITH=Invia messaggi con: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Poni la finestra di chat in primo piano -plugin.generalconfig.ERROR_PERMISSION=Non hai permessi sufficienti per rimuovere l'avvio automatico -plugin.generalconfig.TRANSPARENCY=Trasparenza -plugin.generalconfig.ENABLE_TRANSPARENCY=Abilita trasparenza plugin.generalconfig.DEFAULT_LANGUAGE=Lingua interfaccia plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=I cambiamenti effettuati saranno effettivi al prossimo avvio del programma. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% tradotto @@ -1036,13 +953,19 @@ plugin.ircaccregwizz.HOST=Server: plugin.ircaccregwizz.IRC_SERVER=Server plugin.ircaccregwizz.EXAMPLE_SERVER=Es: chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Usa connessione sicura +plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Rileva presenza contatti +plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Rileva presenze nella chat room +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE=Autenticazione SASL +plugin.ircaccregwizz.ENABLE_SASL_AUTHENTICATION=Abilita autenticazione SASL +plugin.ircaccregwizz.SASL_USERNAME=Nome utente +plugin.ircaccregwizz.SASL_AUTHZ_ROLE=Ruolo +plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=La password IRC sopra è usata per l'autenticazione SASL +plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Risolvi sempre i nomi DNS attraverso il proxy # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Il protocollo XMPP plugin.jabberaccregwizz.USERNAME=Nome utente XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Conferma password -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=Nome utente e password plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Connetti server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Abilita keep alive @@ -1058,13 +981,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Commento plugin.jabberaccregwizz.RESOURCE=Risorsa plugin.jabberaccregwizz.AUTORESOURCE=Genera la risorsa automaticamente plugin.jabberaccregwizz.PRIORITY=Priorità -plugin.jabberaccregwizz.XMPP_ERROR=Errore XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Errore XMPP sconosciuto ({0}). Controlla che il nome del server sia corretto. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Le password non corrispondono. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Sovrascrivi le opzioni di default del server -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Opzioni avanzate plugin.jabberaccregwizz.USE_ICE=Usa ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Usa Jingle/ICE di Google (sperimentale) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Scopri automaticamente i server STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=Abilita TURN plugin.jabberaccregwizz.TURN_USERNAME=Nome utente TURN @@ -1088,14 +1007,12 @@ plugin.jabberaccregwizz.EXISTING_ACCOUNT=Account XMPP esistente plugin.jabberaccregwizz.DOMAIN_BYPASS_CAPS=Dominio per le chiamate GTalk plugin.jabberaccregwizz.TELEPHONY_DOMAIN=Dominio telefonico plugin.jabberaccregwizz.ALLOW_NON_SECURE=Permetti connessioni insicure +plugin.jabberaccregwizz.DISABLE_CARBON=Disabilita le copie carbone dei messaggi plugin.jabberaccregwizz.DTMF_AUTO=Auto: Scegli automaticamente tra RTP e Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Opzioni del server plugin.jabberaccregwizz.CHANGE_PASSWORD=Cambia la password dell'account -plugin.jabberaccregwizz.NEW_PASSWORD=Nuova password -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Conferma nuova password plugin.jabberaccregwizz.PORT_FIELD_INVALID=Inserisci una porta del server valida per continuare plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Devi essere loggato all'account prima di poter cambiare la password. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Il campo della password è vuoto. plugin.jabberaccregwizz.TLS_REQUIRED=La connessione non usa TLS, quindi non sarà effettuato il cambio della password. plugin.jabberaccregwizz.PASSWORD_CHANGED=La password è stata cambiata correttamente plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Questo server XMPP non supporta il cambio della password. @@ -1109,25 +1026,9 @@ plugin.jabberaccregwizz.RESET=Ripristina plugin.jabberaccregwizz.RESET_DESCRIPTION=Ripristina alle impostazioni globali plugin.jabberaccregwizz.DISABLE_JINGLE=Disabilita Jingle (chiamate vocali e videochiamate tramite XMPP). -# mailbox -plugin.mailbox.OUTGOING=Messaggio in uscita: -plugin.mailbox.INCOMING=Messaggi in arrivo: -plugin.mailbox.WAIT_TIME=Attesa prima che la chiamata venga trasferita alla casella vocale -plugin.mailbox.MAX_MESSAGE_TIME=Durata massima dei messaggi in arrivo -plugin.mailbox.CONFIRM=Conferma -plugin.mailbox.DEFAULTS=Default -plugin.mailbox.MAILBOX=Casella di posta elettronica - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Un protocollo per connettersi e chattare su MSN. -plugin.msnaccregwizz.USERNAME=Email: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID e password - # plugin manager plugin.pluginmanager.INSTALL=Installa plugin.pluginmanager.UNINSTALL=Disinstalla -plugin.pluginmanager.UPDATE=Aggiorna plugin.pluginmanager.PLUGINS=Plug-in plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=Seleziona file @@ -1152,7 +1053,6 @@ plugin.sipaccregwizz.SERVER_PORT=Porta server plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Porta del proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Trasporto preferenziale -plugin.sipaccregwizz.ADVANCED_OPTIONS=Opzioni avanzate plugin.sipaccregwizz.PROXY_OPTIONS=Opzioni del proxy plugin.sipaccregwizz.PROXY_AUTO=Configura il proxy server automaticamente plugin.sipaccregwizz.ENABLE_PRESENCE=Attiva presenza (SIMPLE) @@ -1172,8 +1072,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Scegli automaticamente tra RTP e Inband (no plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Sovrascrivi le opzioni di default del server plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Abilita supporto per chiamate criptate plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Annuncia il supporto di ZRTP nel protocollo di segnalazione plugin.sipaccregwizz.AUTH_NAME=Authorization name @@ -1194,10 +1092,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI per il controllo della casella voca plugin.sipaccregwizz.NOT_SAME_PASSWORD=Le password non corrispondono. plugin.sipaccregwizz.NO_CERTIFICATE= (usa l'autenticazione tradizionale) plugin.sipaccregwizz.SAVP_OPTION=Indicazione RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Off (annuncia solo il supporto per RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Obbligatorio (offri e accetta solo RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Opzionale (preferisci RTP/SAVP a RTP/AVP, ma accetta entrambi) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Abilita il "Descrittore S" (conosciuto anche come SDES o SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Scegli i protocolli di cifratura da abilitare e la loro priorità (il più importante sopra): plugin.sipaccregwizz.CIPHER_SUITES=Suite di cifratura abilitate: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} cercherà automaticamente di cifrare tutte le chiamate mediante ZRTP e ci sarà una notifica sonora e visiva una volta che la connessione sicura sarà stabilità. Dovresti cambiare le impostazioni avanzate solo se sei consapevole di quello che stai facendo.
    @@ -1211,15 +1109,6 @@ plugin.skinmanager.DEFAULT_SKIN=Skin predefinita plugin.skinmanager.ADD_NEW_SKIN=Aggiungi una nuova skin... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=La skin predefinita dell'applicazione. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Un protocollo per collegarsi a macchine remote tramite SSH. -plugin.sshaccregwizz.USERNAME=Account ID: -plugin.sshaccregwizz.IDENTITY_FILE=File di identità: -plugin.sshaccregwizz.KNOWN_HOSTS=Host conosciuti: -plugin.sshaccregwizz.OPTIONAL=Opzionale -plugin.sshaccregwizz.ACCOUNT_DETAILS=Dettagli account - # status update plugin.autoaway.AUTO_STATUS=Stato di "assente" automatico plugin.autoaway.ENABLE_CHANGE_STATUS=Cambia stato mentre sei assente @@ -1239,6 +1128,7 @@ plugin.updatechecker.DIALOG_NOUPDATE_TITLE=Nessuna nuova versione plugin.updatechecker.DIALOG_MISSING_UPDATE=L'installatore degli aggiornamenti è mancante. # usersearch +plugin.usersearch.USER_SEARCH=Cerca utente # whiteboard plugin.whiteboard.TITLE=Lavagna [Beta] @@ -1266,22 +1156,6 @@ plugin.whiteboard.DESELECT=Deseleziona plugin.whiteboard.DELETE=Cancella plugin.whiteboard.PROPERTIES=Proprietà -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Collegati e chatta usando Yahoo! -plugin.yahooaccregwizz.USERNAME=Nome utente: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Nome utente e password - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Il protocollo Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Nome: -plugin.zeroaccregwizz.LAST_NAME=Cognome: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Ricorda contatti Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=User ID e password -plugin.zeroaccregwizz.USERID=User ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Il protocollo Google Talk @@ -1295,19 +1169,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, the IP Telecommunications plugin.iptelaccregwizz.USERNAME=Nome utente plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Iscriviti a iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP e chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Nome utente plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Reinserisci la password plugin.sip2sipaccregwizz.EMAIL=Indirizzo e-mail -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Per aiuto riguardo questo servizio visita
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=L'indirizzo e-mail è usato per spedire messaggi vocali,
    notifiche di chiamate perse e per recuperare la password smarrita -plugin.sip2sipaccregwizz.INFO_NOTE=Per aiuto riguardo questo servizio visita http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Account sip2sip.info esistente -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Crea un account sip2sip.info gratuito - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Messaggistica Istantanea plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Per aiuto riguardo questo servizio visita
    http://ippi.fr @@ -1316,6 +1182,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Account ippi esistente plugin.ippiaccregwizz.CREATE_ACCOUNT=Crea un account ippi gratuito # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Chiudi finestra chat plugin.keybindings.CHAT_COPY=Copia plugin.keybindings.CHAT_CUT=Taglia @@ -1338,10 +1205,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Nome plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Scorciatoia primaria plugin.keybindings.globalchooser.SHORTCUT_SECOND=Scorciatoia secondaria plugin.keybindings.globalchooser.PRESS_BTN=Premi per impostare la scorciatoia -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=In attesa plugin.keybindings.globalchooser.PUSH_TO_TALK=Push to talk plugin.keybindings.globalchooser.ENABLE_SPECIAL=Abilita il rilevamento dei tasti speciali plugin.keybindings.PLUGIN_NAME=Scorciatoie +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Principale plugin.keybindings.GLOBAL=Scorciatoie globali @@ -1369,6 +1236,7 @@ plugin.notificationconfig.tableheader.SOUND=Riproduci un suono attraverso il dis plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Riproduci un suono attraverso il dispositivo audio usato per la voce plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Riproduci un suono attraverso gli altoparlanti del PC plugin.notificationconfig.tableheader.DESCRIPTION=Descrizione dell'evento +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Chiamata in arrivo plugin.notificationconfig.event.SecurityMessage=Messaggio di sicurezza plugin.notificationconfig.event.IncomingFile=File in arrivo @@ -1470,6 +1338,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Intra Refresh periodico impl.neomedia.configform.H264.defaultProfile=Profilo predefinito per la codifica: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Baseline impl.neomedia.configform.H264.defaultProfile.high=High impl.neomedia.configform.H264.defaultProfile.main=Main @@ -1500,7 +1369,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Password attuale: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Inserisci una nuova password: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Reinserisci la nuova password: plugin.securityconfig.masterpassword.MP_TITLE=Password principale -plugin.securityconfig.masterpassword.MP_NOT_SET=(non impostata) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=La password principale inserita non è corretta. Riprova. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=La password principale non è corretta! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Cambio password fallito @@ -1516,7 +1384,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Password plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(sconosciuto) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(non posso decifrare) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Password salvate -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Rimuovi plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Rimuovi tutte plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Sei sicuro di voler rimuovere tutte le password? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Rimuovi tutte le password @@ -1601,7 +1468,7 @@ plugin.otr.activator.unreadablemsgreceived={0} ti ha inviato un messaggio cifrat plugin.otr.activator.requireencryption=Il tuo messaggio [{0}] non è stato inviato. È richiesta la messaggistica privata. plugin.otr.activator.unreadablemsgreply=Hai inviato a {0} un messaggio criptato illeggibile. Per favore termina la conversazione privata con {1} o aggiornala. plugin.otr.activator.fallbackmessage={0} vuole iniziare una conversazione con cifratura Off-The-Record con te. Il tuo software, però, non supporta la cifratura Off-The-Record. Per maggiori informazioni visita http://en.wikipedia.org/wiki/Off-the-Record_Messaging (pagina in inglese) -plugin.otr.activator.multipleinstancesdetected={0} è collegato su più di un dispositivo e OTR ha aperto diverse sessioni. Puoi selezionare a quale sessione inviare il messaggio dal menù qui in basso. +plugin.otr.activator.multipleinstancesdetected=Il tuo amico {0} è collegato su più di un dispositivo e OTR ha aperto diverse sessioni. Puoi selezionare a quale sessione inviare il messaggio dal menù qui sotto. plugin.otr.activator.msgfromanotherinstance={0} ti ha inviato un messaggio destinato ad un'altra sessione. Se sei collegato da più di un dispositivo, hai ricevuto il messaggio su uno di questi. # global proxy plugin @@ -1612,7 +1479,6 @@ plugin.globalproxy.PROXY_PORT=Porta plugin.globalproxy.PROXY_USERNAME=Nome utente plugin.globalproxy.PROXY_PASSWORD=Password plugin.globalproxy.DESCRIPTION={0} userà le impostazioni proxy specificate per tutte le reti cui ti connetterai d''ora in poi. \nIl supporto per i server proxy è sperimentale e funziona solo con alcuni protocolli. Controlla la tabella sottostante per maggiori dettagli: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOCKS4/5 SOCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Usa il proxy anche per le richieste DNS plugin.globalproxy.FWD_DNS_NOTE=Utile con Tor. Aiuta ad evitare fughe di informazioni tramite il DNS inoltrando tutto il traffico DNS al proxy Tor. Richiede il riavvio. @@ -1629,9 +1495,11 @@ plugin.reconnectplugin.NETWORK_DOWN=Connessione di rete persa! plugin.chatconfig.TITLE=Chat plugin.chatconfig.replacement.TITLE=Immagini/Video: plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Attiva la sostituzione automatica degli smiley -plugin.chatconfig.replacement.REPLACEMENT_TITLE=Attiva l'anteprima automatica di immagini e video +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Sostituisci immagini/video plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Abilita +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL=Disabilita (mostra anteprima del collegamento) plugin.chatconfig.replacement.DISABLE_REPLACEMENT=Disabilita +plugin.chatconfig.replacement.CONFIGURE_REPLACEMENT=Cambia impostazioni per la sostituzione di Immagini o Video plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Origini: plugin.chatconfig.spellcheck.TITLE=Controllo ortografico @@ -1648,7 +1516,6 @@ plugin.provisioning.RESTART_WARNING=Nota che i cambiamenti avranno effetto solo plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Copia l'UUID negli appunti plugin.provisioning.CLIPBOARD_FAILED=Si è verificato un errore nel copiare l'UUID negli appunti -plugin.provisioning.EXIT_ON_FAIL=Esci dall'applicazione se il provisioning fallisce plugin.provisioning.CREDENTIALS=Ultime credenziali salvate per il provisioning plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Sei sicuro di voler rimuovere la password per il provisioning? plugin.provisioning.PROV_FAILED=Il provisioning è fallito @@ -1715,8 +1582,6 @@ util.dns.DNSSEC_WARNING=
    {0} ha provato a connettersi al s #plugin spellcheck plugin.spellcheck.TITLE=Ortografia e Grammatica plugin.spellcheck.MENU=Mostra controllo ortografico -plugin.spellcheck.LANG=Lingua -plugin.spellcheck.EDIT_PERSONAL_DICT=Modifica plugin.spellcheck.ENABLE_SPELL_CHECK=Attiva controllo ortografico plugin.spellcheck.dialog.FIND=Trova successivo plugin.spellcheck.dialog.REPLACE=Sostituisci -- cgit v1.1 From ae1df895303c7c34de4c894f0091f998444d622c Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:14 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1473 of 1505 strings translated (4 fuzzy). --- resources/languages/resources_sv.properties | 219 +++++----------------------- 1 file changed, 34 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_sv.properties b/resources/languages/resources_sv.properties index f0ce7a6..cd9ba06 100644 --- a/resources/languages/resources_sv.properties +++ b/resources/languages/resources_sv.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Jag service.gui.ACCOUNT_REGISTRATION_WIZARD=Registreringsguide service.gui.ACCOUNTS=Konton service.gui.ADD=&Lägg till -service.gui.ADD_ACCOUNT=Lägg till konto service.gui.ADD_CONTACT=&Lägg till kontakt service.gui.ADD_AUTHORIZED_CONTACT=Lägg till {0} i din kontaktlista service.gui.ADD_CONTACT_TO_CONTACTLIST=Lägg till kontakten i din kontaktlista @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Fel när kontakt lades till service.gui.ADD_CONTACT_EXIST_ERROR={0} finns redan i din kontaktlista. service.gui.ADD_CONTACT_NETWORK_ERROR=Servern svarade inte vid begäran om att lägga till kontakten {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Kunde inte lägga till kontakt med id: {0}. Åtgärden stöds inte. -service.gui.ADD_CONTACT_IDENTIFIER=Ange identifierare för den kontakt du vill lägga till i fältet nedan. -service.gui.ADD_CONTACT_WIZARD=Guide för att lägga till kontakt service.gui.ADD_CONTACT_NOT_CONNECTED=Du måste vara ansluten för att lägga till kontakter. Logga in hos den valda leverantören och försök igen. service.gui.ADD_GROUP_LOCAL_ERROR=Kunde inte lägga till gruppnamnet: {0}. Problemet uppstod under en lokal I/O-åtgärd. service.gui.ADD_GROUP_EXIST_ERROR={0} finns redan i din kontaktlista. Välj ett annat gruppnamn. service.gui.ADD_GROUP_NET_ERROR=Kunde inte lägga till gruppnamnet: {0}. Problemet uppstod på grund av ett nätverksfel. Kontrollera din nätverksanslutning och försök igen. service.gui.ADD_GROUP_ERROR=Kunde inte lägga till grupp med namn: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Gruppnamnet får inte lämnas tomt. -service.gui.ADD_GROUP=Skapa grupp -service.gui.ADD_SUBCONTACT=&Lägg till underkontakt service.gui.ADDRESS=Adress service.gui.ADMINISTRATOR=administratör service.gui.ADVANCED=&Avancerat -service.gui.ALL=&Alla service.gui.ALL_CONTACTS=&Alla kontakter service.gui.ALTERNATE_ADDRESS=Alternativ adress service.gui.APPLY=&Verkställ @@ -65,7 +70,6 @@ service.gui.AT=på service.gui.AUTHORIZE=&Auktorisera service.gui.AUTHORIZATION_ACCEPTED={0} har godkänt din auktoriseringsbegäran. service.gui.AUTHENTICATION_FAILED=Autentisering av {0} misslyckades. Lösenordet är felaktigt. -service.gui.AUTHENTICATION_REQUESTED=Auktorisering begärd service.gui.AUTHENTICATION_REQUESTED_SERVER=Servern {0} begär att du autentiserar dig. service.gui.AUTHENTICATION_REJECTED={0} har nekat din begäran om auktorisering. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autentisering @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=I nedanstående fält kan du ange ditt nya anv service.gui.CHANGE_NICKNAME_ERROR=Kunde inte byta användarnamn service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Användarnamnet finns redan service.gui.CHANGE_VIDEO_QUALITY=Ändra videokvalitet -service.gui.CHAT_CONFERENCE_LABEL=Konferenser service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}s konferens service.gui.CHAT_ROOM_ALREADY_JOINED={0} är redan anslutet. service.gui.CHAT_ROOM_CONFIGURATION=Konfiguration för {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=har lämnat {0} service.gui.CHAT_ROOM_USER_KICKED=har kickats från {0} service.gui.CHAT_ROOM_USER_QUIT=har kopplat ner {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Skicka meddelanden är inte tillåtet (återkallat) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Sparar chattrummet för framtida bruk -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Ta bort markerat rum från listan över sparade chattrum service.gui.CHAT_ROOM_NAME=Namn på chattrum service.gui.CLEAR_CUSTOM_MESSAGES=Rensa anpassade meddelanden service.gui.ROOM_NAME=Chattrum -service.gui.AUTOJOIN=Anslut automatiskt service.gui.CHANGE_PASSWORD=Ändra lösenord service.gui.CHAT_ROOM_NAME_INFO=Ange namnet på det chattrum du vill skapa, i nedanstående fält. service.gui.CHAT_ROOM_NOT_EXIST={0} kunde inte hittas på {1}. Kontrollera att du angett rätt namn. service.gui.CHAT_ROOM_NOT_CONNECTED=Du måste vara inloggad för att kunna ansluta till {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Du måste vara inloggad för att kunna lämna ett chattrum. -service.gui.CHAT_ROOM_NOT_JOINED=Du måste vara ansluten till ett chattrum för att kunna vidta ytterligare åtgärder med det. service.gui.CHAT_ROOM_OPTIONS=Alternativ för chattrum service.gui.CHAT_ROOM_REGISTRATION_REQUIRED={0} kräver registrering för att ansluta. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Chattrummet {0} begär ett lösenord. @@ -151,22 +150,18 @@ service.gui.CLEAR=Rensa service.gui.CLOSE=St&äng service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Det kom ett nytt meddelande för mindre än 2 sekunder sedan. Vill du verkligen stänga den här chatten? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=En eller flera filöverföringar pågår. Vill du verkligen avbryta? -service.gui.CONFIRM=Bekräfta service.gui.CONNECTED_STATUS=Ansluten service.gui.CONNECTING=Ansluter... service.gui.CONNECTING_STATUS=Ansluter service.gui.CONNECTING_EARLY_MEDIA_STATUS=Ansluter* service.gui.CONNECTION=Anslutning -service.gui.CONNECTION_FAILED_MSG=Anslutningen misslyckades för följande konto: {0}, Servernamn: {1}, Kontollera din nätverksanslutning eller kontakta din nätverksadministratör för mer information. service.gui.CONNECTION_EXPIRED_MSG=Du är för närvarande bortkopplad från servern {0}. service.gui.CONTACT_NAME=ID eller nummer -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY={0} saknar stöd för telefoni. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF={0} saknar stöd för chattkonferenser. service.gui.CONTACT_PAUSED_TYPING={0} tog paus i skrivandet service.gui.CONTACT_TYPING={0} skriver ett meddelande service.gui.CONTACT_TYPING_SEND_FAILED=öööh... vi kunde inte meddela {0} att du skrev service.gui.CONTACT_INFO=&Kontaktinfo -service.gui.CONTACTLIST=Kontaktlista service.gui.CONTACTS=Kontakter service.gui.COPY=&Kopiera service.gui.COPY_LINK=Kopiera &länk @@ -176,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Skapa chattrum... service.gui.CREATE_CHAT_ROOM_ERROR=Kunde inte skapa chattrummet {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Chattrumsguide service.gui.CREATE_CONFERENCE_CALL=&Skapa ett konferenssamtal... -service.gui.CREATE_CONFERENCE_CHAT=&Skapa en konferenschatt... service.gui.CREATE_GROUP=&Skapa grupp... service.gui.CREATE_GROUP_NAME=Ange namnet på den grupp du vill skapa, i nedanstående fält. -service.gui.CREATE_FIRST_GROUP_WIZARD=Din kontaktlista innehåller inga grupper. Skapa en grupp först (Arkiv/Skapa grupp). service.gui.CREATE_VIDEO_BRIDGE=Skapa en &videolänk... service.gui.CREATE_VIDEO_BRIDGE_MENU=Skapa en &videolänk service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Skapa / Anslut videokonferens service.gui.CREATE_VIDEO_CONFERENCE=Skapa ny videkonferens för detta chattrum service.gui.CONTACT_INFO_NOT_SUPPORTED=Den här kontakten saknar stöd för webbkontaktinfo service.gui.CUT=K&lipp ut -service.gui.DATE=Datum service.gui.DELETE=Ta bort service.gui.DENY=&Neka service.gui.DESKTOP_SHARING_WARNING=Vill du verkligen starta skärmdelning?
    Klickar du OK, kommer deltagare i den här konversationen att kunna se din skärm. @@ -197,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Frånkopplad service.gui.DND_STATUS=Stör ej service.gui.DO_NOT_ASK_AGAIN=Fråga inte igen service.gui.DO_NOT_SHOW_AGAIN=Visa inte det här meddelandet igen -service.gui.DOWNLOAD_NOW=&Ladda ner nu service.gui.DRAG_FOR_SHARING=Dra och släpp det du vill dela... service.gui.DURATION=varaktighet service.gui.DESTROY_CHATROOM=Ta bort chattrum @@ -218,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Fel från {0} service.gui.ESTIMATED_TIME=Uppskattad tid: service.gui.EVENTS=Händelser service.gui.EXIT=A&vsluta -service.gui.EXTENDED_CRITERIA=Utökade kriterier service.gui.GENERAL=Allmänt service.gui.GENERAL_ERROR=Allmänt fel service.gui.GROUP_NAME=Gruppnamn @@ -260,7 +250,6 @@ service.gui.FONT_ITALIC=Kursiv service.gui.FONT_SIZE=Storlek service.gui.FONT_STYLE=Stil service.gui.FONT_UNDERLINE=Understruken -service.gui.FROM={0} från {1} service.gui.GRANT_OWNERSHIP=Bevilja ägarskap... service.gui.GRANT_ADMIN=Bevilja administratörsbefogenhet... service.gui.GRANT_MODERATOR=Bevilja moderatorsbefogenhet @@ -286,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Vill du verkligen ta bort alla lokalt lag service.gui.HISTORY_REMOVE_ERROR=Kunde inte ta bort lokalt lagrade meddelanden. service.gui.HOME=Hem service.gui.HOME_PAGE=Hemsida -service.gui.HOUR=Timma service.gui.ICE=ICE service.gui.IDENTIFIER=Identifierare service.gui.IGNORE=&Ignorera @@ -310,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Bjud in kontakter till videolänk service.gui.INVITE_REASON=Inbjudningsorsak service.gui.IS_CALLING={0} ringer... service.gui.IS_NOW={0} är nu {1} -service.gui.JITSI_WARNING=SIP Communicator har nyligen bytt namn till Jitsi.
    Ladda ner Jitsi nu, om du vill att din version skall vara fortsatt aktuell.

    Vi är ledsna för alla eventuella besvär som detta kan orsaka dig.

    The Jitsi Dev Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator blir Jitsi service.gui.JOIN=&Anslut service.gui.JOIN_AS=A&nslut som service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Anslut till en pågående videokonferens service.gui.JOIN_VIDEO=Anslut video -service.gui.CLOSE_CHAT_ROOM_DIALOG=S&täng service.gui.JOB_TITLE=Yrkestitel service.gui.JOIN_CHAT_ROOM=&Anslut till chattrum... service.gui.JOIN_CHAT_ROOM_TITLE=Anslut till chattrum @@ -329,7 +314,6 @@ service.gui.KICK_FAILED=Det gick inte att kicka service.gui.KICK_FAILED_GENERAL_ERROR=Kunde inte kicka {0}. Ett allmänt serverfel uppstod. service.gui.KICK_FAILED_NOT_ALLOWED=Kunde inte kicka {0}. Ägare och administratörer i chattrummet kan inte kickas. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Kunde inte kicka {0}. Du har inte tillräcklig behörighet för att göra det. -service.gui.LAST=Senast service.gui.LAST_NAME=Senaste namnet service.gui.LEAVE=&Lämna service.gui.LIMIT_REACHED_FOR_IP=Du har för många befintliga registreringar från din IP-adress och servern {0} tillåter inte att du öppnar fler av dem. @@ -349,7 +333,6 @@ service.gui.MESSAGE=Meddelande service.gui.MISSED_CALLS_TOOL_TIP=Missade samtal från: service.gui.MISSED_CALLS_MORE_TOOL_TIP= och {0} till service.gui.MODERATOR=moderator -service.gui.MORE=Läs mer service.gui.MORE_LABEL=Mer service.gui.MOVE=Flytta service.gui.MOVE_SUBCONTACT=F&lytta kontakt @@ -358,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Den valda kontakten är densamma som källan. service.gui.MOVE_SUBCONTACT_QUESTION=Vill du verkligen flytta {0} till {1}? service.gui.MOVE_TO_GROUP=&Flytta till grupp service.gui.MOVE_CONTACT=Flytta kontakt -service.gui.MOVE_CONTACT_ERROR=&Kontakten kan inte flyttas service.gui.MSG_DELIVERY_FAILURE=Meddelandet ovan kunde inte levereras service.gui.MSG_DELIVERY_NOT_SUPPORTED=Det protokoll du använder, stöder inte offline-meddelanden. Du kan försöka nå {0} genom ett annat protokoll eller vänta tills han/hon är online. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Ett internt fel uppstod. Det är troligen en bugg. Rapportera den gärna här: https://jitsi.org/Development/BugsAndIssues. @@ -372,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Du måste vara ansluten för att skicka service.gui.MULTIPLE_LOGINS=Du har loggat in mer än en gång med samma konto. Följande konto är nu nerkopplat: Användarnamn: {0}, Servernamn: {1} service.gui.MY_CHAT_ROOMS=Lägg till chattrum service.gui.MY_CHAT_ROOMS_TITLE=Lägg till chattrum -service.gui.MUTE=Ljud av service.gui.MUTUALLY_ON_HOLD_STATUS=Ömsesidigt parkerad service.gui.NAME=Namn service.gui.NETWORK=Nätverk @@ -404,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Inte på kontaktlistan service.gui.SD_QUALITY=Standardkvalitet service.gui.OFFLINE=Offline service.gui.OK=&OK -service.gui.OLDER_CALLS=Äldre samtal service.gui.ONLINE=Online service.gui.OPEN=Öppna service.gui.OPEN_FILE_FROM_IMAGE=Dubbelklicka för att öppna en fil. @@ -416,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Öppna vid aktivitet service.gui.OPEN_ON_MESSAGE=Öppna enbart vid nytt meddelande service.gui.OPEN_ON_IMPORTANT_MESSAGE=Öppna enbart vid viktiga meddelanden service.gui.OR=eller -service.gui.OR_ENTER_PHONE_NUMBER=Eller ange telefonnummer här... service.gui.ORGANIZATION=Organisation service.gui.OTHER=Annat service.gui.chat.role.OWNER=Ägare @@ -442,7 +421,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Retur' för förslag service.gui.PRESS_FOR_CALL_INFO=Tryck för samtalsinfo service.gui.PRESS_TO_OPEN_CRM=Klicka för att öppna CRM-program service.gui.PREVIOUS=Föregående -service.gui.PREVIOUS_TOOLTIP=Bläddra bland äldre konversationer service.gui.PRINT=&Skriv ut service.gui.PROACTIVE_NOTIFICATION=skriver ett meddelande service.gui.PROBLEMS_ENCOUNTERED=Problem som uppstått @@ -458,7 +436,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Du har kopplat ner och återanslutit fö service.gui.RE_REQUEST_AUTHORIZATION=Begär auktorisering igen service.gui.REFERRED_STATUS=Hänvisning service.gui.REJECT=&Avböj -service.gui.REMIND_ME_LATER=Påminn mig senare service.gui.REMEMBER_PASSWORD=Kom ihåg lösenordet service.gui.REMOVE=&Ta bort service.gui.REMOVE_ACCOUNT=&Ta bort konto @@ -484,29 +461,20 @@ service.gui.REVOKE_ADMIN=Återkalla administratörstatus service.gui.REVOKE_MODERATOR=Återkalla moderatorstatus service.gui.REVOKE_MEMBERSHIP=Återkalla medlemskap service.gui.REVOKE_VOICE=Återkalla röst -service.gui.ROOT_GROUP=Root-grupp service.gui.SAVE=&Spara -service.gui.SAVE_AS_DEFAULT=Spara som standard service.gui.SEARCH=&Sök service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Klicka på knappen nedan för att visa alla chattrum på den valda servern. Markera sedan det du vill ansluta till, och tryck på 'Anslut'. service.gui.SEARCH_STRING_CONTACT_SOURCE=Sökt kontakt service.gui.SECURITY=Säkerhet -service.gui.SELECT_ACCOUNT=Välj konto service.gui.SELECT_COLOR=Välj färg service.gui.SELECT_GROUP=Välj grupp -service.gui.SELECT_GROUP_WIZARD_MSG=Nedanstående lista innehåller alla grupper i din kontaktlista. Välj i vilken grupp du vill lägga till den nya kontakten. service.gui.SELECT_NO_GROUP=Ingen grupp -service.gui.SELECT_GROUP_WIZARD=Specificera grupp service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Nedanstående lista innehåller alla konton som stöder fleranvändarchatt. Välj vilket du vill använda för att skapa ditt chattrum. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Nedanstående lista innehåller alla registrerade konton. Välj vilket du vill använda för att kommunicera med den nya kontakten. -service.gui.SELECT_PROVIDERS_WIZARD=Välj konto service.gui.SELECT_VIDEO_CONFERENCE=Välj videokonferens service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Välj chatt från listan och tryck OK för att lägga till den. service.gui.SEND=&Skicka service.gui.SEND_FILE=Skicka &fil -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Det finns ingen info om den här kontakten. service.gui.SEND_MESSAGE=&Skicka ett meddelande -service.gui.SEND_AS_SMS=Skicka som SMS service.gui.SEND_PRIVATE_MESSAGE=Skicka privat meddelande service.gui.SEND_SMS=S&kicka SMS service.gui.SEND_SMS_DETAILS=Kom ihåg att du måste ange numret i internationellt format med inledande landskod (+46 för Sverige). Exempel: +4670123456 @@ -545,7 +513,6 @@ service.gui.STREET=Gatuadress service.gui.SUBJECT=Ämne service.gui.SUMMARY=Sammandrag service.gui.TELEPHONY=Telefoni -service.gui.TODAY=I dag service.gui.TOOLS=&Verktyg service.gui.TRANSFER=&Överför service.gui.TO=&Till: @@ -555,7 +522,6 @@ service.gui.TRANSFER_CALL_TO=Överför till: service.gui.TRANSPARENCY_NOT_ENABLED=Transparens stöds inte av din aktuella konfiguration. service.gui.TYPE_YOUR_REQUEST=Ange din begäran här service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Videokvaliteten kunde inte ändras för det här samtalet. -service.gui.UNMUTE=Ljud på service.gui.USER_IDENTIFIER=Användaridentifierare: service.gui.USER_EXISTS_ERROR=Den här användaren finns redan på det valda nätverket. Välj annan användare eller nätverk. service.gui.USERNAME_NULL=Ange användarnamn och lösenord. @@ -568,7 +534,6 @@ service.gui.USE_PROVISIONING=Använd online-etablering service.gui.VALUE=Värde service.gui.VIDEO_CALL=&Videosamtal service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Visa service.gui.VIEW_HISTORY=Visa &historik service.gui.VIEW_SMILEYS=Visa &smileys @@ -588,9 +553,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Justera volymen service.gui.WAITING_AUTHORIZATION=Väntar på auktorisation service.gui.WARNING=Varning service.gui.YES=Ja -service.gui.YESTERDAY=I går -service.gui.EXISTING_ACCOUNT_ERROR=Kontot du angett är redan installerat. -service.gui.NEW_MAIL=Du har ett nytt e-postmeddelande!
    Från: {0} {1}
    Ämne: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Det finns ett nytt e-postmeddelande i din {0} inbox:
    service.gui.NEW_GMAIL_MANY_HEADER=Det finns {2} nya e-postmeddelande i din {0} inbox:
    service.gui.NEW_GMAIL_FOOTER=ett till oläst meddelande i din inbox.
    @@ -602,6 +564,8 @@ service.gui.ENTER_FULL_SCREEN_TOOL_TIP=Helskärmsläge service.gui.EXIT_FULL_SCREEN_TOOL_TIP=Fönsterläge service.gui.HOLD_BUTTON_TOOL_TIP=Parkera/Återuppta service.gui.MUTE_BUTTON_TOOL_TIP=Använd paus eller parkeringsknappen för att aktivera/avaktivera mikrofonljudet +service.gui.PARK=Parkera +service.gui.PARK_BUTTON_TOOL_TIP=Parkera samtal service.gui.RECORD_BUTTON_TOOL_TIP=Spela in/Stoppa service.gui.LOCAL_VIDEO_BUTTON_TOOL_TIP=Video på/av service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Visa/Dölj lokal video @@ -614,7 +578,6 @@ service.gui.SECURITY_ERROR=Säkerhetsfel service.gui.SPEED=Hastighet: service.gui.SILENT_MEMBER=tyst medlem service.gui.NON_SECURE_CONNECTION=Säker anslutning kan inte skapas för {0}. Om du vill ansluta till en icke säker server, måste du bocka för "Tillåt osäkra anslutningar" i dina kontoinställningar -service.gui.UPDATE=Uppdatera service.gui.MOBILE_PHONE=Mobil service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Arbete @@ -649,12 +612,10 @@ service.gui.callinfo.CALL_INFORMATION=Samtalsinformation service.gui.callinfo.CALL_IDENTITY=Identitet service.gui.callinfo.PEER_COUNT=Antal deltagare service.gui.callinfo.IS_CONFERENCE_FOCUS=Konferensfokus -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Kryptering aktiverad service.gui.callinfo.CALL_TRANSPORT=Signalerar samtalsöverföring service.gui.callinfo.CALL_DURATION=Samtalets varaktighet service.gui.callinfo.TLS_PROTOCOL=TLS-protokoll service.gui.callinfo.TLS_CIPHER_SUITE=TLS-chifferlista -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Certifikatkedja för TLS-server service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Innehållet i TLS servercertifikatet visas nedan. service.gui.callinfo.VIEW_CERTIFICATE=Visa certifikat service.gui.callinfo.CODEC=Codec /Frekvens @@ -664,7 +625,6 @@ service.gui.callinfo.AUDIO_INFO=Ljudinfo service.gui.callinfo.VIDEO_INFO=Videoinfo service.gui.callinfo.LOCAL_IP=Lokalt IP / Port service.gui.callinfo.REMOTE_IP=Fjärr-IP / Port -service.gui.callinfo.BANDWITH=Bandbredd service.gui.callinfo.LOSS_RATE=Förlustfrekvens service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -674,10 +634,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Key exchange protocol service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE-kandidat utökad typ service.gui.callinfo.ICE_STATE=ICE processtatus + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Insamlingskandidater service.gui.callinfo.ICE_STATE.RUNNING=Anslutningskontroller service.gui.callinfo.ICE_STATE.COMPLETED=Slutförd service.gui.callinfo.ICE_STATE.FAILED=Misslyckades + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Lokalt värd-IP / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Lokalt reflexivt IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Lokalt reläat IP / Port @@ -698,11 +661,12 @@ service.gui.ALWAYS_TRUST=Lita alltid på det här certifikatet service.gui.CERT_DIALOG_TITLE=Verifiera certifikat service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} kan inte verifiera serverns identitet vid anslutning till
    {1}.

    Certifikatet är inte betrott, vilket innebär att serverns identitet inte kan verifieras automatiskt

    Vill du tillåta anslutningen?
    Klicka på ''Visa certifikat'' för mer information. service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} kan inte verifiera serverns certifikat.

    Certifikatet är inte betrott, vilket innebär att serverns identitet inte kan verifieras automatiskt.
    Vill du tillåta anslutningen?

    Klicka på ''Visa certifikat'' för mer information. -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} kan inte verifiera identiteten för anslutande klient.

    Certifikatet är inte betrott, vilket innebär att klientens identitet inte kan
    verifieras automatiskt. Vill du tillåta anslutningen?

    Klicka på ''Visa certifikat'' för mer information. service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} kan inte verifiera identiteten för {1}.

    Certifikatet är inte betrott, vilket innebär att peer-identitet inte kan
    verifieras automatiskt. Vill du tillåta anslutningen?

    Klicka på ''Visa certifikat'' för mer information. service.gui.CONTINUE_ANYWAY=Fortsätt ändå service.gui.CERT_INFO_CHAIN=Certifikatkedja: service.gui.CERT_INFO_ISSUED_TO=Utfärdat till + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nätverksnamn: service.gui.CERT_INFO_O=Organisation: service.gui.CERT_INFO_C=Land: @@ -721,12 +685,10 @@ service.gui.CERT_INFO_SIGN_ALG=Signaturalgoritm: service.gui.CERT_INFO_PUB_KEY_INFO=Information om publik nyckel service.gui.CERT_INFO_ALG=Algoritm: service.gui.CERT_INFO_PUB_KEY=Publik nyckel: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} byte: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bitar service.gui.CERT_INFO_EXP=Exponent: service.gui.CERT_INFO_KEY_SIZE=Nyckelstorlek: service.gui.CERT_INFO_SIGN=Signatur: -service.gui.CONTINUE=Fortsätt service.gui.SHOW_CERT=Visa certifikat service.gui.HIDE_CERT=Dölj certifikat @@ -749,12 +711,9 @@ service.gui.security.SECURE_AUDIO=Säker ljudlänk service.gui.security.AUDIO_NOT_SECURED=Ljudlänk ej säker service.gui.security.SECURE_VIDEO=Säker videolänk service.gui.security.VIDEO_NOT_SECURED=Videolänk ej säker -service.gui.security.NO_VIDEO=Ingen video -service.gui.security.CIPHER=Kryptering: {0} service.gui.security.CALL_SECURED_TOOLTIP=Samtalsöverföring säker. Klicka här för mer information. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Samtalsöverföring ej säker. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Tryck här för att jämföra säkerhetssträng med din partner. -service.gui.security.COMPARE_WITH_PARTNER=Jämför med din partner och klicka på hänglåset för att bekräfta. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Jämför med partner: service.gui.security.STRING_COMPARED=Autentiseringssträngar jämförda! @@ -772,20 +731,14 @@ service.gui.avatar.imagepicker.CLICK=Klicka ock le service.gui.avatar.imagepicker.IMAGE_FILES=Bildfiler service.gui.avatar.imagepicker.IMAGE_PICKER=Bild service.gui.avatar.imagepicker.IMAGE_SIZE=Bildstorlek -service.gui.avatar.imagepicker.INITIALIZING=Påbörjar service.gui.avatar.imagepicker.RESET=Återställ service.gui.avatar.imagepicker.SET=Verkställ service.gui.avatar.imagepicker.TAKE_PHOTO=Ta ett foto -service.gui.avatar.imagepicker.WEBCAM_ERROR=Webbkamerafel service.gui.security.encryption.required=Kryptering krävs! service.protocol.ICE_FAILED=Kunde inte upprätta anslutningen (ICE misslyckades och ingen relay hittades) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Fel i lagringen av SIP-kontaktlista impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Resursen kan inte läsas {0}. För {1} @@ -815,9 +768,7 @@ impl.ldap.QUERY_CUSTOM=Anpassad fråga impl.ldap.QUERY_CUSTOM_HINT=Använd {0} som platshållare för sökbegreppet. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Lägg automatiskt till jokertecken till sökbegreppet impl.ldap.QUERY_PHOTO_INLINE=Hämta bild tillsammans med övriga attribut -impl.ldap.NEW=Nytt impl.ldap.EDIT=Redigera -impl.ldap.REMOVE=Ta bort impl.ldap.ENABLED=Aktiverad impl.ldap.SERVER_NAME=Servernamn impl.ldap.SERVER_NAME_EXAMPLE=Min LDAP-server @@ -850,6 +801,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=Hemtelefon impl.ldap.PHONE_PREFIX=Telefonprefix impl.ldap.PHONE_PREFIX_EXAMPLE=Exempel: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Adressbok plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Aktivera Mac OS X adressboksökning @@ -864,9 +819,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Gör Outlook till förvald e-po # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google-kontakter -impl.googlecontacts.NEW=Nytt impl.googlecontacts.EDIT=Redigera -impl.googlecontacts.REMOVE=Ta bort impl.googlecontacts.ENABLED=Aktiverad impl.googlecontacts.ACCOUNT_NAME=Kontonamn impl.googlecontacts.SAVE=Spara @@ -905,11 +858,8 @@ plugin.accountinfo.ORGANIZATION=Organisation: plugin.accountinfo.JOB_TITLE=Titel: plugin.accountinfo.ABOUT_ME=Om mig: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Användarbilder plugin.accountinfo.GLOBAL_ICON=Använd standardbild plugin.accountinfo.LOCAL_ICON=Använd denna bild: -plugin.accountinfo.CHANGE=Ändra -plugin.accountinfo.ONLY_MESSAGE=Endast meddelanden # connection info plugin.connectioninfo.TITLE=Anslutningsinformation @@ -929,49 +879,13 @@ plugin.aimaccregwizz.USERNAME=AIM skärmnamn: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Skärmnamn och lösenord plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registrera nytt konto plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Om du inte har något AIM-konto kan du klicka på denna knapp och skapa ett nytt. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Åsidosätt serverns standardalternativ # branding plugin.branding.ABOUT_WINDOW_TITLE=Om {0} plugin.branding.LOGO_MESSAGE=VoIP && IM som öppen källkod -plugin.branding.LOADING=Läser in plugin.branding.ABOUT_MENU_ENTRY=&Om -plugin.branding.WELCOME_MESSAGE=
    {1} är under aktiv utveckling. Versionen du kör är endast experimentell och KANSKE INTE fungerar som förväntat. Se {2} för mer information.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Alla rättigheter reserverade. Besök https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi distribueras under villkoren för LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Ordböcker -plugin.dictaccregwizz.ANY_DICTIONARY=Valfri ordbok -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Valfri ordbok från {0} -plugin.dictaccregwizz.FIRST_MATCH=Första träffen -plugin.dictaccregwizz.NO_MATCH=Inga träffar -plugin.dictaccregwizz.MATCH_RESULT=Inga definitioner hittades för "{0}", du kanske menade:\n -plugin.dictaccregwizz.INVALID_DATABASE=Ordboken "{0}" finns inte längre på den här servern. -plugin.dictaccregwizz.INVALID_STRATEGY=Aktuell strategi är inte tillgänglig på den här servern -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Dict-protokollet -plugin.dictaccregwizz.HOST=Värd -plugin.dictaccregwizz.SERVER_INFO=Serverinformation -plugin.dictaccregwizz.STRATEGY_SELECTION=Strategival -plugin.dictaccregwizz.STRATEGY_LIST=Strategilista: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Sökstrategier -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategi används för att söka efter liknande ord, om en översättning inte hittas tack vare olika synsätt. Som exempel, kommer prefixstrategierna att söka efter ord med samma inledning som det ord du vill översätta. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict-kontoinformation -plugin.dictaccregwizz.FIRST_ACCOUNT=Den här guiden kommer att skapa ditt första Dict-konto på dict.org.\n\nDu kan lägga till nya ordböcker via kontoregistreringsguiden. I värdfältet anger du vilka ordböcker du vill lägga till. -plugin.dictaccregwizz.THREAD_CONNECT=Försöker ansluta till servern -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Anslutningsförsöket misslyckades. Det här är ingen Dict-server eller servern är offline. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Hämtar strategier -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Ingen strategi hittades på servern -plugin.dictaccregwizz.POPULATE_LIST=Fyller listan -plugin.dictaccregwizz.CLOSING_CONNECTION=Stänger anslutningen - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    För att använda Facebook-chatten måste du skapa ett "Användarnamn"
    via dina "Kontoinställningar" på Facebook.


    OBS! När du skapar användarnamn måste du logga ut från webbsidan
    och det kan ta en stund innan du kan logga in med ditt nya användarnamn!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Facebook chattprotokoll -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Användarnamn: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Användarnamn och lösenord + +plugin.busylampfield.PICKUP=Återuppta samtal # generalconfig plugin.generalconfig.AUTO_START=Starta {0} automatiskt vid systemstart @@ -982,9 +896,6 @@ plugin.generalconfig.SHOW_HISTORY=Visa plugin.generalconfig.HISTORY_SIZE=tidigare meddelanden i nya chattar plugin.generalconfig.SEND_MESSAGES_WITH=Skicka meddelanden med: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Visa chattfönster överst -plugin.generalconfig.ERROR_PERMISSION=Du har inte tillräcklig behörighet för att ta bort autostart -plugin.generalconfig.TRANSPARENCY=Transparens -plugin.generalconfig.ENABLE_TRANSPARENCY=Aktivera transparens plugin.generalconfig.DEFAULT_LANGUAGE=Språk plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Ändringar verkställs vid nästa programstart. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% översatt @@ -1043,13 +954,13 @@ plugin.ircaccregwizz.EXAMPLE_SERVER=T.ex. chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Använd säker anslutning plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Aktivera kontaktnärvaro plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Möjliggör närvaro i chattrum +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autentisering +plugin.ircaccregwizz.SASL_USERNAME=Användarnamn # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPP-protokollet plugin.jabberaccregwizz.USERNAME=XMPP användarnamn plugin.jabberaccregwizz.PASSWORD_CONFIRM=Bekräfta lösenord -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID och lösenord plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Anslut server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Aktivera "Håll vid liv" @@ -1065,13 +976,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Kommentar plugin.jabberaccregwizz.RESOURCE=Resurs plugin.jabberaccregwizz.AUTORESOURCE=Autogenerera resurs plugin.jabberaccregwizz.PRIORITY=Prioritet -plugin.jabberaccregwizz.XMPP_ERROR=XMPP-fel plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Okänt XMPP-fel ({0}). Kontrollera att servernamnet är rätt. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Dina lösenord är inte lika. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Åsidosätt serverns standardalternativ -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Avancerat plugin.jabberaccregwizz.USE_ICE=Använd ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Använd Googles Jingle/ICE (Experimentell) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Hitta STUN-/TURN-servrar automatiskt plugin.jabberaccregwizz.SUPPORT_TURN=Stöd TURN plugin.jabberaccregwizz.TURN_USERNAME=TURN-användarnamn @@ -1099,11 +1006,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Inaktivera meddelandekopia plugin.jabberaccregwizz.DTMF_AUTO=Auto: Välj automatiskt mellan RTP och In-band plugin.jabberaccregwizz.SERVER_OPTIONS=Serveralternativ plugin.jabberaccregwizz.CHANGE_PASSWORD=Ändra kontolösenord -plugin.jabberaccregwizz.NEW_PASSWORD=Nytt lösenord -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Bekräfta nytt lösenord plugin.jabberaccregwizz.PORT_FIELD_INVALID=Ange ett giltigt portnummer för att fortsätta. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Kontot var inloggat före lösenordsändringen. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Lösenord saknas. plugin.jabberaccregwizz.TLS_REQUIRED=Anslutningen använder inte TLS. Lösenordsändring kommer inte att utföras. plugin.jabberaccregwizz.PASSWORD_CHANGED=Lösenordet har ändrats plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Din XMPP-server stöder inte lösenordsändring. @@ -1117,25 +1021,9 @@ plugin.jabberaccregwizz.RESET=Återställ plugin.jabberaccregwizz.RESET_DESCRIPTION=Återställ till globala inställningar plugin.jabberaccregwizz.DISABLE_JINGLE=Inaktivera Jingle (röst och videosamtal med XMPP). -# mailbox -plugin.mailbox.OUTGOING=Utgående meddelande: -plugin.mailbox.INCOMING=Inkommande meddelande: -plugin.mailbox.WAIT_TIME=Fördröjning innan samtal vidarekopplas till röstbrevlåda -plugin.mailbox.MAX_MESSAGE_TIME=Maxlängd på inkommande meddelande -plugin.mailbox.CONFIRM=Bekräfta -plugin.mailbox.DEFAULTS=Standard -plugin.mailbox.MAILBOX=Brevlåda - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protokoll för att ansluta och chatta på MSN. -plugin.msnaccregwizz.USERNAME=E-post: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID och lösenord - # plugin manager plugin.pluginmanager.INSTALL=Installera plugin.pluginmanager.UNINSTALL=Avinstallera -plugin.pluginmanager.UPDATE=Uppdatera plugin.pluginmanager.PLUGINS=Insticksprogram plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Välj fil @@ -1160,7 +1048,6 @@ plugin.sipaccregwizz.SERVER_PORT=Serverport plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxyport plugin.sipaccregwizz.PREFERRED_TRANSPORT=Föredragen transport -plugin.sipaccregwizz.ADVANCED_OPTIONS=Avancerat plugin.sipaccregwizz.PROXY_OPTIONS=Proxyalternativ plugin.sipaccregwizz.PROXY_AUTO=Automatiska proxyinställningar plugin.sipaccregwizz.ENABLE_PRESENCE=Aktivera närvaro (ENKEL) @@ -1180,8 +1067,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Välj automatiskt mellan RTP och In-band (i plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP-INFO plugin.sipaccregwizz.DTMF_INBAND=In-band -plugin.sipaccregwizz.REGISTER=REGISTRERA -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Åsidosätt serverns standardalternativ plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Aktivera stöd för samtalskryptering plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indikera stöd för ZRTP i signalprotokoll plugin.sipaccregwizz.AUTH_NAME=Auktoriseringsnamn @@ -1202,10 +1087,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Adress till röstbrevlåda plugin.sipaccregwizz.NOT_SAME_PASSWORD=Dina lösenord är olika. plugin.sipaccregwizz.NO_CERTIFICATE= (använd reguljär autentisering) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP-indikation +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Av (indikera endast RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Obligatorisk (erbjud och acceptera endast RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Tillval (erbjud RTP/SAVP först, sen RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Aktivera S-Descriptor (också känd som SDES eller SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Välj aktiverade krypteringsprotokoll och dess prioritet (översta protokollet först): plugin.sipaccregwizz.CIPHER_SUITES=Aktiverade krypteringssviter: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} försöker automatiskt säkra alla dina samtal med ZRTP och du kommer att både se och höra ett meddelande när en säker anslutning etablerats. Du bör inte ändra nedanstående avancerade inställningar om du inte vet exakt vad du gör.
    @@ -1219,15 +1104,6 @@ plugin.skinmanager.DEFAULT_SKIN=Standardtema plugin.skinmanager.ADD_NEW_SKIN=Lägg till nytt tema... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Standardtema för programmet. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Protokoll för att ansluta till fjärrdatorer över SSH. -plugin.sshaccregwizz.USERNAME=Konto-ID: -plugin.sshaccregwizz.IDENTITY_FILE=Identitetsfil: -plugin.sshaccregwizz.KNOWN_HOSTS=Kända värdar: -plugin.sshaccregwizz.OPTIONAL=Tillval -plugin.sshaccregwizz.ACCOUNT_DETAILS=Kontoinformation - # status update plugin.autoaway.AUTO_STATUS=Auto-status plugin.autoaway.ENABLE_CHANGE_STATUS=Ändra status vid "Ej närvarande" @@ -1275,22 +1151,6 @@ plugin.whiteboard.DESELECT=Avmarkera plugin.whiteboard.DELETE=Ta bort plugin.whiteboard.PROPERTIES=Egenskaper -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protokoll för att ansluta och chatta på Yahoo! -plugin.yahooaccregwizz.USERNAME=Användarnamn: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID och lösenord - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Protokoll för Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Förnamn: -plugin.zeroaccregwizz.LAST_NAME=Efternamn: -plugin.zeroaccregwizz.EMAIL=E-post: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Kom ihåg Bonjour-kontakter? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID och lösenord -plugin.zeroaccregwizz.USERID=Användar-ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Google Talk-protokollet @@ -1304,19 +1164,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, IP Telecommunications Por plugin.iptelaccregwizz.USERNAME=Användarnamn plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Abonnera på iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP och chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Användarnamn plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Upprepa lösenordet plugin.sip2sipaccregwizz.EMAIL=E-postadress -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=För hjälp med den tjänsten, besök
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=E-postadressen används för att skicka röstmeddelanden,
    meddelanden om missade samtal och för att återställa förlorade lösenord -plugin.sip2sipaccregwizz.INFO_NOTE=För hjälp med den här tjänsten, besök http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Befintligt sip2sip-konto -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Skapa ett gratis sip2sip-konto - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Snabbmeddelande plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=För hjälp med den tjänsten, besök
    http://ippi.fr @@ -1325,6 +1177,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Befintligt ippi-konto plugin.ippiaccregwizz.CREATE_ACCOUNT=Skapa ett gratis ippi-konto # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Stäng chattfönstret plugin.keybindings.CHAT_COPY=Kopiera plugin.keybindings.CHAT_CUT=Klipp ut @@ -1347,10 +1200,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Namn plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primär genväg plugin.keybindings.globalchooser.SHORTCUT_SECOND=Sekundär genväg plugin.keybindings.globalchooser.PRESS_BTN=Tryck för att ange genväg -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Väntar plugin.keybindings.globalchooser.PUSH_TO_TALK=Tryck för att prata plugin.keybindings.globalchooser.ENABLE_SPECIAL=Aktivera snabbtangentupptäckt plugin.keybindings.PLUGIN_NAME=Snabbtangenter +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chatt plugin.keybindings.MAIN=Grundläggande plugin.keybindings.GLOBAL=Globala genvägar @@ -1378,6 +1231,7 @@ plugin.notificationconfig.tableheader.SOUND=Spela upp ett ljud genom meddelandee plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Spela upp ett ljud genom uppspelningsenheten plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Spela upp ett ljud genom datorhögtalarna plugin.notificationconfig.tableheader.DESCRIPTION=Händelsebeskrivning +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Inkommande samtal plugin.notificationconfig.event.SecurityMessage=Säkerhetsmeddelande plugin.notificationconfig.event.IncomingFile=Inkommande fil @@ -1479,6 +1333,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Periodic Intra Refresh impl.neomedia.configform.H264.defaultProfile=Standardprofil för kodning: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Bas impl.neomedia.configform.H264.defaultProfile.high=Hög impl.neomedia.configform.H264.defaultProfile.main=Medel @@ -1509,7 +1364,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Aktuellt lösenord: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Ange nytt lösenord: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Upprepa lösenordet: plugin.securityconfig.masterpassword.MP_TITLE=Masterlösenord -plugin.securityconfig.masterpassword.MP_NOT_SET=(ej angivet) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Du angav inte rätt Masterlösenord. Försök igen. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Masterlösenordet är felaktigt! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Lösenordsändringen misslyckades @@ -1525,7 +1379,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Lösenord plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(okänd) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(kan inte dekryptera) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Lagrade lösenord -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Ta bort plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Ta bort alla plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Vill du verkligen ta bort alla lösenord? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Ta bort alla lösenord @@ -1621,7 +1474,6 @@ plugin.globalproxy.PROXY_PORT=Port plugin.globalproxy.PROXY_USERNAME=Användarnamn plugin.globalproxy.PROXY_PASSWORD=Lösenord plugin.globalproxy.DESCRIPTION={0} kommer att använda ovanstående proxyinställningar för alla nätverk du ansluter till, från och med nu.\nProxy-stödet är fortfarande experimentellt och fungerar bara med vissa protokoll. Se nedanstående tabell för ytterligare info: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Också proxy-DNS plugin.globalproxy.FWD_DNS_NOTE=Användbart med Tor. Hjälper dig att undvika DNS-läckage genom att vidarebefordra all DNS-trafik till Tor-proxyn. Kräver omstart. @@ -1659,7 +1511,6 @@ plugin.provisioning.RESTART_WARNING=Notera att dina ändringar verkställs förs plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Kopiera UUID till Urklipp plugin.provisioning.CLIPBOARD_FAILED=Kunde inte kopiera UUID till Urklipp -plugin.provisioning.EXIT_ON_FAIL=Avsluta programmet om nättjänsten misslyckas plugin.provisioning.CREDENTIALS=Senast lagrade nättjänstreferenser plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Vill du verkligen ta bort nättjänstlösenordet? plugin.provisioning.PROV_FAILED=Nättjänsten misslyckades @@ -1726,8 +1577,6 @@ util.dns.DNSSEC_WARNING=
    {0} har försökt ansluta till se #plugin spellcheck plugin.spellcheck.TITLE=Stavning och gramatik plugin.spellcheck.MENU=Visa stavning och gramatik -plugin.spellcheck.LANG=Språk -plugin.spellcheck.EDIT_PERSONAL_DICT=Redigera plugin.spellcheck.ENABLE_SPELL_CHECK=Aktivera stavningskontroll plugin.spellcheck.dialog.FIND=Sök nästa plugin.spellcheck.dialog.REPLACE=Ersätt -- cgit v1.1 From 987a643feb83f68c0603359e69be9b7c697505ab Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:22 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 474 of 1505 strings translated (38 fuzzy). --- resources/languages/resources_sl.properties | 486 ++++++++++++++++++++++++++-- 1 file changed, 461 insertions(+), 25 deletions(-) diff --git a/resources/languages/resources_sl.properties b/resources/languages/resources_sl.properties index b19335e..5f9f079 100644 --- a/resources/languages/resources_sl.properties +++ b/resources/languages/resources_sl.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -31,17 +42,254 @@ service.gui.ACCOUNT=Račun service.gui.ACCOUNT_ME=Jaz service.gui.ACCOUNT_REGISTRATION_WIZARD=Čarovnik za ustvarjanje računov service.gui.ACCOUNTS=Računi -service.gui.ADD_ACCOUNT=Dodaj račun +service.gui.ADD=&Dodaj +service.gui.ADD_CONTACT=&Dodaj stik service.gui.ADD_AUTHORIZED_CONTACT=Dodaj osebo {0} na seznam stikov +service.gui.ADD_CONTACT_TO_CONTACTLIST=Dodaj stik na seznam stikov service.gui.ADD_CONTACT_TO=&Dodaj stik v +service.gui.ADD_CONTACT_ERROR=Stika {0} ni bilo mogoče dodati. service.gui.ADD_CONTACT_ERROR_TITLE=Napaka stika +service.gui.ADD_CONTACT_EXIST_ERROR=Stik {0} na seznamu stikov že obstaja. +service.gui.ADD_CONTACT_NETWORK_ERROR=Strežnik se ne odziva na zahtevo dodajanja stika {0}. +service.gui.ADD_CONTACT_NOT_SUPPORTED=Dodajanje stika {0} je spodletelo. Dejanje ni podprto. +service.gui.ADD_CONTACT_NOT_CONNECTED=Za dodajanje stikov morate biti povezani. Prosimo, vpišite se z izbranim ponudnikom in poskusite znova. +service.gui.ADD_GROUP_LOCAL_ERROR=Ni bilo mogoče dodati skupine: {0}. Problem se je pojavil med lokalno V/I operacijo. +service.gui.ADD_GROUP_EXIST_ERROR=Skupina {0} na seznamu stikov že obstaja. Prosimo, izberite drugo ime. +service.gui.ADD_GROUP_NET_ERROR=Ni bilo mogoče dodati skupine: {0}. Problem se je pojavil zaradi omrežne napake. Prosimo, preverite svojo omrežno povezavo in poskusite znova. +service.gui.ADD_GROUP_ERROR=Ni bilo mogoče dodati skupine: {0}. +service.gui.ADD_GROUP_EMPTY_NAME=Ime skupine ne more biti prazno. +service.gui.ADDRESS=Naslov service.gui.ADMINISTRATOR=Skrbnik service.gui.ADVANCED=N&apredno +service.gui.ALL_CONTACTS=&Vsi stiki +service.gui.ALTERNATE_ADDRESS=Pomožni naslov +service.gui.APPLY=&Uporabi service.gui.ARE_CALLING={0} kliče... - - - - +service.gui.ARE_NOW=Sedaj ste {0} +service.gui.AT=pri +service.gui.AUTHORIZE=&Pooblasti +service.gui.AUTHORIZATION_ACCEPTED={0} je sprejel vašo prošnjo za pooblastitev. +service.gui.AUTHENTICATION_FAILED=Overitev za {0} ni uspela. Geslo, ki ste ga vpisali, ni veljavno. +service.gui.AUTHENTICATION_REQUESTED_SERVER=Strežnik {0} je zahteval vašo overitev. +service.gui.AUTHENTICATION_REJECTED={0} je zavrnil vašo prošnjo za overitev. +service.gui.AUTHENTICATION_WINDOW_TITLE={0} overitev +service.gui.AUTHORIZATION_REQUESTED=Zahtevana overitev +service.gui.AUTHORIZATION_REQUESTED_INFO=Stik {0} zahteva vašo overitev. +service.gui.AUTHORIZATION_RESPONSE=Odgovor overitve +service.gui.AWAY_STATUS=Odsoten +service.gui.EXTENDED_AWAY_STATUS=Odsoten - daljše +service.gui.BAN=Izobčenje ni uspelo +service.gui.BANNED=izobčen +service.gui.BAN_FAILED=Izobčenje ni uspelo +service.gui.BAN_FAILED_GENERAL_ERROR=Izobčenje ni uspelo {0}. Prišlo je do splošne napake. +service.gui.BAN_FAILED_NOT_ALLOWED=Izobčenje ni uspelo {0}. Ni mogoče izobčiti lastnika ali moderatorja klepetalnice. +service.gui.BAN_FAILED_NOT_ENOUGH_PERMISSIONS=Izobčenje ni uspelo {0}. Nimate te pravice. +service.gui.BRB_MESSAGE=Trenutno me ni, a se bom vrnil kasneje. +service.gui.BROWSE=Brskaj +service.gui.BUSY_MESSAGE=Oprostite, trenutno sem zaposlen. +service.gui.BUSY_STATUS=Zaposlen +service.gui.CALL=Pokliči +service.gui.CALL_CONTACT=Pokliči stik +service.gui.CALL_FAILED=Klic ni uspel +service.gui.CALL_HISTORY_TOOL_TIP=Klikni tukaj za prikaz zgodovine klicev +service.gui.CALL_HISTORY_GROUP_NAME=Zgodovina klicev +service.gui.CALL_VIA=Pokliči skozi +service.gui.CALL_NAME_OR_NUMBER=Pokliči stik ali številko +service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=Ta klic podpira samo udeležence omrežja {0} in vašega računa {1}. {2} ne vsebuje naslova za to omrežje ali račun. +service.gui.CALL_WITH=Pokliči z/s +service.gui.CALL_NO_AUDIO_DEVICE=Nastavili niste nobene zvočne naprave. +service.gui.CALL_NO_AUDIO_CODEC=Noben zvočni kodek ni omogočen. +service.gui.CALL_NO_DEVICE_CODECS_Q=Želite nadaljevati s klicem? +service.gui.CANCEL=&Prekliči +service.gui.CHAT=Klepet +service.gui.CHANGE_FONT=Spremeni pisavo +service.gui.CHANGE_ROOM_SUBJECT=Spremeni zadevo klepetalnice ... +service.gui.CHANGE_ROOM_SUBJECT_LABEL=V spodnje polje lahko vpišete novo zadevo klepetalnice +service.gui.CHANGE_NICK=Spremeni vzdevek +service.gui.CHANGE_NICKNAME=Spremeni vzdevek... +service.gui.CHANGE_NICKNAME_LABEL=Spodaj lahko vnesete nov vzdevek. +service.gui.CHANGE_NICKNAME_ERROR=Napaka pri spreminjanju vzdevka +service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Vzdevek že obstaja +service.gui.CHANGE_VIDEO_QUALITY=Spremeni kvaliteto oddaljenega videa +service.gui.CHAT_CONFERENCE_ITEM_LABEL=konferenca od {0} +service.gui.CHAT_ROOM_ALREADY_JOINED=Klepetalnica {0} je že pridružena. +service.gui.CHAT_ROOM_CONFIGURATION=nastavitve za klepetalnico {0} +service.gui.CHAT_ROOM_CONFIGURATION_FAILED=Ni bilo mogoče pridobiti obrazca za nastavitve klepetalnice {0}. +service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=Ni bilo mogoče pridobiti obrazca za nastavitve klepetalnice {0}. Samo lastniki klepetalnic lahko vidijo in spreminjajo nastavitveni obrazec. +service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=Prišlo je do napake pri pošiljanju nastavitvenega obrazca za klepetalnico {0}. +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=Uredi spisek članov +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_DESCRIPTION=Člani so uporabniki izpisani v spisku na desni. Ko je klepetalnica "Samo za člane" se samo ti uporabniki lahko pridružijo. +service.gui.CHAT_ROOM_USER_JOINED=se je pridružil {0} +service.gui.CHAT_ROOM_USER_LEFT=je odšel {0} +service.gui.CHAT_ROOM_USER_KICKED=ga je izobčil {0} +service.gui.CHAT_ROOM_USER_QUIT=je končal {0} +service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Pošiljanje sporočila je prepovedano (preklican glas) +service.gui.CHAT_ROOM_NAME=Ime klepetalnice +service.gui.CLEAR_CUSTOM_MESSAGES=Počisti sporočila po meti +service.gui.ROOM_NAME=Klepetelnica +service.gui.CHANGE_PASSWORD=Spremeni geslo +service.gui.CHAT_ROOM_NAME_INFO=V spodnje polje vpišite ime klepetalnice, ki jo želite ustvariti. +service.gui.CHAT_ROOM_NOT_EXIST=Klepetalnice {0} ni najti na strežniku {1}. Preverite, prosim, da ste ime napisali pravilno. +service.gui.CHAT_ROOM_NOT_CONNECTED=Če se želite pridružiti klepetalnici {0} morate biti prijavljeni. +service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Da zapustite klepetalnico morate biti prijavljeni. +service.gui.CHAT_ROOM_OPTIONS=Možnosti kelpetalnice +service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Klepetalnica {0} zahteva registracijo za pridružitev. +service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Klepetalnica {0} zahteva geslo. +service.gui.CHAT_ROOMS=Klepetalnice +service.gui.CHAT_ROOM=Klepetelnica +service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} je spremenil zadevo v {1} +service.gui.CHAT_ROOM_ALTERNATE_ADDRESS=Pogovor lahko nadaljujete v klepetalnici: {0} +service.gui.CHAT_NICKNAME_CHANGE={0} je zdaj znan kot {1} +service.gui.CHOOSE_CONTACT=Izberite stik +service.gui.CHOOSE_NUMBER=Izberite številko +service.gui.CHOOSE_ACCOUNT=Izberite prosim enega izmed računov na seznamu +service.gui.CITY=Mesto +service.gui.COUNTRY=Država +service.gui.SHOW_MORE_TOOLTIP=Kliknite za več rezultatov +service.gui.CLEAR=Počisti +service.gui.CLOSE=&Zapri +service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Pred manj kot 2 sekundama ste prejeli novo sporočilo. Ali res želite zapreti ta pogovor? +service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Nekateri prenosi datotek so še aktivni. Ali jih res želite prekiniti? +service.gui.CONNECTED_STATUS=Povezan +service.gui.CONNECTING=Povezovanje ... +service.gui.CONNECTING_STATUS=Povezovanje +service.gui.CONNECTING_EARLY_MEDIA_STATUS=Povezovanje* +service.gui.CONNECTION=Povezava +service.gui.CONTACT_NAME=ID ali Številka +service.gui.CONTACTS=Stiki +service.gui.COPY=&Kopiraj +service.gui.COPY_LINK=Kopiraj &povezavo +service.gui.CREATE=&Ustvari +servoce.gui.CREATE_CALL_FAILED=Klic ni uspel. +service.gui.CREATE_CHAT_ROOM=Ustvari &klepetalnico ... +service.gui.CREATE_CHAT_ROOM_ERROR=Ustvarjanje klepetalnice {0} ni uspelo. +service.gui.CREATE_CHAT_ROOM_WIZARD=Čarovnik za ustvarjanje klepetalnice +service.gui.CREATE_CONFERENCE_CALL=&Ustvari konferenčni klic ... +service.gui.CREATE_GROUP=&Ustvari skupino ... +service.gui.CREATE_VIDEO_BRIDGE=Ustvari most &video ... +service.gui.CREATE_VIDEO_BRIDGE_MENU=Ustvari most &video +service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Ustvari / Pridruži se videokonferenci +service.gui.CREATE_VIDEO_CONFERENCE=Ustvari novo videokonferenco za to klepetalnico +service.gui.CUT=&Izreži +service.gui.DELETE=Izbriši +service.gui.DENY=&Zavrni +service.gui.DESKTOP_SHARING_WARNING=Ali res želite dati svoje namizje v skupno uporabo?
    Če kliknete na DA bodo sogovorniki videli vaš zaslon. +service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Zaslon ste dali v skupno rabo +service.gui.DIALPAD=Številčnica +service.gui.DISPLAY_NAME=Ime za prikaz +service.gui.DISCONNECTED_STATUS=Ni povezave +service.gui.DND_STATUS=Ne moti +service.gui.DO_NOT_ASK_AGAIN=Ne sprašuj spet +service.gui.DO_NOT_SHOW_AGAIN=Tega sporočila ne prikaži več +service.gui.DRAG_FOR_SHARING=Sem povlecite kar želite dati v skupno rabo ... +service.gui.DURATION=trajanje +service.gui.DESTROY_CHATROOM=Zbriši klepetalnico +service.gui.END_CONFERENCE=Zaključi konferenco +service.gui.ENTER_PHONE_NUMBER=Vpišite telefonsko številko +service.gui.ENTER_NAME_OR_NUMBER=Vpišite ime ali številko +service.gui.ERROR=Napaka +service.gui.ERROR_RECEIVED_FROM=Napaka od {0} +service.gui.ESTIMATED_TIME=Predvideni čas: +service.gui.EVENTS=Dogodki +service.gui.EXIT=&Izhod +service.gui.GENERAL=Splošno +service.gui.GENERAL_ERROR=Splošna napaka +service.gui.GROUP_NAME=Ime skupine +service.gui.FAILED_STATUS=Klic ni uspel +service.gui.FAILED_TO_JOIN_CHAT_ROOM=Ni se mogoče pridružiti klepetalnici: {0}. +service.gui.FAX=Faks +service.gui.FFC_STATUS=Na razpolago za klepet +service.gui.FILE=&Datoteka +service.gui.FILE_TOO_BIG=Velikost datoteke je večja od največje dovoljene velikosti za protokol: {0}. +service.gui.FILE_SEND_REFUSED={0} je zavrnil to datoteko. +service.gui.FILE_TRANSFER_REFUSED=Zavrnjen prenos datoteke. +service.gui.FILE_TRANSFER_NOT_SUPPORTED=Izbrani stik ne podpira prenosa datoteke. +service.gui.FILE_TRANSFER_PREPARING=Priprava prenosa datoteke za uporabnika {0}. Prosim počakajte ... +service.gui.FILE_TRANSFER_REQUEST_RECIEVED={0} deli datoteko z vami. +service.gui.FILE_DOES_NOT_EXIST=Izbrane datoteke ni mogoče najti. Lahko je bila premaknjena ali izbrisana. +service.gui.FILE_OPEN_FAILED=Datoteke ni mogoče odpreti. Lahko je bila premaknjena ali izbrisana. +service.gui.FONT=Pisava +service.gui.FONT_BOLD=Krepko +service.gui.FONT_COLOR=Barva +service.gui.FONT_ITALIC=Ležeče +service.gui.FONT_SIZE=Velikost +service.gui.FONT_STYLE=Slog +service.gui.FONT_UNDERLINE=Podčrtano +service.gui.HANG_UP=Odloži +service.gui.HD_QUALITY=HD video +service.gui.HELP=&Pomoč +service.gui.HIDE=Skrij +service.gui.ICE=ICE +service.gui.IDENTIFIER=Določilnik +service.gui.IS_CALLING={0} kliče ... +service.gui.LAST_NAME=Priimek +service.gui.LIST=Spisek +service.gui.MEMBER=član +service.gui.MESSAGE=Sporočilo +service.gui.MORE_LABEL=Več +service.gui.MOVE=Premakni +service.gui.MOVE_SUBCONTACT=&Premakni stik +service.gui.MOVE_CONTACT=Premakni stik +service.gui.NAME=Ime +service.gui.NEW_MESSAGE=Novo sporočilo +service.gui.NEW_NAME=Novo ime +service.gui.NEW_STATUS_MESSAGE=Nov status +service.gui.NEW_STATUS_MESSAGE_SAVE=Shrani kot prilagojeno sporočilo +service.gui.NICKNAME=Vzdevek +service.gui.NO_CAMERA_AVAILABLE=Nobene kamere na razpolago +service.gui.NO_DESKTOP_SHARING_FOR_PROTOCOL=V tem protokolu ni podpore za souporabo namizja +service.gui.NO_VIDEO_FOR_PROTOCOL=V tem protokolu ni podpore za video +service.gui.OR=ali +service.gui.chat.role.OWNER=Lastnik +service.gui.chat.role.ADMINISTRATOR=Skrbnik +service.gui.chat.role.MODERATOR=Moderator +service.gui.chat.role.MEMBER=Član +service.gui.chat.role.GUEST=Gost +service.gui.chat.role.SILENT_MEMBER=Tihi član +service.gui.chat.role.OUTCAST=Izobčen +service.gui.OWNER=lastnik klepetalnice +service.gui.PASSWORD=Geslo +service.gui.PASSWORD_CHANGE_FAILURE=Napak pri spremembi gesla +service.gui.PASSWORD_CHANGE_SUCCESS=Geslo uspešno spremenjeno +service.gui.PERSONAL=Osebno +service.gui.PORT=Vrata +service.gui.POSTAL_CODE=Poštna številka +service.gui.PREFERENCES=Možnosti +service.gui.PREFIX=Predpona +service.gui.PRESENCE=Prisotnost +service.gui.PREVIOUS=Prejšnji +service.gui.PROACTIVE_NOTIFICATION=piše sporočilo +service.gui.PROTOCOL=Protokol +service.gui.REASON=Razlog +service.gui.REMEMBER_PASSWORD=Zapomni si geslo +service.gui.RETRY=Ponovno poskusi +service.gui.SAVE=&Shrani +service.gui.SEARCH=&Išči +service.gui.SELECT_COLOR=Izberi barvo +service.gui.SELECT_GROUP=Izberi skupino +service.gui.SELECT_NO_GROUP=Brez skupine +service.gui.SEND_PRIVATE_MESSAGE=Pošlji zasebno sporočilo +service.gui.SEND_SMS=P&ošlji SMS +service.gui.SMS=SMS +service.gui.SMS_SUCCESSFULLY_SENT=Sporočilo SMS je bilo uspešno poslano! +service.gui.SOUND_OFF=Izklopi zvok +service.gui.SOUND_ON=Vklopi zvok +service.gui.STATUS=Stanje +service.gui.STATUS_CHANGED_CHAT_MESSAGE=je postal {0} +service.gui.STREET=Ulica +service.gui.SUBJECT=Zadeva +service.gui.SUMMARY=Povzetek +service.gui.TELEPHONY=Telefonija +service.gui.TOOLS=&Orodje + + + + +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names # keep the following string short @@ -50,9 +298,6 @@ service.gui.ARE_CALLING={0} kliče... -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -61,6 +306,10 @@ service.gui.ARE_CALLING={0} kliče... # LDAP +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -74,10 +323,8 @@ service.gui.ARE_CALLING={0} kliče... # aimaccregwizz # branding +plugin.branding.ABOUT_MENU_ENTRY=O programu -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -89,20 +336,15 @@ service.gui.ARE_CALLING={0} kliče... # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -111,21 +353,18 @@ service.gui.ARE_CALLING={0} kliče... # whiteboard -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +#Enum KeybindingSet.Category # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -137,36 +376,233 @@ service.gui.ARE_CALLING={0} kliče... +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. # Security configuration form title +plugin.securityconfig.masterpassword.COL_PASSWORD=Geslo +plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(neznano) +plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(ni mogoče odšifrirati) +plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Shrani gesla +plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Odstrani vse +plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Ali res želite odstraniti vsa gesla? +plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Odstrani vsa gesla +plugin.securityconfig.masterpassword.SHOW_PASSWORDS_BUTTON=Pokaži gesla +plugin.securityconfig.masterpassword.HIDE_PASSWORDS_BUTTON=Skrij gesla +plugin.securityconfig.masterpassword.PASSWORD_QUALITY_METER=Merilec kakovosti gesla +plugin.securityconfig.masterpassword.MP_INPUT=Vpišite svoje glavno geslo:\n\n # otr plugin +plugin.otr.menu.TITLE=Varni klepet +plugin.otr.menu.START_OTR=Začni zasebni pogovor +plugin.otr.menu.END_OTR=Prekini zasebni pogovor +plugin.otr.menu.FINISHED=Vaš sogovornik je prekinil zasebni pogovor. Vi bi morali storiti isto +plugin.otr.menu.VERIFIED=Vaš zasebni pogovor je preverjen +plugin.otr.menu.UNVERIFIED=Vaš zasebni pogovor ni preverjen. Prosim overite svojega sogovornika +plugin.otr.menu.LOADING_OTR=Začenjam zasebni pogovor ... +plugin.otr.menu.TIMED_OUT=Čas za začetek zasebnega pogovora je pretekel. +plugin.otr.menu.REFRESH_OTR=Osveži zasebni pogovor +plugin.otr.menu.AUTHENTICATE_BUDDY=Overi sogovornika +plugin.otr.menu.WHATS_THIS=Kaj je to +plugin.otr.menu.CB_AUTO=Samodejno začni zasebni pogovor z {0} +plugin.otr.menu.CB_AUTO_ALL=Samodejno začni zasebni pogovor z vsemi +plugin.otr.menu.CB_ENABLE=Omogoči zasebna sporočila +plugin.otr.menu.CB_REQUIRE=Zahtevaj zasebna sporočila +plugin.otr.menu.CB_RESET=Ponasatvi +plugin.otr.menu.OTR_TOOLTIP=Šifriraj pogovore z OTR +plugin.otr.authbuddydialog.HELP_URI=https://jitsi.org/GSOC2009/OTR +plugin.otr.authbuddydialog.AUTHENTICATION_INFO=Overjanje sogovornika pomaga pri zagotavljanju, da je oseba res ta kdor trdi, da je. +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD=Kako se želite overiti? +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_QUESTION=Overjanje z vprašanjem +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_SECRET=Overjanje s skupnim geslom +plugin.otr.authbuddydialog.AUTHENTICATION_METHOD_FINGERPRINT=Overjanje s prstnim odtisom +plugin.otr.authbuddydialog.AUTHENTICATION_FINGERPRINT=Za preverjanje prstnega odtisa navežite stik s sogovornikom preko drugega overjenega kanal, kot je telefon ali e-pošta s podpisom GPG. Vsak mora sporočiti svoj prstni odtis drugemu. V primeru, da se vse sklada, označite , da *ste* preverili prstni odtis v naslednjem pogovornem oknu. +plugin.otr.authbuddydialog.LOCAL_FINGERPRINT=Prstni odtis za vas {0}: {1} +plugin.otr.authbuddydialog.REMOTE_FINGERPRINT=Domnevni prstni odtis za {0}: {1} +plugin.otr.authbuddydialog.AUTH_BY_QUESTION_INFO_INIT=Za overjanje z vprašanjem morate izbrati vprašanje katerega odgovor je znan samo vam in sogovorniku. Sogovorniku bo postavljeno vprašanje in če se odgovora ne skladata je možno, da se pogovarjate z goljufom. +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_INIT=Za overjanje s skupnim geslom morate izbrati nekaj, kar je znano samo vam in sogovorniku. Sogovornik bo moral tudi izbrati geslo, ki je znano vam in če se skrivnosti ne skladata je možno, da se pogovarjate z goljufom. +plugin.otr.authbuddydialog.AUTH_BY_SECRET_INFO_RESPOND=Vaš sogovornik želi preveriti, ali se res pogovarja z vami ali z goljufom. Sogovornik vam je postavil vprašanje. V primeru, da se želite overiti vpišite odgovor v spodnje polje. +plugin.otr.authbuddydialog.SHARED_SECRET=Vpišite svoje skupno geslo: +plugin.otr.authbuddydialog.QUESTION_RESPOND=Vaš sogovornik vas sprašuje: +plugin.otr.authbuddydialog.QUESTION_INIT=Vpišite svoje vprašanje: +plugin.otr.authbuddydialog.ANSWER=Vpišite svoj odgovor (razlikovanje velikosti črk): +plugin.otr.authbuddydialog.AUTHENTICATION_FROM=Overjeno z {0}. +plugin.otr.authbuddydialog.CANCEL=Prekliči +plugin.otr.authbuddydialog.HELP=Pomoč +plugin.otr.authbuddydialog.TITLE=Overi sogovornika +plugin.otr.authbuddydialog.AUTHENTICATE_BUDDY=Overi sogovornika +plugin.otr.authbuddydialog.I_HAVE=Sem +plugin.otr.authbuddydialog.I_HAVE_NOT=Nisem +plugin.otr.authbuddydialog.VERIFY_ACTION=preveril, da je to res pravi prstni odtis za {0}. +plugin.otr.authbuddydialog.FINGERPRINT_CHECK=Vpišite prstni odtis, ki ste ga dobili od {0}. +plugin.otr.smpprogressdialog.TITLE=Napredovanje overitve +plugin.otr.smpprogressdialog.AUTHENTICATION_SUCCESS=Overitev je uspela! +plugin.otr.smpprogressdialog.AUTHENTICATION_FAIL=Overitev ni uspela! +plugin.otr.configform.MY_PRIVATE_KEYS=Moji zasebni ključi +plugin.otr.configform.KNOWN_FINGERPRINTS=Znani prstni odtisi +plugin.otr.configform.CB_AUTO=Samodejno začni zasebno sporočanje +plugin.otr.configform.CB_ENABLE=Omogoči zasebno sporočanje +plugin.otr.configform.CB_REQUIRE=Zahtevaj zasebno sporočanje +plugin.otr.configform.NO_KEY_PRESENT=Nobenega ključa ni +plugin.otr.configform.GENERATE=Ustvari +plugin.otr.configform.REGENERATE=Ponovo ustvari +plugin.otr.configform.FINGERPRINT=Prstni odtis +plugin.otr.configform.VERIFY_FINGERPRINT=Preveri prstni odtis +plugin.otr.configform.FORGET_FINGERPRINT=Pozabi prstni odtis +plugin.otr.configform.COLUMN_NAME_CONTACT=Naveži stik +plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=Preverjenoi +plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=Da +plugin.otr.configform.COLUMN_VALUE_VERIFIED_FALSE=Ne +plugin.otr.activator.unverifiedsessionwarning={0} navezuje stik z vami iz neznanega računalnika. Primerno bi bilo, da overite {0}. +plugin.otr.activator.unverifiedsessionstared=Začel se je nepreverjen zasebni pogovor z uporabnikom {0}. +plugin.otr.activator.sessionstared=Začel se je zasebni pogovor z uporabnikom {0}. +plugin.otr.activator.sessionfinished={0} je prekinil zasebni pogovor z vami; vi bi morali storiti isto. +plugin.otr.activator.sessionlost=Zasebni pogovor z {0} se je prekinil. +plugin.otr.activator.historyon={0} snema vajin pogovor na vaši napravi. Tukaj lahko izključite zgodovino klepeta. +plugin.otr.activator.historyoff={0} NE snema vajinega pogovora. Tukaj lahko vključite zgodovino klepeta. +plugin.otr.activator.sessionfinishederror=Vaše sporočilo [{0}] ni bilo poslano. Prosim prekinite vaš zasebni pogovor z {1}. +plugin.otr.activator.smpaborted={0} je preklical postopek overitve. +plugin.otr.activator.smperror=Pri postopku overtive je prišlo do napake. +plugin.otr.activator.unencryptedmsgreceived=To sporočilo je bilo sprejeto nešifrirano, +plugin.otr.activator.unreadablemsgreceived={0} vam je poslal šifrirano sporočilo, ki ga ni bilo mogoče prebrati. +plugin.otr.activator.requireencryption=Vaše sporočilo [{0}] ni bilo poslano. Zahtevano je zasebno sporočanje. +plugin.otr.activator.unreadablemsgreply=Poslali ste {0} neberljivo šifrirano sporočilo. Prosim prekinite zasebni pogovor z uporabnikom {1}, da osvežite pogovor. +plugin.otr.activator.fallbackmessage={0} skuša začeti šifriran pogovor Off-The-Record z vami. A vaša programska oprema ne podpira sporočanja Off-The-Record. Za več informacij preberite http://en.wikipedia.org/wiki/Off-the-Record_Messaging +plugin.otr.activator.multipleinstancesdetected=Vaš sogovornik {0} je prijavljen večkrat in OTR je vzpostavil več sej. Iz spodnjega menija lahko izberete izhodno sejo. +plugin.otr.activator.msgfromanotherinstance={0} vam je poslal sporočilo mišljeno za drugo sejo. V primeru, da ste prijavljeni večkrat, bi lahko to sporčilo prišlo v drugo sejo. # global proxy plugin +plugin.globalproxy.GLOBAL_PROXY_CONFIG=Splošni posredniški strežnik +plugin.globalproxy.PROXY_TYPE=Vrsta posredniškega strežnika +plugin.globalproxy.PROXY_ADDRESS=Posredniški strežnik +plugin.globalproxy.PROXY_PORT=Vrata posredniškega strežnika +plugin.globalproxy.PROXY_USERNAME=Uporabniško ime posredniškega strežnika +plugin.globalproxy.PROXY_PASSWORD=Geslo posredniškega strežnika #plugin.globalproxy.PROTOCOL_SUPPORT +plugin.globalproxy.FWD_DNS=Uporabi posrednika za DNS +plugin.globalproxy.FWD_DNS_ADDR=Naslov posrednika za DNS +plugin.globalproxy.FWD_DNS_PORT=Vrata posredniška za DNS # plugin reconnect +plugin.reconnectplugin.NETWORK_DOWN=Prekinjena omrežna povezava! #plugin chat config +plugin.chatconfig.TITLE=Klepet +plugin.chatconfig.replacement.TITLE=Slika/Video: +plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Omogoči zamejavo smeškov +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Zamenjava slike/videa +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Omogoči +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_PROPOSAL=Onemogoči (pokaži povezavo za predogled) +plugin.chatconfig.replacement.DISABLE_REPLACEMENT=Onemogoči +plugin.chatconfig.replacement.CONFIGURE_REPLACEMENT=Spremeni nastavitve za zamenjavo slike/videa +plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Viri: +plugin.chatconfig.spellcheck.TITLE=Črkovanje #provisioning plugin +plugin.provisioning.PROVISIONING=Oskrbovanje +plugin.provisioning.ENABLE_DISABLE=Omogoči oskrbovanje +plugin.provisioning.AUTO=Samodejno odkrij URI za oskrbovanje +plugin.provisioning.DHCP=DHCP +plugin.provisioning.DNS=DNS +plugin.provisioning.BONJOUR=Bonjour +plugin.provisioning.MANUAL=Ročno vnesi URI za oskrbovanje +plugin.provisioning.URI=URI +plugin.provisioning.RESTART_WARNING=Upoštevajte, da bodo vaše spremembe začele veljati šele pri naslednjem zagonu {0}! +plugin.provisioning.UUID=UUID +plugin.provisioning.COPYTOCLIPBOARD=Kopiraj UUID v odložišče +plugin.provisioning.CLIPBOARD_FAILED=Ni bilo mogoče kopirati UUID v odložišče +plugin.provisioning.CREDENTIALS=Zadnji shranjeni podatki oskrbovanja +plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Ali res želite odstraniti geslo za oskrbovanje? +plugin.provisioning.PROV_FAILED=Oskrbovanje ni uspelo +plugin.provisioning.PROV_FAILED_MSG=Oskrbovanje ni uspelo. {0}!
    Prosim poskusite kasneje ali pokličite svojega administratorja +plugin.provisioning.FORGET_PASSWORD=Pozabi geslo # packet logging service +plugin.loggingutils.PACKET_LOGGING_CONFIG=Dnevniški zapis +plugin.loggingutils.ENABLE_DISABLE=Omogoči dnevniško zapisovnaje paketov +plugin.loggingutils.PACKET_LOGGING_RTP=RTP +plugin.loggingutils.PACKET_LOGGING_RTP_DESCRIPTION=(shrani 1 paket na 5000) +plugin.loggingutils.PACKET_LOGGING_ICE4J=ice4j.org +plugin.loggingutils.PACKET_LOGGING_DESCRIPTION=Zapisuje razhroščevalne pakete raznih protokolov v
    mapo dnevniškega zapisa formatu pcap (tcpdump/wireshark). +plugin.loggingutils.PACKET_LOGGING_FILE_COUNT=Število dnevniških datotek +plugin.loggingutils.PACKET_LOGGING_FILE_SIZE=Največja velikost datoteke (v KB) +plugin.loggingutils.ARCHIVE_BUTTON=Arhiviraj dnevniški zapis +plugin.loggingutils.UPLOAD_LOGS_BUTTON=Pošlji dnevniški zapis +plugin.loggingutils.UPLOAD_BUTTON=Pošlji +plugin.loggingutils.ARCHIVE_FILECHOOSE_TITLE=Izberite datoteko +plugin.loggingutils.ARCHIVE_UPREPORT_EMAIL=marijanovak@example.com +plugin.loggingutils.ARCHIVE_MESSAGE_OK=Arhviranje dnevniških zapisov je uspelo \n{0} +plugin.loggingutils.ARCHIVE_MESSAGE_NOTOK=Napaka pri arhviranju dnevniških zapisov \n{0} # dns config plugin +plugin.dnsconfig.TITLE=DNS +plugin.dnsconfig.DNSSEC=Varni DNS (DNSSEC) +plugin.dnsconfig.PARALLEL_DNS=Vzporedni DNS +plugin.dnsconfig.border.TITLE=Rezervni razreševalnik +plugin.dnsconfig.chkBackupDnsEnabled.text=Omogoči paralelno razreševanje DNS +plugin.dnsconfig.lblBackupResolver.text=Ime gostitelja +plugin.dnsconfig.lblBackupResolverFallbackIP.text=Nadomestni IP +plugin.dnsconfig.lblBackupPort.text=Vrata +plugin.dnsconfig.lblRedemption.text=Nazaj k glavnemu razreševalniku +plugin.dnsconfig.lblRedemption.description=število odzivov, ki jih mora nuditi glavni razreševelnaik, da ponovo izključimo rezervnega +plugin.dnsconfig.lblPatience.text=Zaženi rezervni razreševalnik po +plugin.dnsconfig.lblPatience.description=število ms, ko čakamo na odziv glavnega DNS preden preidemo na rezervni razreševalnik +plugin.dnsconfig.dnssec.chkEnabled=Omogoči razreševalnik DNSSEC +plugin.dnsconfig.dnssec.lblDefault=Privzeto obnašanje +plugin.dnsconfig.dnssec.DOMAIN_NAME=Domena +plugin.dnsconfig.dnssec.MODE=Obnašanje +net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Prezri +net.java.sip.communicator.util.dns.SecureResolveMode.SecureOnly=Zahtevano +util.dns.DNSSEC_ADVANCED_OPTIONS=Pokaži napredne možnosti +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Accept=Sprejmi v vsakem priemeru +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysAccept=Vedno sprejmi +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=Ne sprejmi +net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.AlwaysDeny=Nikoli ne sprejmi #plugin spellcheck +plugin.spellcheck.TITLE=Črkovanje in slovnica +plugin.spellcheck.MENU=Pokaži črkovanje in slovnico +plugin.spellcheck.ENABLE_SPELL_CHECK=Omogoči črkovanje +plugin.spellcheck.dialog.FIND=Najdi naslednje +plugin.spellcheck.dialog.REPLACE=Zamenjaj +plugin.spellcheck.dialog.ADD=Dodaj besedo +plugin.spellcheck.DICT_ERROR_TITLE=Napaka pri spremembi slovarja +plugin.spellcheck.DICT_ERROR=Ni mogoče spremeniti slovarja +plugin.spellcheck.DICT_PROCESS_ERROR=Jezikovna oznaka ni poznana +plugin.spellcheck.UNINSTALL_DICTIONARY=Odstrani +plugin.spellcheck.DICT_ERROR_DELETE_TITLE=Napaka pri odstranjevanju slovarja +plugin.spellcheck.DICT_ERROR_DELETE=Slovarja ni mogoče odstraniti +plugin.spellcheck.SPELLCHECK=Črkovanje #Certificate configuration plugin +plugin.certconfig.JAVA_TRUSTSTORE=Java +plugin.certconfig.WINDOWS_TRUSTSTORE=Windows +plugin.certconfig.ALIAS=Vzdevek v shrambi ključev +plugin.certconfig.KEYSTORE_TYPE=Vrsta +plugin.certconfig.KEYSTORE=Datoteka +plugin.certconfig.KEYSTORE_PASSWORD=Geslo +plugin.certconfig.ALIAS_LOAD_EXCEPTION=Zvdevka ni bilo mogoče pridobiti iz shrambe ključev ({0}). +plugin.certconfig.INVALID_KEYSTORE_TYPE=Izbrana vrsta shrambe ključev ni veljavna ({0}). +plugin.certconfig.BROWSE_KEYSTORE=Odpri shrambo ključev +plugin.certconfig.REVOCATION_TITLE=Možnosti preklica potrdil +plugin.certconfig.REVOCATION_CHECK_ENABLED=Preverjanje CRL (Seznam preklicanih potrdil) omogočeno +plugin.certconfig.REVOCATION_OCSP_ENABLED=Preverjanje OCSP (Spletni protokol stanja potrdil) omogočeno # Phone number contact source plugin +plugin.phonenumbercontactsource.DISPLAY_NAME=Telefonske številke # properties editor +plugin.propertieseditor.TITLE=Urejevalnik lastnosti +plugin.propertieseditor.NEW_PROPERTY_TITLE=Dodaj lastnost +plugin.propertieseditor.CHECK_BOX=Prihodnjič še pokaži to opozorilo +plugin.propertieseditor.IM_AWARE=Razumem tveganje #Thunderbird address book plugin +plugin.thunderbird.CONFIG_FORM_TITLE=Thunderbird +plugin.thunderbird.ENABLED=Omogočen +plugin.thunderbird.PHONE_PREFIX=Predklicna: -- cgit v1.1 From 333531bdc7dba58918cea7482086d5fb0d1ab858 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:29 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1300 of 1505 strings translated (13 fuzzy). --- resources/languages/resources_tr.properties | 306 ++++++++-------------------- 1 file changed, 88 insertions(+), 218 deletions(-) diff --git a/resources/languages/resources_tr.properties b/resources/languages/resources_tr.properties index 474bf3a..1fc3ca6 100644 --- a/resources/languages/resources_tr.properties +++ b/resources/languages/resources_tr.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -26,52 +37,49 @@ # ant -Duser.language=xx run service.gui.ABOUT=Hakkında -service.gui.ACCEPT=Cevapla +service.gui.ACCEPT=&Kabul Et service.gui.ACCOUNT=Hesap service.gui.ACCOUNT_ME=Kendim service.gui.ACCOUNT_REGISTRATION_WIZARD=Hesap Kayıt Sihirbazı service.gui.ACCOUNTS=Hesaplar service.gui.ADD=Ekle -service.gui.ADD_ACCOUNT=Hesap Ekle service.gui.ADD_CONTACT=Kişi Ekle service.gui.ADD_AUTHORIZED_CONTACT={0} Kişilere ekle -service.gui.ADD_CONTACT_TO=Şuraya Kişi Ekle -service.gui.ADD_CONTACT_ERROR={0} nolu kişi ekleyemedi +service.gui.ADD_CONTACT_TO_CONTACTLIST=Bu numarayı kişilere ekle +service.gui.ADD_CONTACT_TO=Kişi ekle +service.gui.ADD_CONTACT_ERROR={0} nolu kişi eklenemedi service.gui.ADD_CONTACT_ERROR_TITLE=Kişi Ekleme Hatası service.gui.ADD_CONTACT_EXIST_ERROR={0} zaten kişi listesinde var. service.gui.ADD_CONTACT_NETWORK_ERROR=Sunucu {0} nolu kişiyi ekleme isteğine cevap vermedi. -service.gui.ADD_CONTACT_NOT_SUPPORTED={0} nolu kişi ekleyemedi. İşlem desteklenmiyor. -service.gui.ADD_CONTACT_IDENTIFIER=Eklemek istediğiniz kişinin tanıtıcı kimliğini aşağıdaki bölüme giriniz. -service.gui.ADD_CONTACT_WIZARD=Kişi Ekleme Sihirbazı +service.gui.ADD_CONTACT_NOT_SUPPORTED={0} nolu kişi eklenemedi. İşlem desteklenmiyor. service.gui.ADD_CONTACT_NOT_CONNECTED=Kişi eklemek için bağlı olmalısınız. Lütfen seçili sağlayıcıya giriş yapın ve tekrar deneyin. -service.gui.ADD_GROUP_LOCAL_ERROR={0} isimli grubu ekleyemedi. Yerel yazım işlemi sırasında bir hata oluştu. -service.gui.ADD_GROUP_EXIST_ERROR={0} isimli grup zaten arkadaş listesinde mevcut. Lütfen başka bir grup ismi seçiniz. +service.gui.ADD_GROUP_LOCAL_ERROR={0} isimli grup eklenemedi. Yerel Giriş/Çıkış işlemi sırasında bir hata oluştu. +service.gui.ADD_GROUP_EXIST_ERROR={0} isimli grup zaten kişi listesinde mevcut. Lütfen başka bir grup ismi seçiniz. service.gui.ADD_GROUP_NET_ERROR={0} isimli grubu ekleyemedi. Ağ bağlantısından dolayı bir hata oluştu. Lütfen ağ bağlantınızı kontrol edin ve tekrar deneyin. service.gui.ADD_GROUP_ERROR={0} isimli grubu ekleyemedi. service.gui.ADD_GROUP_EMPTY_NAME=Grup ismi boş olamaz. -service.gui.ADD_GROUP=Grup oluştur -service.gui.ADD_SUBCONTACT=İkincil Kişi Ekle service.gui.ADDRESS=Adres service.gui.ADMINISTRATOR=yönetici service.gui.ADVANCED=Gelişmiş -service.gui.ALL=Hepsi service.gui.ALL_CONTACTS=Bütün kişiler +service.gui.ALTERNATE_ADDRESS=İkinci adres service.gui.APPLY=Uygula -service.gui.ARE_CALLING=arıyor... +service.gui.ARE_CALLING={0} arıyor... service.gui.ARE_NOW=Siz şu an {0} service.gui.AT=de service.gui.AUTHORIZE=Yetkilendir -service.gui.AUTHORIZATION_ACCEPTED=kişi sizin izin isteğinizi kabul etti. +service.gui.AUTHORIZATION_ACCEPTED={0}, yetkilendirme isteğinizi kabul etti. service.gui.AUTHENTICATION_FAILED=Kimlik {0} için başarısız oldu. Girdiğiniz şifre geçerli değil. -service.gui.AUTHENTICATION_REQUESTED=Onay istendi service.gui.AUTHENTICATION_REQUESTED_SERVER={0} sunucusu sizin onaylanmanızı istiyor. -service.gui.AUTHENTICATION_REJECTED=kişi sizin izin isteğinizi reddetti. +service.gui.AUTHENTICATION_REJECTED={0}, yetkilendirme isteğinizi reddetti. service.gui.AUTHENTICATION_WINDOW_TITLE={0} onaylama service.gui.AUTHORIZATION_REQUESTED=İzin istendi -service.gui.AUTHORIZATION_REQUESTED_INFO={0} arkadaş sizin izninizi istiyor. +service.gui.AUTHORIZATION_REQUESTED_INFO={0} kişi sizin izninizi istiyor. service.gui.AUTHORIZATION_RESPONSE=İzin cevabı service.gui.AWAY_STATUS=Dışarda +service.gui.EXTENDED_AWAY_STATUS=Uzun Süre Uzakta service.gui.BAN=Yasakla +service.gui.BANNED=yasaklı service.gui.BAN_FAILED=Yasaklanamandı service.gui.BAN_FAILED_GENERAL_ERROR={0} yasaklanamadı. Genel bir sunucu hatası oluştu. service.gui.BAN_FAILED_NOT_ALLOWED={0} yasaklanamadı. Oda sahibi ve oda yöneticisi yasaklanamaz. @@ -81,13 +89,17 @@ service.gui.BROWSE=Göz at service.gui.BUSY_MESSAGE=Üzgünüm, şu an meşgulum. service.gui.BUSY_STATUS=Meşgul service.gui.CALL=Ara -service.gui.CALL_CONTACT=Kişi ara +service.gui.CALL_CONTACT=Kişiyi ara service.gui.CALL_FAILED=Arama başarısız oldu service.gui.CALL_HISTORY_TOOL_TIP=Arama geçmişi için buraya tıkla +service.gui.CALL_HISTORY_GROUP_NAME=Arama geçmişi service.gui.CALL_VIA=Bunla ara: service.gui.CALL_NAME_OR_NUMBER=İsim veya numara gir service.gui.CALL_NOT_SUPPORTING_PARTICIPANT=Bu arama sadece {0} ağından katılımcıları ve sizin {1} hesabınızı destekler. {2} bu ağdan veya hesabınızdan adres içermemektedir. service.gui.CALL_WITH=Şununla ara +service.gui.CALL_NO_AUDIO_DEVICE=Yapılandırılmış bir ses aygıtınız yok. +service.gui.CALL_NO_AUDIO_CODEC=Yapılandırılmış bir ses çözücünüz yok. +service.gui.CALL_NO_DEVICE_CODECS_Q=Aramayı sürdürmek ister misiniz? service.gui.CANCEL=İptal et service.gui.CHAT=Sohbet service.gui.CHANGE_FONT=Fontu değiştir @@ -96,10 +108,13 @@ service.gui.CHANGE_ROOM_SUBJECT_LABEL=Aşağıdaki bölümde, odanın yeni konus service.gui.CHANGE_NICK=Takma ismi değiştir service.gui.CHANGE_NICKNAME=Takma ismi değiştir... service.gui.CHANGE_NICKNAME_LABEL=Aşağıdaki bölümde, yeni takma isminizi girebilirsiniz. -service.gui.CHANGE_VIDEO_QUALITY=Video kalitesini değişitir +service.gui.CHANGE_NICKNAME_ERROR=Takma adı değiştirirken sorun oluştu +service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Takma ad zaten var +service.gui.CHANGE_VIDEO_QUALITY=Uzak video kalitesini değiştir +service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}''ın konferansı service.gui.CHAT_ROOM_ALREADY_JOINED={0} sohbet odasına zaten katılındı. -service.gui.CHAT_ROOM_CONFIGURATION={0} sohbet odası konfigürasyonu -service.gui.CHAT_ROOM_CONFIGURATION_FAILED={0} sohbet odası konfigürasyon formu alınamadı. +service.gui.CHAT_ROOM_CONFIGURATION={0} sohbet odası ayarları +service.gui.CHAT_ROOM_CONFIGURATION_FAILED={0} sohbet odası ayarları formu alınamadı. service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED={0} sohbet odası konfigürasyonu kaydedilirken bir hata oluştu. service.gui.CHAT_ROOM_USER_JOINED={0} katıldı service.gui.CHAT_ROOM_USER_LEFT={0} ayrıldı @@ -108,18 +123,16 @@ service.gui.CHAT_ROOM_USER_QUIT={0} çıktı service.gui.CHAT_ROOM_NAME=Sohbet odası ismi service.gui.CLEAR_CUSTOM_MESSAGES=Kişiselleştirilmiş mesajları temizle service.gui.ROOM_NAME=Sohbet Odası -service.gui.AUTOJOIN=Otomatik katıl service.gui.CHANGE_PASSWORD=Şİfre değiştir service.gui.CHAT_ROOM_NAME_INFO=Aşağıdaki bölümde, oluşturmak istediğiniz sohbet odasının ismini giriniz. service.gui.CHAT_ROOM_NOT_EXIST={0} odası {1} sunucusunda bulunamadı. Lütfen girdiğiniz ismin doğruluğunu kontrol ediniz service.gui.CHAT_ROOM_NOT_CONNECTED={0} sohbet odasına katılabilmek için önce oturum açmalısınız. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Sohbet odasından ayrılabilmek için önce oturum açmalısınız. -service.gui.CHAT_ROOM_NOT_JOINED=Bir sohbet odasında işlem yapmak için önce o odaya katılmanız gerekir. service.gui.CHAT_ROOM_OPTIONS=Sohbet odası seçenekleri service.gui.CHAT_ROOM_REGISTRATION_REQUIRED={0} sohbet odası katılmak için kayıt gerektirmektedir. service.gui.CHAT_ROOM_REQUIRES_PASSWORD={0} sohbet odası şifre gerektirmektedir. service.gui.CHAT_ROOMS=Sohbet odaları -service.gui.CHAT_ROOM=Sohbet odaları +service.gui.CHAT_ROOM=Sohbet odası service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} konuyu {1}"e çevirdi. service.gui.CHOOSE_CONTACT=Kişi seç service.gui.CHOOSE_ACCOUNT=Lütfen listedeki hesaplardan birini seçiniz @@ -130,22 +143,18 @@ service.gui.CLEAR=Temizle service.gui.CLOSE=Kapat service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=2 saniyeden az bir süre önce bir mesaj aldınız? Bu sohbeti kapatmak istiyor musunuz? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Aktif dosya transferleriniz var. Bunları iptal etmek istiyor musunuz? -service.gui.CONFIRM=Onayla service.gui.CONNECTED_STATUS=Bağlandı service.gui.CONNECTING=Bağlanıyor... service.gui.CONNECTING_STATUS=Bağlantı service.gui.CONNECTING_EARLY_MEDIA_STATUS=Bağlanıyor* service.gui.CONNECTION=Bağlantı -service.gui.CONNECTION_FAILED_MSG=Bu hesap için bağlantı sağlanmadı: Kullanıcı adı: {0}, Sunucu adı: {1}. Lütfen ağ bağlantılarınızı kontrol ediniz veya daha fazla bilgi için ağ yöneticinizle görüşünüz. service.gui.CONNECTION_EXPIRED_MSG={0} sunucusundan koptunuz. service.gui.CONTACT_NAME=ID veya Numara -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Seçilen {0} kişinin telefonu desteklemiyor. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Seçilen {0} kişi sohbeti desteklemiyor. service.gui.CONTACT_PAUSED_TYPING={0} mesaj yazmaya ara verdi service.gui.CONTACT_TYPING={0} mesaj yazıyor service.gui.CONTACT_TYPING_SEND_FAILED=eyvah... {0}'a yazmakta olduğunuzu söyleyemedik service.gui.CONTACT_INFO=Kişi bilgisi -service.gui.CONTACTLIST=Kişilistesi service.gui.CONTACTS=Kişiler service.gui.COPY=Kopyala service.gui.COPY_LINK=Linki kopyala @@ -155,25 +164,21 @@ service.gui.CREATE_CHAT_ROOM=Sohbet odası oluştur... service.gui.CREATE_CHAT_ROOM_ERROR={0} sohbet odası oluşturulamadı. service.gui.CREATE_CHAT_ROOM_WIZARD=Sohbet odası sihirbazı oluştur service.gui.CREATE_CONFERENCE_CALL=Konferans arama oluştur... -service.gui.CREATE_CONFERENCE_CHAT=Konferans sohbet oluştur... service.gui.CREATE_GROUP=Grup oluştur... service.gui.CREATE_GROUP_NAME=Aşağıdaki bölümde oluşturmak istediğiniz grubun adını giriniz. -service.gui.CREATE_FIRST_GROUP_WIZARD=Kişi listeniz hiç grup içermemektedir. Lütfen önce bir grup oluşturunuz(Dosya/Grup Oluştur). service.gui.CREATE_VIDEO_BRIDGE=Bir &video köprüsü oluştur... service.gui.CREATE_VIDEO_BRIDGE_MENU=Bir &video köprüsü oluştur service.gui.CONTACT_INFO_NOT_SUPPORTED=Bu kişi ağ arkadaş bilgisini desteklememektedir service.gui.CUT=Kes -service.gui.DATE=Tarih service.gui.DELETE=Sil service.gui.DENY=Reddet -service.gui.DESKTOP_SHARING_WARNING=Ekran paylaşımını başlatmak istediğinizden emin misiniz
    Tamam'a basmak bu aramadaki insanların ekranınızı görmesini sağlar +service.gui.DESKTOP_SHARING_WARNING=Ekran paylaşımını başlatmak istediğinizden emin misiniz
    Bu aramadaki insanların ekranınızı görmesi için Tamam''a tıklayın. service.gui.DIALPAD=Tuş takımı service.gui.DISPLAY_NAME=Gösterilen isim service.gui.DISCONNECTED_STATUS=Bağlantı kesildi service.gui.DND_STATUS=Rahatsız etme service.gui.DO_NOT_ASK_AGAIN=Tekrar sorma service.gui.DO_NOT_SHOW_AGAIN=Bu mesajı tekrar gösterme -service.gui.DOWNLOAD_NOW=Şimdi indir service.gui.DRAG_FOR_SHARING=Buraya paylaşmak istediğinizi sürükleyerek bırakınız.... service.gui.DURATION=süre service.gui.EDIT=Düzenle @@ -190,7 +195,6 @@ service.gui.ERROR_WAS={0} hatası çıktı service.gui.ESTIMATED_TIME=Tahmin edilen süre: service.gui.EVENTS=Aktiviteler service.gui.EXIT=Çık -service.gui.EXTENDED_CRITERIA=Genişletilmiş kriter service.gui.GENERAL=Genel service.gui.GENERAL_ERROR=Genel Hata service.gui.GROUP_NAME=Grup ismi @@ -224,7 +228,7 @@ service.gui.FOLDER_DOES_NOT_EXIST=Bu dosyayı içeren dizin bulunamadı. Silinmi service.gui.FOLDER_OPEN_FAILED=Dizin açılamadı. service.gui.FOLDER_OPEN_NO_PERMISSION=Bu dizini açmak için yeterli izniniz yok. Lütfen okuma izinlerinizi kontrol edip tekrar deneyiniz. service.gui.FOLDER_OPEN_NO_APPLICATION=Bu dizini açabilecek program bulunamadı. -service.gui.FONT=Punto +service.gui.FONT=Yazıtipi service.gui.FONT_BOLD=Kalın service.gui.FONT_COLOR=Renk service.gui.FONT_FAMILY=Aile @@ -246,14 +250,15 @@ service.gui.HIDE_OFFLINE_CONTACTS=Çevrimdışı kişileri gizle service.gui.HIDE_MAIN_WINDOW=
    X pencere butonuna tıklamak programı kapatmaz, sadece gizler.
    Eğer kapatmak istiyorsanız Dosya/Çık seçilmeli.
    service.gui.HISTORY=Geçmiş service.gui.HISTORY_CONTACT=Geçmiş - {0} +service.gui.HISTORY_ERASE_PER_CHATROOM=Bu sohbet odasındaki bütün eski yazışmaları sil service.gui.HOME=Ev service.gui.HOME_PAGE=Ana sayfa -service.gui.HOUR=Saat service.gui.ICE=ICE service.gui.IDENTIFIER=Belirleyici kimlik service.gui.IGNORE=Yoksay service.gui.INSERT_SMILEY=Gülücük koy service.gui.INCOMING_CALL={0}"dan gelen arama alındı +service.gui.INCOMING_SCREEN_SHARE={0}''dan gelen ekran paylaşımı alındı service.gui.INCOMING_CALL_STATUS=Gelen arama service.gui.INSTANT_MESSAGINGS=IM'ler service.gui.INITIATING_CALL_STATUS=Başlatılan arama @@ -267,13 +272,10 @@ service.gui.INVITE_CONTACT_TO_CHAT=Kişileri sohbete davet et service.gui.INVITE_CONTACT_TO_CALL=Kişileri konuşmaya davet et service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Kişileri video köprüsüne davet et service.gui.INVITE_REASON=Davet nedeni -service.gui.IS_CALLING=arıyor... +service.gui.IS_CALLING={0} arıyor... service.gui.IS_NOW={0} şu an {1} -service.gui.JITSI_WARNING=SIP Communicatorın ismi Jitsi olarak değişti.
    Eğer sürümünüzü güncellemek istiyorsanız Jitsi'yi indirebilirsiniz..

    Sizi rahatsız ettiğimiz için özür dileriz.

    The Jitsi Dev Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator Jitsi oluyor service.gui.JOIN=Katıl service.gui.JOIN_AS=Şu şekilde katıl -service.gui.CLOSE_CHAT_ROOM_DIALOG=Kapat service.gui.JOB_TITLE=İş tanımı service.gui.JOIN_CHAT_ROOM=Sohbet odasına katıl... service.gui.JOIN_CHAT_ROOM_TITLE=Sohbet odasına katıl @@ -284,11 +286,10 @@ service.gui.KICK_FAILED=Atma başarısız service.gui.KICK_FAILED_GENERAL_ERROR={0} atılamadı. Genel bir sunucu hatası oluştu. service.gui.KICK_FAILED_NOT_ALLOWED={0} atılamadı. Odanın sahibi ve yöneticisi atılamaz. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS={0} atılamadı. Bu yapmak için yeterli izniniz yok. -service.gui.LAST=Son service.gui.LAST_NAME=Soyad service.gui.LEAVE=Terk et service.gui.LIMIT_REACHED_FOR_IP=Yerel IP adresinden çok fazla kaydınız var ve {0} sunucusu daha fazla açmanıza izin vermeyecek. -service.gui.LIST=Son +service.gui.LIST=Listele service.gui.LOADING_ROOMS=Odalar yükleniyor... service.gui.LOADING=Yükleniyor... service.gui.LOCALLY_ON_HOLD_STATUS=Yerel olarak beklemede @@ -304,8 +305,7 @@ service.gui.MESSAGE=Mesaj service.gui.MISSED_CALLS_TOOL_TIP=Cevapsız çağrılar: service.gui.MISSED_CALLS_MORE_TOOL_TIP= ve {0} daha fazla service.gui.MODERATOR=moderatör -service.gui.MORE=Daha fazla gör -service.gui.MORE_LABEL=Taşı +service.gui.MORE_LABEL=Daha service.gui.MOVE=Taşı service.gui.MOVE_SUBCONTACT=Kişi taşı service.gui.MOVE_SUBCONTACT_MSG=Seçtiğiniz kişiyi taşıyacağınız kişi veya grup seçiniz. @@ -313,7 +313,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Seçtiğiniz kişi taşımak istediğiniz ki service.gui.MOVE_SUBCONTACT_QUESTION={0}"ı {1}"e taşımak istediğinizden emin misiniz? service.gui.MOVE_TO_GROUP=Gruba taşı service.gui.MOVE_CONTACT=Kişi Taşı -service.gui.MOVE_CONTACT_ERROR=Kişi taşınamaz service.gui.MSG_DELIVERY_FAILURE=Yukarıdaki mesaj iletilemedi service.gui.MSG_DELIVERY_NOT_SUPPORTED=Kullandığınız protokol çevrimdışı mesajları desteklememektedir. {0}'a başka bir protokolden ulaşmayı deneyebilir veya kişi çevrimiçi olana kadar bekleyebilirsiniz. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Dahili bir hata oluştu. Bu büyük bir ihtimalle program hatası. Lütfen şuraya bildiriniz: http://jitsi.org/index.php/Development/BugAndIssues. @@ -324,7 +323,6 @@ service.gui.MSG_NOT_POSSIBLE=Mesajlaşma bu kişi için imkansız(protokol taraf service.gui.MSG_RECEIVED={0} yazdı service.gui.MSG_SEND_CONNECTION_PROBLEM=Mesaj gönderebilmek için çevrimiçi olmalısınız. service.gui.MULTIPLE_LOGINS=Aynı hesap ile birden fazla oturum açtınız. Şu hesabın bağlantısı koptu: Kullanıcı adı: {0}, Sunucu adı: {1}. -service.gui.MUTE=Sessiz service.gui.MUTUALLY_ON_HOLD_STATUS=Sessizce beklemede service.gui.NAME=İsim service.gui.NETWORK=Ağ @@ -335,6 +333,7 @@ service.gui.NEW_MESSAGE=Yeni mesaj service.gui.NEW_NAME=Yeni isim service.gui.NEW_STATUS_MESSAGE=Yeni durum mesajı service.gui.NEW_STATUS_MESSAGE_SAVE=Kişiselleştirilmiş mesaj olarak kaydet +service.gui.NICKNAME=Rumuz service.gui.NO=Hayır service.gui.NONE=Hiç service.gui.NO_CAMERA_AVAILABLE=Kamera yok @@ -353,8 +352,7 @@ service.gui.NON_EXISTING_USER_ID={0} sunucusu belirtilen kullanıcı numarasın service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Kişilistesindedeğil service.gui.SD_QUALITY=Standart kalite service.gui.OFFLINE=Çevrimdışı -service.gui.OK=Tamam -service.gui.OLDER_CALLS=Daha eski aramalar +service.gui.OK=&Tamam service.gui.ONLINE=Çevrimiçi service.gui.OPEN=Aç service.gui.OPEN_FILE_FROM_IMAGE=Dosyayı açmak için çift tıklayınız. @@ -362,9 +360,12 @@ service.gui.OPEN_FOLDER=Dizini aç service.gui.OPEN_IN_BROWSER=Web tarayıcısında aç service.gui.OPTIONS=Ayarlar service.gui.OR=veya -service.gui.OR_ENTER_PHONE_NUMBER=Veya telefon numarasını buraya giriniz... service.gui.ORGANIZATION=Organizasyon service.gui.OTHER=Diğer +service.gui.chat.role.ADMINISTRATOR=Yönetici +service.gui.chat.role.MODERATOR=Moderatör +service.gui.chat.role.MEMBER=Üye +service.gui.chat.role.SILENT_MEMBER=Sessiz üye service.gui.OWNER=odanın sahibi service.gui.PASSWORD=Şifre service.gui.PASSWORD_CHANGE_FAILURE=Şifre değiştirme başarısız oldu @@ -378,7 +379,6 @@ service.gui.PRESENCE=Durum service.gui.PRESS_ENTER_FOR_SUGGESTIONS=Öneriler için 'Enter' service.gui.PRESS_FOR_CALL_INFO=Arama bilgisi için tıkla service.gui.PREVIOUS=Önceki -service.gui.PREVIOUS_TOOLTIP=Daha eski konuşmalara göz at service.gui.PRINT=Yazdır service.gui.PROACTIVE_NOTIFICATION=mesaj yazıyor service.gui.PROTOCOL=Protokol @@ -391,7 +391,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Çok hızlı bir şekilde sunucudan kopu service.gui.RE_REQUEST_AUTHORIZATION=Re-İzin iste service.gui.REFERRED_STATUS=Başvuruldu service.gui.REJECT=Reddet -service.gui.REMIND_ME_LATER=Daha sonra hatırlat service.gui.REMEMBER_PASSWORD=Şifreyi hatırla service.gui.REMOVE=Sil service.gui.REMOVE_ACCOUNT=Hesabı sil @@ -416,27 +415,18 @@ service.gui.REVOKE_ADMIN=Yöneticiliği geri al service.gui.REVOKE_MODERATOR=Moderatörlüğü geri al service.gui.REVOKE_MEMBERSHIP=Üyeliği geri al service.gui.REVOKE_VOICE=Sesi geri al -service.gui.ROOT_GROUP=Temel grup service.gui.SAVE=Kaydet -service.gui.SAVE_AS_DEFAULT=Varsayılan olarak kaydet service.gui.SEARCH=Ara service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Seçili sunucudaki bütün sohbet odalarını listelemek için aşağıdaki butona tıklayınız. Daha sonra katılmak istediğinizi seçiniz ve katıl butonuna tıklayınız service.gui.SEARCH_STRING_CONTACT_SOURCE=Kişi arandı service.gui.SECURITY=Güvenlik -service.gui.SELECT_ACCOUNT=Hesap seç service.gui.SELECT_COLOR=Renk seç service.gui.SELECT_GROUP=Grup seç -service.gui.SELECT_GROUP_WIZARD_MSG=Aşağıdaki liste sizin kişi listenizdeki bütün grupları içermektedir. Yeni kişi eklemek istediğiniz grubu seçiniz. service.gui.SELECT_NO_GROUP=Grup yok -service.gui.SELECT_GROUP_WIZARD=Grubu belirtiniz service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Aşağıdaki liste çoklu kullanıcı sohbet modunu destekleyen bütün hesapları göstermektedir. Sohbet odası oluştururken kullanmak istediğiniz bir hesap seçiniz. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Aşağıdaki liste bütün kayıtlı hesapları içermektedir. Yeni kişi ile iletişim kurmak için kullanacağınız bir hesap seçiniz. -service.gui.SELECT_PROVIDERS_WIZARD=Hesap seç service.gui.SEND=Gönder service.gui.SEND_FILE=Dosya gönder -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Bu arkadaş için bilgi yok. service.gui.SEND_MESSAGE=Mesaj gönder -service.gui.SEND_AS_SMS=SMS olarak gönder service.gui.SEND_SMS=SMS gönder service.gui.SEND_SMS_DETAILS=Numarayı uluslararası formatta gireceğinizi unutmayın örneğin Birleşik Krallık için +44 ile başlıyor +447777000000 service.gui.SEND_SMS_NOT_SUPPORTED=Seçtiğiniz protokol SMS mesajlarını desteklemiyor. @@ -471,7 +461,6 @@ service.gui.STREET=Sokak service.gui.SUBJECT=Konu service.gui.SUMMARY=Özet service.gui.TELEPHONY=Telefon -service.gui.TODAY=Bugün service.gui.TOOLS=Araçlar service.gui.TRANSFER=Transfer service.gui.TO=Şu kişiye: @@ -481,7 +470,6 @@ service.gui.TRANSFER_CALL_TO=Şu kişiye transfer et: service.gui.TRANSPARENCY_NOT_ENABLED=Saydamlık şuanki konfigürasyonunuz tarafından desteklenmemektedir. service.gui.TYPE_YOUR_REQUEST=İsteğinizi buraya giriniz service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Bu çağrı için video kalitesini değiştiremiyoruz -service.gui.UNMUTE=Sessiz modunu kapat service.gui.USER_IDENTIFIER=Kullanıcı tanıtıcı kimlik: service.gui.USER_EXISTS_ERROR=Bu kullanıcı seçilen ağda zaten mevcut. Lütfen başka bir kullanıcı veya ağ seçiniz. service.gui.USERNAME_NULL=Lütfen kullanıcı adınızı ve şifrenizi doldurunuz @@ -490,9 +478,8 @@ service.gui.UNKNOWN=Bilinmeyen kullanıcı service.gui.UNKNOWN_STATUS=Bilinmeyen durum service.gui.UNREGISTERED_MESSAGE=Şu hesaba bağlanılamadı: Kullanıcı adı : {0}, Sunucu adı: {1}. Şu an çevrimdışısınız. service.gui.USE_PROVISIONING=Online provizyon kullan -service.gui.VALUE=Değer: +service.gui.VALUE=Değer service.gui.VIDEO_CALL=Video araması -service.gui.VIA_SMS=SMS ile gönder service.gui.VIEW=Görünüm service.gui.VIEW_HISTORY=Geçmiş görünümü service.gui.VIEW_SMILEYS=Yüzler görünümü @@ -512,9 +499,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Ses ayarla service.gui.WAITING_AUTHORIZATION=Yetki için bekleniyor service.gui.WARNING=Uyarı service.gui.YES=Evet -service.gui.YESTERDAY=Dün -service.gui.EXISTING_ACCOUNT_ERROR=Girdiğiniz hesap zaten yüklendi. -service.gui.NEW_MAIL=Bir yeni maliniz var!
    Den: {0} {1}
    Konu: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Sizin {0} gelen kutunuzda, yeni bir mail mesajı aldınız:
    service.gui.NEW_GMAIL_MANY_HEADER=Sizin {0} gelen kutunuzda, {2} tane yeni mail mesajı aldınız:
    service.gui.NEW_GMAIL_FOOTER=Sizin gelen kutunuzda bir tane daha okunmamış konuşma bulunmaktadır.
    @@ -537,7 +521,6 @@ service.gui.SECURITY_ERROR=Güvenlik hatası service.gui.SPEED=Hız: service.gui.SILENT_MEMBER=sessiz üye service.gui.NON_SECURE_CONNECTION={0} hesabı için güvenli bağlantı oluşturulamadı. Eğer güvensiz sunucuyabağlanmak istiyorsanız hesabınız ayarlarında "Güvensiz bağlantılara izin}seçiniz -service.gui.UPDATE=Güncelle service.gui.MOBILE_PHONE=Mobil service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=İş @@ -549,7 +532,7 @@ service.gui.ZID_NAME_SET=ZRTP tanımlayıcısının ismi: service.gui.ZID_NAME_NOT_SET=ZRTP tanımlayıcısının ismi konulmamış. service.gui.ZID_NAME_BUTTON=Bir ZRTP tanımlayıcısı ismi koymak için tıklayın. service.gui.ZID_NAME_DIALOG=ZRTP tanımlayıcısının ismini düzenle -service.gui.ZID_NAME_UNEXPECTED=ZRTP tanımlayıcı ismi eşleşmiyor.
    Doğrulama metni partneriniz ile karşılaştırın ve kontrol edin!
    ZRTP tanımlayıcısının ismini düzenle ve sadece doğrulama metni tutuyorsa sakla. +service.gui.ZID_NAME_UNEXPECTED=ZRTP tanımlayıcı ismi eşleşmiyor.
    Doğrulama metni partneriniz ile karşılaştırın ve kontrol edin!
    ZRTP tanımlayıcısının ismini düzenleyin ve sadece doğrulama metni tutuyorsa saklayın. service.gui.JANUARY=Oca service.gui.FEBRUARY=Şub @@ -569,7 +552,6 @@ service.gui.callinfo.CALL_INFORMATION=Arama bilgisi service.gui.callinfo.CALL_IDENTITY=Kimlik service.gui.callinfo.PEER_COUNT=Katılımcı sayısı service.gui.callinfo.IS_CONFERENCE_FOCUS=Konferans odağı -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Şifreleme etkin service.gui.callinfo.CALL_TRANSPORT=Çağrı ulaştırma sinyalleniyor service.gui.callinfo.CALL_DURATION=Arama süresi service.gui.callinfo.VIEW_CERTIFICATE=Sertifikayı göster @@ -580,7 +562,6 @@ service.gui.callinfo.AUDIO_INFO=Ses bilgisi service.gui.callinfo.VIDEO_INFO=Vieo bilgisi service.gui.callinfo.LOCAL_IP=Yerel IP/ Port service.gui.callinfo.REMOTE_IP=Uzak IP/ Port -service.gui.callinfo.BANDWITH=Bandwith service.gui.callinfo.LOSS_RATE=Kayıp oranı service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Seğirme @@ -590,10 +571,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Anahtar değiştirme protokolü service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE adayı genişletilmiş türü service.gui.callinfo.ICE_STATE=ICE işleme durumu + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Adayları topla service.gui.callinfo.ICE_STATE.RUNNING=Bağlantı durumu kontrolleri service.gui.callinfo.ICE_STATE.COMPLETED=Tamamlandı service.gui.callinfo.ICE_STATE.FAILED=Başarısız oldu + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Yerel istemci IP / Port service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Yerel yansımalı IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Yerel aktarmalı IP / Port @@ -612,11 +596,12 @@ service.gui.callinfo.JITTER_BUFFER_DELAY=Jitter önbelleği service.gui.ALWAYS_TRUST=Bu sertifikaya her zaman güven service.gui.CERT_DIALOG_TITLE=Sertifikayı doğrula -service.gui.CERT_DIALOG_DESCRIPTION_TXT=
    {0}, {1}:{2}"e bağlanırken sunucunun kimliğini belirleyemez.

    Sertifika güvenilir değil, bunun anlamı sunucunun kimliği otomatik olarak belirlenemez. Bağlanmaya devam etmek istiyor musunuz?

    Daha fazla bilgi için, "Sertifikayı göster" e tıklayınız. +service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} sunucunun kimliğini doğrulayamadı
    {1}''e bağlanırken.

    Sertifika güvenilir değil, bunun anlamı sunucunun kimliği otomatik olarak doğrulanamaz.

    Bağlanmaya devam etmek istiyor musunuz?
    Daha fazla bilgi için, "Sertifikayı göster" e tıklayınız. service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST=
    {0}, {1}:{2}"e bağlanırken sunucunun kimliğini belirleyemez.

    Sertifika güvenilir değil, bunun anlamı sunucunun kimliği otomatik olarak belirlenemez. Bağlanmaya devam etmek istiyor musunuz?

    Daha fazla bilgi için, "Sertifikayı göster" e tıklayınız. -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT=
    {0}, {1}:{2}"e bağlanırken sunucunun kimliğini belirleyemez.

    Sertifika güvenilir değil, bunun anlamı sunucunun kimliği otomatik olarak belirlenemez. Bağlanmaya devam etmek istiyor musunuz?

    Daha fazla bilgi için, "Sertifikayı göster" e tıklayınız. service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT=
    {0}, {1}:{2}"e bağlanırken sunucunun kimliğini belirleyemez.

    Sertifika güvenilir değil, bunun anlamı sunucunun kimliği otomatik olarak belirlenemez. Bağlanmaya devam etmek istiyor musunuz?

    Daha fazla bilgi için, "Sertifikayı göster" e tıklayınız. service.gui.CONTINUE_ANYWAY=Yine de devam et + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Yaygın isim: service.gui.CERT_INFO_O=Organizasyon: service.gui.CERT_INFO_C=Ülke ismi: @@ -625,18 +610,16 @@ service.gui.CERT_INFO_L=İlçe/Mahalle ismi: service.gui.CERT_INFO_OU=Organizasyon birimi: service.gui.CERT_INFO_ISSUED_ON=Şu zamanda yayıldı: service.gui.CERT_INFO_EXPIRES_ON=Şu zamanda bitiyor: -service.gui.CERT_INFO_FINGERPRINTS=Parmak İzi +service.gui.CERT_INFO_FINGERPRINTS=Parmak izleri service.gui.CERT_INFO_SER_NUM=Seri Numarası: service.gui.CERT_INFO_VER=Versiyon: service.gui.CERT_INFO_SIGN_ALG=İmza Algoritması: service.gui.CERT_INFO_ALG=Algoritma: service.gui.CERT_INFO_PUB_KEY=Genel Anahtar: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} byte: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bit service.gui.CERT_INFO_EXP=Üst: service.gui.CERT_INFO_KEY_SIZE=Anahtar Boyutu: service.gui.CERT_INFO_SIGN=İmza: -service.gui.CONTINUE=Devam et service.gui.SHOW_CERT=Sertifikayı göster service.gui.HIDE_CERT=Sertifikayı gizle @@ -657,12 +640,9 @@ service.gui.security.SECURE_AUDIO=Güvenli ses service.gui.security.AUDIO_NOT_SECURED=Ses güvenli değil service.gui.security.SECURE_VIDEO=Güvenli video service.gui.security.VIDEO_NOT_SECURED=Video güvenli değil -service.gui.security.NO_VIDEO=Video yok -service.gui.security.CIPHER=Şifre: {0} service.gui.security.CALL_SECURED_TOOLTIP=Arama güvenlileştirildi. Daha fazla bilgi için buraya tıklayın. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Arama güvenli değil. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Güvenlik sırrını partneriniz ile karşılaştırmak için buraya tıklayın. -service.gui.security.COMPARE_WITH_PARTNER=Partneriniz ile karşılaştırınız ve onaylamak için kilite tıklayınız # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Partneriniz ile karşılaştırın: service.gui.security.STRING_COMPARED=Metin karşılaştırıldı! @@ -679,19 +659,13 @@ service.gui.avatar.imagepicker.CLICK=Tıkla ve Gülümse service.gui.avatar.imagepicker.IMAGE_FILES=Resim dosyaları service.gui.avatar.imagepicker.IMAGE_PICKER=Resim service.gui.avatar.imagepicker.IMAGE_SIZE=Resim boyutu -service.gui.avatar.imagepicker.INITIALIZING=Başlatılıyor service.gui.avatar.imagepicker.RESET=Sıfırla service.gui.avatar.imagepicker.SET=Ayarla service.gui.avatar.imagepicker.TAKE_PHOTO=Resim çek -service.gui.avatar.imagepicker.WEBCAM_ERROR=Webcam hatası service.gui.security.encryption.required=Şifrleme gerekli! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=SIP kişi listesi depolamada hata impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Kaynak okunamadı {0}. {1} için @@ -714,9 +688,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=ağ seç # LDAP impl.ldap.CONFIG_FORM_TITLE=LDAP ayarları impl.ldap.GENERAL=Genel -impl.ldap.NEW=Yeni impl.ldap.EDIT=düzenle -impl.ldap.REMOVE=Sil impl.ldap.ENABLED=Aktif et impl.ldap.SERVER_NAME=Sunucu adı impl.ldap.SERVER_NAME_EXAMPLE=LDAP sunucum @@ -749,6 +721,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=ev telefonu impl.ldap.PHONE_PREFIX=Telefon öneki impl.ldap.PHONE_PREFIX_EXAMPLE=Ör:00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Adres defteri plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=MacOSX Adres Defterini aramayı etkinleştir @@ -759,9 +735,7 @@ plugin.addrbook.PREFIX_EXAMPLE=Ör.:00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google Kişiler -impl.googlecontacts.NEW=Yeni impl.googlecontacts.EDIT=düzenle -impl.googlecontacts.REMOVE=Sil impl.googlecontacts.ENABLED=Aktif et impl.googlecontacts.ACCOUNT_NAME=Hesap Adı impl.googlecontacts.SAVE=Kaydet @@ -775,7 +749,7 @@ impl.googlecontacts.WRONG_CREDENTIALS={0} Google hesabı için yanlış kimlik b plugin.accountinfo.TITLE=Hesap Bilgisi plugin.accountinfo.EXTENDED=Genişletilmiş plugin.accountinfo.NOT_SUPPORTED=Hesap bilgisi yok. -plugin.accountinfo.DISPLAY_NAME=Gösterilen isim +plugin.accountinfo.DISPLAY_NAME=Görünen isim: plugin.accountinfo.FIRST_NAME=İsim: plugin.accountinfo.MIDDLE_NAME=İkinci İsim: plugin.accountinfo.LAST_NAME=Soy İsim: @@ -783,16 +757,13 @@ plugin.accountinfo.NICKNAME=Takma ad: plugin.accountinfo.AGE=Yaş: plugin.accountinfo.BDAY=Doğum Tarihi: plugin.accountinfo.GENDER=Cinsiyet: -plugin.accountinfo.CITY=Şehir -plugin.accountinfo.POST=Posta kodu -plugin.accountinfo.COUNTRY=Ülke +plugin.accountinfo.CITY=Şehir: +plugin.accountinfo.POST=Posta kodu: +plugin.accountinfo.COUNTRY=Ülke: plugin.accountinfo.EMAIL=E-mail Adresi: plugin.accountinfo.PHONE=Telefon: plugin.accountinfo.MOBILE_PHONE=cep telefonu plugin.accountinfo.JOB_TITLE=İş tanımı -plugin.accountinfo.USER_PICTURES=Kullanıcı Resimleri -plugin.accountinfo.CHANGE=Değiştir -plugin.accountinfo.ONLY_MESSAGE=Sadece mesajlar # connection info @@ -811,49 +782,12 @@ plugin.aimaccregwizz.USERNAME=AIM Ekran İsmi plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Ekran İsmi ve Şifre plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Yeni hesap kaydet plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Eğer AIM hesabınız yoksa, bu butona tıklayarak yeni bir hesap alabilirsiniz. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Sunucu varsayılan ayarlarını üzerine yaz # branding plugin.branding.ABOUT_WINDOW_TITLE={0} hakkında plugin.branding.LOGO_MESSAGE=Açık kaynak kodlu VoIP && Anlık Mesajlaşma -plugin.branding.LOADING=Yükleniyor plugin.branding.ABOUT_MENU_ENTRY=Hakkında -plugin.branding.WELCOME_MESSAGE=
    {1} aktif olarak geliştirilmektedir. Şu an kullanmakta olduğunuz versiyon test aşamasındadır ve beklendiği gibi ÇALIŞMAYABİLİR. Lütfen daha fazla bilgi için {2}.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.orgBütün hakları gizlidir. Ziyaret et http://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi LGPL lisansı koşulları altında dağıtılmaktadır(http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Sözlükler -plugin.dictaccregwizz.ANY_DICTIONARY=Herhangi bir sözlük -plugin.dictaccregwizz.ANY_DICTIONARY_FORM={0}"dan herhangi bir sözlük -plugin.dictaccregwizz.FIRST_MATCH=İlk Eşleşen -plugin.dictaccregwizz.NO_MATCH=Eşleşen yok -plugin.dictaccregwizz.MATCH_RESULT="{0}" için tanım bulunamadı, belki bunu demek istediniz:\n -plugin.dictaccregwizz.INVALID_DATABASE=Şuanki sözlük "{0}" artık sunucuda bulunmamaktadır. -plugin.dictaccregwizz.INVALID_STRATEGY=Şuanki arama kriteri sunucuda hazır değildir. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Dict servis protokolü -plugin.dictaccregwizz.HOST=Servis sağlayıcı -plugin.dictaccregwizz.SERVER_INFO=Sunucu bilgileri -plugin.dictaccregwizz.STRATEGY_SELECTION=Arama kriteri seçimi -plugin.dictaccregwizz.STRATEGY_LIST=Arama kriterleri listesi -plugin.dictaccregwizz.SEARCH_STRATEGIES=Arama kriterlerini ara -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Arama kriteri, eğer çviri yoksa benzer kelimeleri bulmak için kullanılır. Örneğin önden arama kriteri, sizin çevireceğiniz kelimenin ilk harfiyle başlayan kelimeleri arayacak. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict Hesap Bilgileri -plugin.dictaccregwizz.FIRST_ACCOUNT=Bu sihirbaz sizin için dict.org'da bir Dict hesabı açacaktır.\n\nHesap Kayıt Sihirbazına giderek yeni bir sözlük ekleyebilirsiniz. Servis sağlayıcı kısmını eklemek istediğiniz sözlük ile doldurunuz. -plugin.dictaccregwizz.THREAD_CONNECT=Sunucuya bağlanmaya çalışıyor -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Bağlanamadı, bu dict sunucusu değil veya sunucu çevrim dışı -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Arama kriterleri alınıyor -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Sunucuda arama kriteri bulunamadı -plugin.dictaccregwizz.POPULATE_LIST=Liste dolduruluyor -plugin.dictaccregwizz.CLOSING_CONNECTION=Bağlantı kapatılıyor - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Facebook sohbeti kullanabilmek için Hesap Ayarları sayfasından bir kullanıcı ismi oluşturmalısınız.a>

    Not: Kullanıcı ismi aldıktan sonra oturum kapatmalısınız ve yeni kullanıcı isminizle oturum açmak biraz zaman alabilir.
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Facebook Sohbet Protokolü -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Kullanıcı Adı: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Kullanıcı Adı ve Şifre + # generalconfig plugin.generalconfig.AUTO_START=Bilgisayar baştan başladığında otomatik başlat {0}. @@ -864,9 +798,6 @@ plugin.generalconfig.SHOW_HISTORY=Göster plugin.generalconfig.HISTORY_SIZE=Yeni sohbetlerdeki son mesajlar plugin.generalconfig.SEND_MESSAGES_WITH=Mesajları şunla gönder: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Sohbet penceresini öne getir -plugin.generalconfig.ERROR_PERMISSION=Otomatik başlatı silmek için yeterli izniniz yok -plugin.generalconfig.TRANSPARENCY=Saydamlık -plugin.generalconfig.ENABLE_TRANSPARENCY=Saydamlığı aktif et plugin.generalconfig.DEFAULT_LANGUAGE=Arabirim dili plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Değişiklikler tekrar başladığında aktif olacak. plugin.generalconfig.SIP_CLIENT_PORT=SIP istemci portu @@ -910,19 +841,20 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Yeni hesap kaydet plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=IRC protokol plugin.ircaccregwizz.USERNAME_AND_PASSWORD=Kullanıcı ID ve Şifre +plugin.ircaccregwizz.USERNAME=Rumuz plugin.ircaccregwizz.INFO_PASSWORD=Genellikle IRC sunucuları şifre istemez. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Eğer takma ad daha önce kullanıldıysa otomatik olarak değiştir plugin.ircaccregwizz.USE_DEFAULT_PORT=Varsayılan portu kullan plugin.ircaccregwizz.PASSWORD_NOT_REQUIRED=Benim takma adım kimlik tanımlaması gerektirmez plugin.ircaccregwizz.HOST=Servis sağlayıcı: plugin.ircaccregwizz.IRC_SERVER=Sunucu +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} onaylama +plugin.ircaccregwizz.SASL_USERNAME=Kullanıcı adı # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPP protokol plugin.jabberaccregwizz.USERNAME=XMPP kullanıcı adı plugin.jabberaccregwizz.PASSWORD_CONFIRM=Şifreyi onayla -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=Kullanıcı ID ve Şifre plugin.jabberaccregwizz.CSERVER=Sunucu plugin.jabberaccregwizz.SERVER=Sunucuya Bağlan plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Bağlantının canlı durmasını aktif et @@ -938,13 +870,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Yorum plugin.jabberaccregwizz.RESOURCE=Kaynak plugin.jabberaccregwizz.AUTORESOURCE=Otomatik kaynak oluştur plugin.jabberaccregwizz.PRIORITY=Öncelik -plugin.jabberaccregwizz.XMPP_ERROR=XMPP Hatası plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Bilinmeyen XMPP hatası. Sunucu isminin doğruluğundan emin olunuz. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Şifreler birbiri ile uyumlu değil -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Sunucu varsayılan ayarlarının üstüne yaz -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Gelişmiş ayarlar plugin.jabberaccregwizz.USE_ICE=ICE kullan -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Google Jingle/ICE kullan(deneysel) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Otomatik STUN/TURN sunucularını ara plugin.jabberaccregwizz.SUPPORT_TURN=TURN destekle plugin.jabberaccregwizz.TURN_USERNAME=TURN kullanıcı adı @@ -971,11 +899,8 @@ plugin.jabberaccregwizz.ALLOW_NON_SECURE=Güvensiz bağlantılara izin ver plugin.jabberaccregwizz.DTMF_AUTO=Otomatik: RTP ve Inband arasında seçim yap plugin.jabberaccregwizz.SERVER_OPTIONS=Sunucu seçenekleri plugin.jabberaccregwizz.CHANGE_PASSWORD=Hesap parolasını değiştir -plugin.jabberaccregwizz.NEW_PASSWORD=Yeni parola -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Yeni parolayı onayla plugin.jabberaccregwizz.PORT_FIELD_INVALID=Devam etmek için lütfen geçerli bir port numarası girin. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Parola değiştirmeden önce bu hesaba giriş yapılmalıdır. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Bu parola boş. plugin.jabberaccregwizz.TLS_REQUIRED=Bağlantı TLS kullanmıyor, parola değişikliği girişiminde bulunulmayacak. plugin.jabberaccregwizz.PASSWORD_CHANGED=Parola başarıyla değiştirildi plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Jabber sunucunuz parola değişikliğini desteklemiyor. @@ -989,25 +914,9 @@ plugin.jabberaccregwizz.RESET=Sıfırla plugin.jabberaccregwizz.RESET_DESCRIPTION=Sıfırlayarak evrensel ayarlara dön plugin.jabberaccregwizz.DISABLE_JINGLE=Jingle'ı (XMPP ile sesli ve videolu aramalar) devredışı bırak -# mailbox -plugin.mailbox.OUTGOING=Giden Mesajlar -plugin.mailbox.INCOMING=Gelen Mesajlar -plugin.mailbox.WAIT_TIME=Arama sesli mesaja gönderilene kadar beklet -plugin.mailbox.MAX_MESSAGE_TIME=Maksimum gelen mesaj süresi -plugin.mailbox.CONFIRM=Onayla -plugin.mailbox.DEFAULTS=Varsayılan -plugin.mailbox.MAILBOX=Mail kutusu - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=MSN servise bağlanmak ve sohbet etmek için protokol. -plugin.msnaccregwizz.USERNAME=E-mail adresi: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Kullanıcı Adı ve Şifre - # plugin manager plugin.pluginmanager.INSTALL=Yükle plugin.pluginmanager.UNINSTALL=Kaldır -plugin.pluginmanager.UPDATE=Güncelle plugin.pluginmanager.PLUGINS=Eklentiler plugin.pluginmanager.URL=Adresi plugin.pluginmanager.CHOOSE_FILE=Dosya Seç @@ -1032,7 +941,6 @@ plugin.sipaccregwizz.SERVER_PORT=Sunucu portu plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxy port plugin.sipaccregwizz.PREFERRED_TRANSPORT=Tercih edilen taşıma -plugin.sipaccregwizz.ADVANCED_OPTIONS=Gelişmiş ayarlar plugin.sipaccregwizz.PROXY_OPTIONS=Proxy seçenekleri plugin.sipaccregwizz.PROXY_AUTO=Proxy i otomatik ayarla plugin.sipaccregwizz.ENABLE_PRESENCE=Durum Bilgisini(SIMPLE) aktif et @@ -1049,8 +957,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Otomatik: RTP ve Inband arasında otomatik seçim plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP bilgisi plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=KAYDOL -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Varsayılan sunucu ayarlarının üzerine yaz plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Aramaları şifrelemeyi aktif et plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Sinyal protokolünde ZRTP desteğini belirt plugin.sipaccregwizz.AUTH_NAME=Yetki ismi @@ -1068,16 +974,16 @@ plugin.sipaccregwizz.VOICEMAIL=Sesli posta plugin.sipaccregwizz.MWI=Mesaj bekleniyor (MWI) plugin.sipaccregwizz.VOICEMAIL_URI=Sesli posta Abonelik URI plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Sesli posta kontrol URI -plugin.sipaccregwizz.NOT_SAME_PASSWORD=Şifrenler biribiri ile uyumlu değil -plugin.sipaccregwizz.NO_CERTIFICATE=(düzenli kimlik bilgilerini kullan) +plugin.sipaccregwizz.NOT_SAME_PASSWORD= (sıradan yetkilendirme kullan) +plugin.sipaccregwizz.NO_CERTIFICATE= (sıradan yetkilendirme kullan) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP işareti +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Kapat(yalnızca RTP/AVP işareti) plugin.sipaccregwizz.SAVP_OPTION_1=Zorunlu (yalnızca RTP/SAVP öner ve kabul et) plugin.sipaccregwizz.SAVP_OPTION_2=İsteğe bağlı(önce RTP/SAVP öner, sonra RTP/AVP ) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=S-Descriptor etkinleştir (SDES veya SRTP olarakta bilinir) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Devredeki şifreleme protokollerini ve öncelik sırasını seç (üstteki protokol önce gelir): plugin.sipaccregwizz.CIPHER_SUITES=Şifre takımlarını etkinleştir -plugin.sipaccregwizz.SECURITY_WARNING=
    {0} ZRTP ile tüm çağrılarınızı otomatik olarak güvene +plugin.sipaccregwizz.SECURITY_WARNING=
    {0} tüm çağrılarınızı otomatik olarak ZRTP ile güvenli hale getirecek ve güvenli bağlantı kurulduğunda her iki tarafta da bir bildirim görünecek. Aşağıdaki ayarları yalnızca ne olduklarını biliyorsanız düzenlemelisiniz.
    plugin.sipaccregwizz.SHOW_ADVANCED=Gelişmiş şifreleme ayarları plugin.sipaccregwizz.ZRTP_OPTION=ZRTP seçeneği plugin.sipaccregwizz.SDES_OPTION=SDes seçeneği @@ -1088,15 +994,6 @@ plugin.skinmanager.DEFAULT_SKIN=Varsayılan tema plugin.skinmanager.ADD_NEW_SKIN=Yeni tema ekle plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Programın varsayılan teması -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=SSH üzerinden uzaktaki makinalara bağlanırken kullanılan bir protokol. -plugin.sshaccregwizz.USERNAME=Hesap ID: -plugin.sshaccregwizz.IDENTITY_FILE=Kimlik Dosyası: -plugin.sshaccregwizz.KNOWN_HOSTS=Bilinen Servis Sağlayıcılar -plugin.sshaccregwizz.OPTIONAL=İsteğe bağlı -plugin.sshaccregwizz.ACCOUNT_DETAILS=Hesap Detayları - # status update plugin.autoaway.AUTO_STATUS=Otomatik olarak uzakta plugin.autoaway.ENABLE_CHANGE_STATUS=Uzaktayken durumu değiştir @@ -1141,27 +1038,11 @@ plugin.whiteboard.DESELECT=Seçme plugin.whiteboard.DELETE=Sil plugin.whiteboard.PROPERTIES=Özellikler -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Yahoo! servisine bağlanmak ve sohbet etmek için kullanılan bir protokol. -plugin.yahooaccregwizz.USERNAME=Kullanıcı adı: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Kullanıcı ID ve Şifre - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Zeroconf(Bonjour) servis protokolü -plugin.zeroaccregwizz.FIRST_NAME=İsim: -plugin.zeroaccregwizz.LAST_NAME=Soyisim: -plugin.zeroaccregwizz.EMAIL=E-mail adresi: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Bonjour kişilerini hatırla -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Kullanıcı adı ve Şifre -plugin.zeroaccregwizz.USERID=Kullanıcı ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Google Talk protokolü plugin.googletalkaccregwizz.USERNAME=Google Talk kullanıcı adı -plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Eğer Google Talk hesabınız yoksa, bu butona tıklayarak yeni bir tane alabilirsiniz. +plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Eğer Google Talk hesabınız yoksa,
    bu butona tıklayarak yeni bir tane alabilirsiniz. plugin.googletalkaccregwizz.NEW_ACCOUNT_TITLE=Google Talk yeni hesap kaydı # iptel accregwizz @@ -1170,19 +1051,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, IP telekomüniskasyon por plugin.iptelaccregwizz.USERNAME=Kullanıcı adı plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=iptel.org'a abone ol -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=Internet arama ve sohbet +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Kullanıcı adı plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Şifreyi tekrar giriniz plugin.sip2sipaccregwizz.EMAIL=Email adresi -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Servis hakkında yardım için
    http://wiki.sip2sip.info 'yu ziyaret ediniz -plugin.sip2sipaccregwizz.EMAIL_NOTE=Email adresi sesli mesaj göndermek, kaçırılan aramaların hatırlatmaları ve unutulan şifre için kullanılacaktır. -plugin.sip2sipaccregwizz.INFO_NOTE=Servis hakkında yardım için ziyaret ediniz
    http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Varolan sip2sip.info hesabı -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Bedava sip2sip.info hesabı oluştur - -# ippi accregwizz +plugin.sip2sipaccregwizz.EMAIL_NOTE=Email adresiniz sesli mesaj göndermek, cevapsız çağrı
    hatırlatmaları ve unutulan şifre için kullanılacaktır. plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Anlık Mesajlaşma plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Servis hakkında yardım için
    http://ippi.fr 'yu ziyaret ediniz @@ -1191,6 +1064,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Varolan ippi hesabı plugin.ippiaccregwizz.CREATE_ACCOUNT=Bedava ippi hesabı oluştur # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Sohbet penceresini kapat plugin.keybindings.CHAT_COPY=Kopyala plugin.keybindings.CHAT_CUT=Kes @@ -1213,9 +1087,9 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=İsim plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Ana kısayol plugin.keybindings.globalchooser.SHORTCUT_SECOND=İkinci kısayol plugin.keybindings.globalchooser.PRESS_BTN=Kısayolu atamak için bas -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Bekleniyor plugin.keybindings.globalchooser.ENABLE_SPECIAL=Özel tuş tanımlamayı etkinleştir plugin.keybindings.PLUGIN_NAME=Tuş bağlayıcıları +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Sohbet plugin.keybindings.MAIN=Ana plugin.keybindings.GLOBAL=Genel kısayollar @@ -1243,6 +1117,7 @@ plugin.notificationconfig.tableheader.SOUND=Bildirim aygıtından bir ses oynat plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Geri oynatma aygıtından bir ses oynat plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=PC speaker aygıtından bir ses oynat plugin.notificationconfig.tableheader.DESCRIPTION=Olayın tanımı +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Gelen arama plugin.notificationconfig.event.SecurityMessage=Güvenlik mesajı plugin.notificationconfig.event.IncomingFile=Gelen dosya @@ -1340,6 +1215,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultProfile=Kodlama yapılacak varsayılan profil: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Baz Profil impl.neomedia.configform.H264.defaultProfile.main=Ana Profil impl.neomedia.configform.H264.preferredKeyFrameRequester=Anahtarları talep etmek için seçilen yöntem: @@ -1368,7 +1244,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Şuanki şifre: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Yeni şifre giriniz: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Şifreyi tekrar giriniz: plugin.securityconfig.masterpassword.MP_TITLE=Ana Şifre -plugin.securityconfig.masterpassword.MP_NOT_SET=(ayarlanmamış) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Doğru ana şifreyi girmediniz. Lütfen tekrar deneyiniz. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Ana şifre doğru değil! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Şifre değiştirilemedi @@ -1384,7 +1259,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Şifre plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(bilinmeyen) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(şifre çözülemiyor) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Kayıtlı Şifreler -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Sil plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Hepsini sil plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Bütün şifreleri silmek istiyor musunuz? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Bütün şifreleri sil @@ -1403,7 +1277,7 @@ plugin.otr.menu.REFRESH_OTR=Özel konuşmayı tazele plugin.otr.menu.AUTHENTICATE_BUDDY=Arkadaşı onayla plugin.otr.menu.WHATS_THIS=Bu nedir plugin.otr.menu.CB_AUTO=Otomatik olarak özel mesajlaşmayı başlat -plugin.otr.menu.CB_AUTO_ALL=Otomatik olarak özel mesajlaşmayı başlat +plugin.otr.menu.CB_AUTO_ALL=Tüm kişilerle özel mesajlaşmayı otomatik olarak başlat plugin.otr.menu.CB_ENABLE=Özel mesajlaşmayı aktif et plugin.otr.menu.CB_REQUIRE=Özel mesajlaşma iste plugin.otr.menu.CB_RESET=Sıfırla @@ -1448,7 +1322,6 @@ plugin.globalproxy.PROXY_PORT=Proxy Portu plugin.globalproxy.PROXY_USERNAME=Proxy Kullanıcı Adı plugin.globalproxy.PROXY_PASSWORD=Proxy şifresi plugin.globalproxy.DESCRIPTION={0} bundan sonra sizin bağlı olduğunuz ve tekrar bağlandığınız bütün ağlar için yukarıdaki proxy ayarlarını kullanacaktır. \nProxy desteği şu an test aşamasındadır ve sadece bazı bağlantı protokolleri çalışmaktadır Daha fazla bilgi için aşağıdaki tabloyu kontrol ediniz: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1461,7 +1334,7 @@ plugin.reconnectplugin.NETWORK_DOWN=Ağ bağlantısı koptu! plugin.chatconfig.TITLE=Sohbet plugin.chatconfig.replacement.TITLE=Resim/Video: plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Gülücük değişimini etkinleştir -plugin.chatconfig.replacement.REPLACEMENT_TITLE=Resim/Video değişimini etkinleştir +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Resim/Video değişimi plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Aktif et plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Kaynaklar: plugin.chatconfig.spellcheck.TITLE=İmla Klavuzu @@ -1479,7 +1352,6 @@ plugin.provisioning.RESTART_WARNING={0} değişiklikleriniz sonraki programı ye plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=UUID kopyala plugin.provisioning.CLIPBOARD_FAILED=UUID kopyalama başarısız -plugin.provisioning.EXIT_ON_FAIL=Provizyon sağlanamazsa programdan çık plugin.provisioning.CREDENTIALS=Son kaydedilen provizyon bilgileri plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Provizyon şifresini silmek istediğinizden emin misiniz? plugin.provisioning.PROV_FAILED=Provizyonlama başarısız oldu @@ -1546,8 +1418,6 @@ util.dns.DNSSEC_WARNING=
    {0}, sunucuya {1}'den bağ #plugin spellcheck plugin.spellcheck.TITLE=İmla ve Dilbilgisi plugin.spellcheck.MENU=İmla ve Dilbilgisi göster -plugin.spellcheck.LANG=Dil -plugin.spellcheck.EDIT_PERSONAL_DICT=Düzenle plugin.spellcheck.ENABLE_SPELL_CHECK=İmla kontrolünü etkinleştir plugin.spellcheck.dialog.FIND=Sonrakini bul plugin.spellcheck.dialog.REPLACE=Değiştir @@ -1592,5 +1462,5 @@ plugin.phonenumbercontactsource.DISPLAY_NAME=Telefon numaraları # properties editor #Thunderbird address book plugin -plugin.thunderbird.ENABLED=Aktif et -plugin.thunderbird.PHONE_PREFIX=Telefon öneki +plugin.thunderbird.ENABLED=Etkin +plugin.thunderbird.PHONE_PREFIX=Telefon öneki: -- cgit v1.1 From 57c9264a52adbfd6472b451b0e9ccd4a27d6a6fe Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:36 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 423 of 1505 strings translated (163 fuzzy). --- resources/languages/resources_sk.properties | 122 ++++++++-------------------- 1 file changed, 35 insertions(+), 87 deletions(-) diff --git a/resources/languages/resources_sk.properties b/resources/languages/resources_sk.properties index 70ccefb..72e4f3c 100644 --- a/resources/languages/resources_sk.properties +++ b/resources/languages/resources_sk.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Ja service.gui.ACCOUNT_REGISTRATION_WIZARD=Sprievodca registráciou účtu service.gui.ACCOUNTS=Účty service.gui.ADD=&Pridať -service.gui.ADD_ACCOUNT=Pridať účet service.gui.ADD_CONTACT=&Pridať kontakt service.gui.ADD_AUTHORIZED_CONTACT=Pridať {0} do zoznamu kontaktov service.gui.ADD_CONTACT_TO_CONTACTLIST=Pridať kontakt do zoznamu kontaktov @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Chyba pri pridávaní kontaktu service.gui.ADD_CONTACT_EXIST_ERROR=Kontakt {0} už existuje vo vašom zozname kontaktov. service.gui.ADD_CONTACT_NETWORK_ERROR=Server neodpovedal na požiadávku pridania kontaktu: {0} service.gui.ADD_CONTACT_NOT_SUPPORTED=Nepodarilo sa pridať kontakt s ID: {0}. Nepodporovaná operácia. -service.gui.ADD_CONTACT_IDENTIFIER=Do pola nižšie zadajte identifikátor kontaktu, ktorý chcete pridať. -service.gui.ADD_CONTACT_WIZARD=Sprievodca pridaním kontaktu service.gui.ADD_CONTACT_NOT_CONNECTED=Na pridanie kontaktu musíte byť pripojený. Prosím prihláste sa na zvolenú službu a skúste znova. service.gui.ADD_GROUP_LOCAL_ERROR=Nepodarilo sa pridať skupinu: {0}. Problém nastal počas lokálnej vstup/výstup operácie. service.gui.ADD_GROUP_EXIST_ERROR=Skupina {0} už existuje vo vašom zozname kontaktov. Zvoľte iný názov. service.gui.ADD_GROUP_NET_ERROR=Nepodarilo sa pridať skupinu: {0}. Problém nastal kvôli chybe v sieti. Prosím skontrolujte sieťové pripojenie a skúste znova. service.gui.ADD_GROUP_ERROR=Nepodarilo sa pridať skupinu: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Názov skupiny musí byť zadaný. -service.gui.ADD_GROUP=Vytvoriť skupinu -service.gui.ADD_SUBCONTACT=&Pridať subkontakt service.gui.ADDRESS=Adresa service.gui.ADMINISTRATOR=administrátor service.gui.ADVANCED=&Pokročilé -service.gui.ALL=&Všetko service.gui.ALL_CONTACTS=&Všetky kontakty service.gui.ALTERNATE_ADDRESS=Alternatívna adresa service.gui.APPLY=&Použiť @@ -65,7 +70,6 @@ service.gui.AT=o service.gui.AUTHORIZE=&Autorizovať service.gui.AUTHORIZATION_ACCEPTED=kontakt prijal vašu žiadosť o autorizáciu. service.gui.AUTHENTICATION_FAILED=Nepodarilo sa prihlásiť pre {0}. Zadali ste nesprávne heslo. -service.gui.AUTHENTICATION_REQUESTED=Požadované prihlásenie service.gui.AUTHENTICATION_REQUESTED_SERVER=Server {0} vyžaduje prihlásenie. service.gui.AUTHENTICATION_REJECTED=kontakt zamietol vašu žiadosť o autorizáciu. service.gui.AUTHENTICATION_WINDOW_TITLE={0} prihlásenie @@ -107,26 +111,24 @@ service.gui.CHANGE_NICKNAME_LABEL=Do políčka nižšie zadajte novú prezívku. service.gui.CHANGE_NICKNAME_ERROR=Chyba pri zmene prezývky service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Prezývka už existuje service.gui.CHANGE_VIDEO_QUALITY=Zmeniť kvalitu vzdialeného videa -service.gui.CHAT_CONFERENCE_LABEL=Konferencia service.gui.CHAT_ROOM_ALREADY_JOINED=K miestnosti {0} ste už pripojený. service.gui.CHAT_ROOM_CONFIGURATION=Nastavenia miestnosti {0} service.gui.CHAT_ROOM_CONFIGURATION_FAILED=Nepodarilo sa získať formulár nastavenia miestnosti {0}. +service.gui.CHAT_ROOM_CONFIGURATION_FORBIDDEN=Nebolo možné získať konfiguračný formulár pre {0} chat miestnosť. Iba majitelia chat miestnosti môžu vidieť a zmeniť konfiguračný formulár. service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED=Chyba pri odosielaní formuláru nastavenia miestnosti {0}. +service.gui.CHAT_ROOM_CONFIGURATION_MEMBERS_EDIT_TITLE=Uprav členský zoznam service.gui.CHAT_ROOM_USER_JOINED=sa pripojil(a) {0} service.gui.CHAT_ROOM_USER_LEFT=opustil(a) {0} service.gui.CHAT_ROOM_USER_KICKED=bol(a) vykopnutý z {0} service.gui.CHAT_ROOM_USER_QUIT=sa odpojil(a) {0} -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Vymaže vybranú miestnosť zo zoznamu uložených miestností. service.gui.CHAT_ROOM_NAME=Názov miestnosti service.gui.CLEAR_CUSTOM_MESSAGES=Vymazať vlastné správy service.gui.ROOM_NAME=Miestnosť -service.gui.AUTOJOIN=Automaticky pripojiť service.gui.CHANGE_PASSWORD=Zmeniť heslo service.gui.CHAT_ROOM_NAME_INFO=Do poľa nižšie zadajte názov miestnosti, ktorú chcete vytvoriť. service.gui.CHAT_ROOM_NOT_EXIST=Miestnosť {0} nebola nájdená na serveri {1}. Prosím skontrolujte názov miestnosti. service.gui.CHAT_ROOM_NOT_CONNECTED=Musíte byť prihlásený aby ste sa mohli pripojiť k miestnosti {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Musíte byť prihlásený aby ste mohli opustiť miestnosť. -service.gui.CHAT_ROOM_NOT_JOINED=Musíte byť pripojený k miestnosti aby ste s ňou mohli vykonávať ďalšie operácie. service.gui.CHAT_ROOM_OPTIONS=Možnosti miestnosti service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Na pripojenie k miestnosti {0} je potrebná registrácia. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Miestnosť {0} vyžaduje heslo. @@ -140,21 +142,17 @@ service.gui.CLEAR=Vymazať service.gui.CLOSE=&Zavrieť service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Pred menej než dvoma sekundami ste prijali novú správu. Naozaj chcete zavrieť tento chat? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Prebieha prenos súborov. Chcete ich zrušiť? -service.gui.CONFIRM=Potvrdiť service.gui.CONNECTED_STATUS=Pripojený service.gui.CONNECTING=Pripája sa... service.gui.CONNECTING_STATUS=Pripája sa service.gui.CONNECTING_EARLY_MEDIA_STATUS=Pripája sa* service.gui.CONNECTION=Pripojenie -service.gui.CONNECTION_FAILED_MSG=Pripojenie k serveru zlyhalo: Užívateľské meno: {0}, Názov serveru: {1}. Skontrolujte, prosím, svoje nastavenia alebo sa obráťte na správcu siete pre ďalšie informácie. service.gui.CONNECTION_EXPIRED_MSG=Momentálne ste odpojení od serveru {0}. service.gui.CONTACT_NAME=ID alebo číslo -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Zvolený {0} kontakt nepodporuje telefonovanie. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Zvolený {0} kontakt nepodporuje konferenčný chat. service.gui.CONTACT_PAUSED_TYPING={0} prestal(a) písať... service.gui.CONTACT_TYPING={0} píše správu... service.gui.CONTACT_INFO=&Informácie o kontakte -service.gui.CONTACTLIST=Zoznam kontaktov service.gui.CONTACTS=Kontakty service.gui.COPY=&Kopírovať service.gui.COPY_LINK=Kopírovať &odkaz @@ -163,13 +161,10 @@ service.gui.CREATE_CHAT_ROOM=&Vytvoriť miestnosť... service.gui.CREATE_CHAT_ROOM_ERROR=Nepodarilo sa vytvoriť miestnosť {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Sprievodca vytváraním miestnosti service.gui.CREATE_CONFERENCE_CALL=&Vytvoriť konferenčný hovor... -service.gui.CREATE_CONFERENCE_CHAT=&Vytvoriť konferenčný chat... service.gui.CREATE_GROUP=&Vytvoriť skupinu... service.gui.CREATE_GROUP_NAME=Do poľa nižšie zadajte názov skupiny, ktorú chcete vytvoriť. -service.gui.CREATE_FIRST_GROUP_WIZARD=Váš zoznam kontaktov neobsahuje žiadnu skupinu. Prosím vytvorte najprv skupinu (Súbor/Vytvoriť skupinu). service.gui.CONTACT_INFO_NOT_SUPPORTED=Tento kontakt nepodporuje informácie z webu service.gui.CUT=&Vystrihnúť -service.gui.DATE=Dátum service.gui.DELETE=Vymazať service.gui.DENY=&Zamietnuť service.gui.DESKTOP_SHARING_WARNING=Naozaj chcete zdielať obrazovku?
    Stlačením OK umožníte všetkým účastníkom hovoru vidieť vašu obrazovku. @@ -179,7 +174,6 @@ service.gui.DISCONNECTED_STATUS=Odpojený service.gui.DND_STATUS=Nerušiť service.gui.DO_NOT_ASK_AGAIN=Nepýtať sa znovu service.gui.DO_NOT_SHOW_AGAIN=Túto správu už nezobrazovať -service.gui.DOWNLOAD_NOW=&Stiahnúť teraz service.gui.DRAG_FOR_SHARING=Potiahnite sem to čo chcete zdielať... service.gui.DURATION=trvanie service.gui.EDIT=&Upraviť @@ -196,7 +190,6 @@ service.gui.ERROR_WAS=Chyba bola: {0} service.gui.ESTIMATED_TIME=Predpokladaný čas: service.gui.EVENTS=Udalosti service.gui.EXIT=&Ukončiť -service.gui.EXTENDED_CRITERIA=Rozšírené hľadanie service.gui.GENERAL=Všeobecný service.gui.GENERAL_ERROR=Všeobecná chyba service.gui.GROUP_NAME=Názov skupiny @@ -252,7 +245,6 @@ service.gui.HIDE_MAIN_WINDOW=
    Kliknutím na tlačidlo X nevypne aplikáciu, service.gui.HISTORY=&História service.gui.HISTORY_CONTACT=História - {0} service.gui.HOME=Domov -service.gui.HOUR=Hodina service.gui.IDENTIFIER=Identifikátor service.gui.IGNORE=Ignorovať service.gui.INSERT_SMILEY=Vložiť smajlík @@ -271,9 +263,6 @@ service.gui.INVITE_CONTACT_TO_CALL=Pozvať kontakty na hovor service.gui.INVITE_REASON=Dôvod pozvania service.gui.IS_CALLING=volá... service.gui.IS_NOW={0} je teraz {1} -service.gui.JITSI_WARNING=SIP Communicator bol nedávno premenovaný na Jitsi.
    Ak chcete aby vaša verzia ostala aktuálna, stiahnite si Jitsi teraz.

    Ospravedlňujeme sa za všetky nepríjemnosti, ktoré vám to mohlo spôsobiť.

    Jitsi Dev Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator sa premenoval na Jitsi -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Zatvoriť service.gui.JOIN_CHAT_ROOM_TITLE=Pripojiť sa do miestnosti service.gui.JOIN_CHAT_ROOM_NAME=Zadajte prosím názov miestnosti, do ktorej sa chcete pripojiť. service.gui.JOIN_CHAT_ROOM_WIZARD=Sprievodca pripojením k miestnosti @@ -293,7 +282,7 @@ service.gui.NAME=Meno service.gui.NEW_ACCOUNT=Pridať nový účet service.gui.NO=Nie service.gui.OPEN=Otvoriť -service.gui.OPTIONS=Voliteľné +service.gui.OPTIONS=Nastavenia service.gui.chat.role.ADMINISTRATOR=administrátor service.gui.PASSWORD=Heslo service.gui.PASSWORD_CHANGE_FAILURE=Zmena hesla bola neúspešná @@ -306,7 +295,7 @@ service.gui.RENAME_CONTACT=Premenovať kontakt service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Kliknite na tlačidlo na zobrazenie všetkých chat miestností vo vybranom servery. Následne vyberte tú, do ktorej sa chcete zapojiť a stlačte tlačidlo pripojiť. service.gui.SECURITY=Bezpečnosť service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Vyberte chat miestnosť z listu a stlačte ok pre jej pridanie. -service.gui.SETTINGS=Voliteľné +service.gui.SETTINGS=&Nastavenia service.gui.SHOW=Zobraz service.gui.SHOW_CONTACT_LIST_TOOL_TIP=Kliknite tu pre vypnutie historie a zobrazenie vášho kontaktu zoznamov. service.gui.SHOW_MORE=ukázať viac... @@ -317,7 +306,6 @@ service.gui.YES=Áno service.gui.NEW=Nový service.gui.SHOW_LOCAL_VIDEO_BUTTON_TOOL_TIP=Zobraziť/skryť lokálne video service.gui.SHOW_HIDE_PEERS_TOOL_TIP=Zobraziť/skryť účastníkov rozhovoru -service.gui.UPDATE=Aktualizovať service.gui.VIDEO_PHONE=Video @@ -325,13 +313,16 @@ service.gui.VIDEO_PHONE=Video service.gui.callinfo.MEDIA_STREAM_RTP=RTP service.gui.callinfo.MEDIA_STREAM_SRTP=RTP +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_PUB_KEY=Verejný klúč: service.gui.AUTO_ANSWER_LABEL=Automatická odpoveď service.gui.AUTO_ANSWER_VIDEO=Video -service.gui.security.NO_VIDEO=HD video -service.gui.security.COMPARE_WITH_PARTNER=Porovnajte údaje s partnerom a kliknite na "zámok" pre potvrdenie. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Porovnajte s partnerom: {0} @@ -340,9 +331,6 @@ service.gui.avatar.imagepicker.CANCEL=Zrušiť -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -352,21 +340,21 @@ service.gui.avatar.imagepicker.CANCEL=Zrušiť # LDAP impl.ldap.CONFIG_FORM_TITLE=ICE nastavenie impl.ldap.GENERAL=Všeobecný -impl.ldap.NEW=Nový impl.ldap.EDIT=upraviť -impl.ldap.REMOVE=Odstrániť impl.ldap.ENABLED=Povoliť impl.ldap.CANCEL=Zrušiť impl.ldap.SERVER_PORT=Port impl.ldap.PASSWORD=Heslo impl.ldap.MAIL_FIELD_EXAMPLE=E-mail: +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts -impl.googlecontacts.NEW=Nový impl.googlecontacts.EDIT=upraviť -impl.googlecontacts.REMOVE=Odstrániť impl.googlecontacts.ENABLED=Povoliť impl.googlecontacts.CANCEL=Zrušiť impl.googlecontacts.PASSWORD=Heslo @@ -391,19 +379,16 @@ plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=V prípade že nemáte AIM účet # branding plugin.branding.ABOUT_MENU_ENTRY=&O programe -# Dict protocol -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informácie o RSS účte - -# facebookaccregwizz -plugin.facebookaccregwizz.USERNAME=Užívateľské meno: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Používateľské meno a heslo # generalconfig plugin.generalconfig.AUTO_START=Zapnúť automaticky {0} pri štarte alebo reštarte plugin.generalconfig.GROUP_CHAT_MESSAGES=Správy skupinových konverzácií v jednom okne plugin.generalconfig.LOG_HISTORY=Ukladaj históriu konverzácií plugin.generalconfig.HISTORY_SIZE=posledných správ v nových konverzáciách +plugin.generalconfig.BRING_WINDOW_TO_FRONT=Preniesť okno s konverzáciou do popredia plugin.generalconfig.CHECK_FOR_UPDATES=Skontrolovať aktualizácie pri štarte +plugin.generalconfig.LEAVE_CHATROOM_ON_WINDOW_CLOSE=Opusť chat miestnosti po zatvorení okna +plugin.generalconfig.SHOW_RECENT_MESSAGES=Zobraz posledné konverzácie (závisí na histórii konverzácií) plugin.generalconfig.SIP_CALL_CONFIG=SIP plugin.generalconfig.RESTORE=Obnoviť štandardné @@ -417,32 +402,16 @@ plugin.ircaccregwizz.USERNAME_AND_PASSWORD=ID a heslo # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=SIP protokol -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID a heslo plugin.jabberaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Vytvoriť voľný SIP účet plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Vaše heslá sa nezhodujú. -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Pokročilé nastavenia plugin.jabberaccregwizz.EXISTING_ACCOUNT=Existujúci SIP účet plugin.jabberaccregwizz.ALLOW_NON_SECURE=Povoliť nezabezpečené spojenia plugin.jabberaccregwizz.AUDIO=Zvuk plugin.jabberaccregwizz.VIDEO=Video -# mailbox -plugin.mailbox.OUTGOING=Odchádzajúca správa: -plugin.mailbox.INCOMING=Prichádzajúce správy: -plugin.mailbox.CONFIRM=Potvrdiť -plugin.mailbox.DEFAULTS=Východzie -plugin.mailbox.MAILBOX=Poštová schránka - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protokol pre pripojenie k službe MSN. -plugin.msnaccregwizz.USERNAME=E-mail: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID a heslo - # plugin manager plugin.pluginmanager.INSTALL=Inštalovať plugin.pluginmanager.UNINSTALL=Odinštalovať -plugin.pluginmanager.UPDATE=Aktualizovať plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=Vybrať súbor plugin.pluginmanager.SYSTEM=Systém @@ -459,7 +428,6 @@ plugin.sipaccregwizz.PROTOCOL_NAME=SIP plugin.sipaccregwizz.PROTOCOL_DESCRIPTION=SIP protokol plugin.sipaccregwizz.USERNAME_AND_PASSWORD=Používateľské meno a heslo plugin.sipaccregwizz.PROXY_PORT=Proxy port -plugin.sipaccregwizz.ADVANCED_OPTIONS=Pokročilé nastavenia plugin.sipaccregwizz.PROXY_OPTIONS=Nastavenia proxy plugin.sipaccregwizz.PROXY_AUTO=Nastaviť proxy automaticky plugin.sipaccregwizz.PRESENCE_OPTIONS=Nastavenia Prítomnosti @@ -468,7 +436,6 @@ plugin.sipaccregwizz.KEEP_ALIVE_METHOD=Metóda pre udržiavanie spojenia plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=Interval udržiavania spojenia plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=Medzi 1 a 3600 sekundami plugin.sipaccregwizz.DTMF_METHOD=Metóda DTMF -plugin.sipaccregwizz.REGISTER=REGISTER plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Povoliť podporu pre šifrovanie hovorov plugin.sipaccregwizz.AUTH_NAME=Meno pre autorizáciu plugin.sipaccregwizz.DISPLAY_NAME=Zobraziť meno @@ -479,6 +446,7 @@ plugin.sipaccregwizz.CLIST_TYPE=Typ plugin.sipaccregwizz.XCAP_USER=Používateľ plugin.sipaccregwizz.XCAP_PASSWORD=Heslo plugin.sipaccregwizz.NOT_SAME_PASSWORD=Vaše heslá sa nezhodujú. +#used from SecurityPanel # skin manager plugin.skinmanager.SKINS=Vzhľady @@ -486,10 +454,6 @@ plugin.skinmanager.DEFAULT_SKIN=Štandardný vzhľad plugin.skinmanager.ADD_NEW_SKIN=Pridať nový vzhľad... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Predvolený vzhľad aplikácie. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.OPTIONAL=Voliteľné - # status update plugin.autoaway.ENABLE_CHANGE_STATUS=Zmeniť status keď som preč @@ -528,18 +492,6 @@ plugin.whiteboard.GRID=Mriežka plugin.whiteboard.DELETE=Vymazať plugin.whiteboard.PROPERTIES=Vlastnosti -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protokol pre pripojenie k službe MSN. -plugin.yahooaccregwizz.USERNAME=Užívateľské meno: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID a heslo - -# zero accregwizz -plugin.zeroaccregwizz.FIRST_NAME=Krstné meno: -plugin.zeroaccregwizz.LAST_NAME=Priezvisko: -plugin.zeroaccregwizz.EMAIL=E-mail: -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID a heslo - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Google Talk protokol @@ -550,16 +502,14 @@ plugin.googletalkaccregwizz.NEW_ACCOUNT_TITLE=Google Talk registrácia nového # iptel accregwizz plugin.iptelaccregwizz.USERNAME=Užívatelské meno -# sip2sip accregwizz +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Užívatelské meno plugin.sip2sipaccregwizz.EMAIL=E-mailová adresa -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Vytvoriť voľný SIP účet - -# ippi accregwizz plugin.ippiaccregwizz.EXISTING_ACCOUNT=Existujúci SIP účet plugin.ippiaccregwizz.CREATE_ACCOUNT=Vytvoriť voľný SIP účet # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Zavrieť okno chatu plugin.keybindings.CHAT_COPY=Kopírovať plugin.keybindings.CHAT_CUT=Vystrihnúť @@ -576,6 +526,7 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Meno plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primárna klávesová skratka plugin.keybindings.globalchooser.SHORTCUT_SECOND=Sekundárna klávesová skratka plugin.keybindings.globalchooser.PRESS_BTN=Stlačte kláves pre nastavenie skratky +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Hlavný @@ -594,6 +545,7 @@ plugin.notificationconfig.BROWSE_PROGRAM=Vybrať program plugin.notificationconfig.tableheader.ENABLE=Povoliť alebo zakázať túto funkciu plugin.notificationconfig.tableheader.EXECUTE=Spustiť program plugin.notificationconfig.tableheader.DESCRIPTION=Opis udalosti +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Prichádzajúci hovor plugin.notificationconfig.event.SecurityMessage=Bezpečnostná správa plugin.notificationconfig.event.IncomingFile=Prichádzajúci súbor @@ -642,6 +594,7 @@ impl.media.configform.VIDEO_RESET=Obnoviť východzie nastavenia impl.neomedia.configform.AUDIO=Zvuk impl.neomedia.configform.VIDEO=Video +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.main=Hlavný impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTP @@ -662,7 +615,6 @@ plugin.securityconfig.masterpassword.SAVED_PASSWORDS=Uložené heslá... plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Súčastné heslo: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Zadajte nové heslo: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Znovu zadajte nové heslo: -plugin.securityconfig.masterpassword.MP_NOT_SET=(nenastavené) plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Zmena hesla bola neúspešná plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS=Zmena hesla bola úspešná plugin.securityconfig.masterpassword.MP_REMOVE_FAILURE=Odstránenie hesla bolo neúspešné @@ -673,7 +625,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Heslo plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(neznámy) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nie je možné dešifrovať) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Uložené heslá -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Odstrániť plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Odstrániť všetky plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Ste si istý, že chcete odstrániť všetky heslá? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Zmazať všetky heslá @@ -721,7 +672,6 @@ plugin.globalproxy.PROXY_PORT=Port proxy plugin.globalproxy.PROXY_USERNAME=Používateľské meno pre proxy plugin.globalproxy.PROXY_PASSWORD=Heslo pre proxy plugin.globalproxy.DESCRIPTION={0} bude používať nastavenia serveru proxy uvedenné vyššie pre všetky siete ku ktorým sa od teraz pripojíte. \nPodpora proxy je momentálne experimentálna a funguje iba s niektorými protokolmi. Pre detaily viď tabuľku dole: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -768,8 +718,6 @@ net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult #plugin spellcheck plugin.spellcheck.TITLE=Pravopis a gramatika plugin.spellcheck.MENU=Ukáž pravopis a gramatiku -plugin.spellcheck.LANG=Jazyk -plugin.spellcheck.EDIT_PERSONAL_DICT=Upraviť plugin.spellcheck.ENABLE_SPELL_CHECK=Zapnúť kontrolu pravopisu plugin.spellcheck.dialog.FIND=Nájsť ďalšie plugin.spellcheck.dialog.REPLACE=Nahradiť -- cgit v1.1 From 54f64298b11950d5fb8ac37da9643879eaa98cd2 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:43 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1470 of 1505 strings translated (4 fuzzy). --- resources/languages/resources_nl.properties | 216 ++++------------------------ 1 file changed, 31 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_nl.properties b/resources/languages/resources_nl.properties index 120c5b3..c08fc0e 100644 --- a/resources/languages/resources_nl.properties +++ b/resources/languages/resources_nl.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Mezelf service.gui.ACCOUNT_REGISTRATION_WIZARD=Account Registratie Gids service.gui.ACCOUNTS=Accounts service.gui.ADD=&Toevoegen -service.gui.ADD_ACCOUNT=Voeg account toe service.gui.ADD_CONTACT=&Voeg contactpersoon toe service.gui.ADD_AUTHORIZED_CONTACT={0} toevoegen aan uw contactenlijst service.gui.ADD_CONTACT_TO_CONTACTLIST=Contactpersoon toevoegen aan mijn contactenlijst @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Contact toevoegingsfout service.gui.ADD_CONTACT_EXIST_ERROR=De contactpersoon {0} bestaat al in uw contactenlijst. service.gui.ADD_CONTACT_NETWORK_ERROR=De server heeft niet geantwoord op het verzoek om contactpersoon met id: {0} toe te voegen. service.gui.ADD_CONTACT_NOT_SUPPORTED=Het toevoegen van contactpersoon met id: {0} is mislukt. Methode wordt niet ondersteund. -service.gui.ADD_CONTACT_IDENTIFIER=Vul in onderstaand veld de identificatie van het contact dat u toe wilt voegen in. -service.gui.ADD_CONTACT_WIZARD=Voeg contact toe gids service.gui.ADD_CONTACT_NOT_CONNECTED=Je dient verbonden te zijn om een contactpersoon toe te voegen. Meld je aan op de geselecteerde provider en probeer opnieuw. service.gui.ADD_GROUP_LOCAL_ERROR=Mislukt om een groep met naam {0} toe te voegen. Het probleem gebeurde tijdens een lokale IO operatie. service.gui.ADD_GROUP_EXIST_ERROR=De groep {0} bestaat al, gelieve een andere naam te kiezen. service.gui.ADD_GROUP_NET_ERROR=Mislukt om de groep met naam {0} toe te voegen. Het probleem gebeurde door een netwerkfout. Bekijk uw verbinding en probeer het opnieuw. service.gui.ADD_GROUP_ERROR=Mislukt om de groep met naam {0} toe te voegen. service.gui.ADD_GROUP_EMPTY_NAME=De naam van de groep mag niet leeg zijn. -service.gui.ADD_GROUP=Maak een groep -service.gui.ADD_SUBCONTACT=&Voeg subcontact toe service.gui.ADDRESS=Adres service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Geavanceerd -service.gui.ALL=&Alles service.gui.ALL_CONTACTS=&Alle contacten service.gui.ALTERNATE_ADDRESS=Alternatief adres service.gui.APPLY=&Toepassen @@ -65,7 +70,6 @@ service.gui.AT=te service.gui.AUTHORIZE=&Autoriseren service.gui.AUTHORIZATION_ACCEPTED={0} heeft uw autorisatieverzoek geaccepteerd. service.gui.AUTHENTICATION_FAILED=Authenticatie mislukt voor {0}. Het opgegeven wachtwoord is niet geldig. -service.gui.AUTHENTICATION_REQUESTED=Authenticatie gevraagd service.gui.AUTHENTICATION_REQUESTED_SERVER=De {0} server heeft uw authenticatie gevraagd. service.gui.AUTHENTICATION_REJECTED={0} heeft uw autorisatieverzoek afgewezen. service.gui.AUTHENTICATION_WINDOW_TITLE={0} authenticatie @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=In onderstaand veld kan je je nieuwe nickname service.gui.CHANGE_NICKNAME_ERROR=Fout tijdens het wijzigen van nickname service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nickname bestaat al service.gui.CHANGE_VIDEO_QUALITY=Wijzig videokwaliteit -service.gui.CHAT_CONFERENCE_LABEL=Conferenties service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}'s conferentie service.gui.CHAT_ROOM_ALREADY_JOINED=U zit al in chatroom {0}. service.gui.CHAT_ROOM_CONFIGURATION={0} chatroom configuratie @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=heeft {0} verlaten service.gui.CHAT_ROOM_USER_KICKED=is buitengesmeten bij {0} service.gui.CHAT_ROOM_USER_QUIT=is gestopt met {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Berichten verzenden is verboden (stem ontnomen) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Slaat de chat ruimte op voor toekomstig gebruik -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Verwijdert de geselecteerde ruimte uit de lijst van opgeslagen ruimtes. service.gui.CHAT_ROOM_NAME=Chatroom naam service.gui.CLEAR_CUSTOM_MESSAGES=Schoon aangepaste berichten op. service.gui.ROOM_NAME=Chatroom -service.gui.AUTOJOIN=Autojoin service.gui.CHANGE_PASSWORD=Wijzig wachtwoord service.gui.CHAT_ROOM_NAME_INFO=Vul de naam van de chatroom in in onderstaand veld. service.gui.CHAT_ROOM_NOT_EXIST=De chatroom {0} is niet gevonden op server {1}. Controleer of de ingevoerde naam correct is. service.gui.CHAT_ROOM_NOT_CONNECTED=U moet ingelogd zijn om deel te nemen aan chatroom {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=U moet ingelogd zijn om een chatroom te verlaten. -service.gui.CHAT_ROOM_NOT_JOINED=U moet deelnemen aan een chatroom om er verdere operaties mee te kunnen doen. service.gui.CHAT_ROOM_OPTIONS=Chat room opties. service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=De {0} chatroom verplicht registratie voor u deel kunt nemen. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=De {0} chatroom heeft een wachtwoord gevraagd. @@ -151,22 +150,18 @@ service.gui.CLEAR=Wissen service.gui.CLOSE=&Sluiten service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=U heeft minder dan 2 seconden geleden een nieuw bericht ontvangen. Weet u zeker dat u deze chat wilt sluiten? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=U heeft actieve bestandsoverdrachten. Weet u zeker dat u deze wilt annuleren? -service.gui.CONFIRM=Bevestig service.gui.CONNECTED_STATUS=Verbonden service.gui.CONNECTING=Verbinden... service.gui.CONNECTING_STATUS=Verbinden service.gui.CONNECTING_EARLY_MEDIA_STATUS=Verbinden* service.gui.CONNECTION=Verbinding -service.gui.CONNECTION_FAILED_MSG=Verbinding mislukt voor de volgende account: Gebruikersnaam: {0}, Servernaam: {1}. Controleer uw netwerkverbinding, of neem contact op met uw beheerder voor meer informatie. service.gui.CONNECTION_EXPIRED_MSG=U bent momenteel niet meer verbonden met de {0} server. service.gui.CONTACT_NAME=ID of nummer -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Het gekozen {0} contact ondersteunt geen telefonie. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Het gekozen {0} contact ondersteunt geen chat conferenties. service.gui.CONTACT_PAUSED_TYPING={0} heeft het typen gepauzeerd service.gui.CONTACT_TYPING={0} is een bericht aan het typen service.gui.CONTACT_TYPING_SEND_FAILED=oh-oh ... we konden {0} niet vertellen dat je aan het typen bent service.gui.CONTACT_INFO=&Contact info -service.gui.CONTACTLIST=Contactenlijst service.gui.CONTACTS=Contacten service.gui.COPY=&Kopiëren service.gui.COPY_LINK=&Link kopiëren @@ -176,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Creëer een chatroom... service.gui.CREATE_CHAT_ROOM_ERROR=Mislukt om chatroom {0} te creëren. service.gui.CREATE_CHAT_ROOM_WIZARD=Creëer chatroom gids service.gui.CREATE_CONFERENCE_CALL=&Creëer een conference call... -service.gui.CREATE_CONFERENCE_CHAT=&Creëer een conference chat... service.gui.CREATE_GROUP=&Creëer groep... service.gui.CREATE_GROUP_NAME=Vul de naam van de te creëren groep in in onderstaand veld. -service.gui.CREATE_FIRST_GROUP_WIZARD=Uw contactenlijst bevat geen groepen. Maak eerst een groep (Bestand/Creëer groep). service.gui.CREATE_VIDEO_BRIDGE=Maak een &videobrug... service.gui.CREATE_VIDEO_BRIDGE_MENU=Maak een &videobrug service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Maak / bezoek videoconferentie service.gui.CREATE_VIDEO_CONFERENCE=Maak een nieuwe videoconferentie voor deze chatruimte service.gui.CONTACT_INFO_NOT_SUPPORTED=Dit contact ondersteunt geen web contactinformatie. service.gui.CUT=&Knippen -service.gui.DATE=Datum service.gui.DELETE=Verwijderen service.gui.DENY=&Afwijzen service.gui.DESKTOP_SHARING_WARNING=Weet u zeker dat u schermdeling wilt starten?
    Als u op OK klikt zal iedereen in dit gesprek uw scherm zien. @@ -197,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Niet verbonden service.gui.DND_STATUS=Niet storen service.gui.DO_NOT_ASK_AGAIN=Niet opnieuw vragen service.gui.DO_NOT_SHOW_AGAIN=Toon dit bericht niet opnieuw -service.gui.DOWNLOAD_NOW=&Download nu service.gui.DRAG_FOR_SHARING=Sleep hier alles wat u wilt delen... service.gui.DURATION=duur service.gui.DESTROY_CHATROOM=Verwijder de chatruimte @@ -218,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Foutmelding ontvangen van {0} service.gui.ESTIMATED_TIME=Geschatte tijd: service.gui.EVENTS=Gebeurtenissen service.gui.EXIT=&Exit -service.gui.EXTENDED_CRITERIA=Uitgebreide criteria service.gui.GENERAL=Algemeen service.gui.GENERAL_ERROR=Algemene fout service.gui.GROUP_NAME=Groepsnaam @@ -260,7 +250,6 @@ service.gui.FONT_ITALIC=Cursief service.gui.FONT_SIZE=Grootte service.gui.FONT_STYLE=Stijl service.gui.FONT_UNDERLINE=Onderlijnen -service.gui.FROM={0} van {1} service.gui.GRANT_OWNERSHIP=Geef eigenaarsrecht... service.gui.GRANT_ADMIN=Geef administratorrecht... service.gui.GRANT_MODERATOR=Geef moderatorrecht @@ -286,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Weet je zeker dat je alle lokaal opgeslag service.gui.HISTORY_REMOVE_ERROR=Fout tijdens het verwijderen van lokaal opgeslagen berichten. service.gui.HOME=Thuis service.gui.HOME_PAGE=Thuispagina -service.gui.HOUR=Uur service.gui.ICE=ICE service.gui.IDENTIFIER=Identificatie service.gui.IGNORE=&Negeren @@ -310,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Nodig contactpersonen uit voor videob service.gui.INVITE_REASON=Uitnodiginsreden service.gui.IS_CALLING={0} belt ... service.gui.IS_NOW={0} is nu {1} -service.gui.JITSI_WARNING=SIP Communicator is hernoemd naar Jitsi.
    Als u een recente versie wilt behouden, download Jitsi dan nu.

    We bieden onze excuses aan voor eventuele ongemakken die dit met zich meebrengt.

    Het Jitsi Ontwikkelaars Team -service.gui.JITSI_WARNING_TITLE=SIP Communicator wordt Jitsi service.gui.JOIN=&Binnengaan service.gui.JOIN_AS=&Binnengaan als service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Neem deel aan een bestaande videoconferentie service.gui.JOIN_VIDEO=Neem deel aan video -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Sluiten service.gui.JOB_TITLE=Werktitel service.gui.JOIN_CHAT_ROOM=Werktitel service.gui.JOIN_CHAT_ROOM_TITLE=Ga chatroom binnen @@ -329,7 +314,6 @@ service.gui.KICK_FAILED=Buitengooien mislukt service.gui.KICK_FAILED_GENERAL_ERROR=Mislukt om {0} buiten te gooien. Er is een serverfout gebeurd. service.gui.KICK_FAILED_NOT_ALLOWED=Mislukt om {0} buiten te gooien. De eigenaar en administrator van de chatroom kunnen niet buitengegooid worden. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Mislukt om {0} buiten te gooien. U heeft geen privileges om dat te doen. -service.gui.LAST=Laatste service.gui.LAST_NAME=Achternaam service.gui.LEAVE=&Verlaten service.gui.LIMIT_REACHED_FOR_IP=U heeft teveel bestaande registraties van het lokale IP-adres en de server {0} accepteert geen extra registraties. @@ -349,7 +333,6 @@ service.gui.MESSAGE=Bericht service.gui.MISSED_CALLS_TOOL_TIP=Gemiste oproepen van: service.gui.MISSED_CALLS_MORE_TOOL_TIP= en {0} meer service.gui.MODERATOR=moderator -service.gui.MORE=Toon meer service.gui.MORE_LABEL=Meer service.gui.MOVE=Verplaats service.gui.MOVE_SUBCONTACT=&Verplaats contact @@ -358,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Het gekozen contact is dezelfde als \n de ges service.gui.MOVE_SUBCONTACT_QUESTION=Weet u zeker dat u {0} naar {1} wilt verplaatsen? service.gui.MOVE_TO_GROUP=&Verplaats naar groep service.gui.MOVE_CONTACT=Verplaats Contact -service.gui.MOVE_CONTACT_ERROR=&Contact kan niet verplaatst worden service.gui.MSG_DELIVERY_FAILURE=Bovenstaand bericht kon niet afgeleverd worden. service.gui.MSG_DELIVERY_NOT_SUPPORTED=Het protocol dat je gebruikt ondersteunt geen offline berichten. Je kunt proberen de contactpersoon te bereiken via een ander protocol of wachten tot hij/zij online komt. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Er is een interne fout opgetreden. Dit is waarschijnlijk een bug. Gelieve dit te rapporteren op http://www.jitsi.org/index.php/Development/BugsAndIssues. @@ -372,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=U dient verbonden te zijn voor u bericht service.gui.MULTIPLE_LOGINS=U bent meer dan één keer ingelogd met hetzelfde account. De account: Gebruikersnaam: {0}, Servernaam{1} is momenteel niet verbonden. service.gui.MY_CHAT_ROOMS=Chatruimte toevoegen service.gui.MY_CHAT_ROOMS_TITLE=Chatruimte toevoegen -service.gui.MUTE=Mute service.gui.MUTUALLY_ON_HOLD_STATUS=Wederzijds on hold service.gui.NAME=Naam service.gui.NETWORK=Netwerk @@ -404,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=NietInContactenlijst service.gui.SD_QUALITY=Standaard kwaliteit service.gui.OFFLINE=Offline service.gui.OK=&OK -service.gui.OLDER_CALLS=Oudere telefoongesprekken service.gui.ONLINE=Online service.gui.OPEN=Open service.gui.OPEN_FILE_FROM_IMAGE=Dubbelklik om bestand te openen. @@ -416,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Openen bij activiteit service.gui.OPEN_ON_MESSAGE=Alleen openen bij berichten service.gui.OPEN_ON_IMPORTANT_MESSAGE=Alleen openen bij belangrijke berichten service.gui.OR=of -service.gui.OR_ENTER_PHONE_NUMBER=Of voer hier een telefoonnummer in... service.gui.ORGANIZATION=Organisatie service.gui.OTHER=Anders service.gui.chat.role.OWNER=Eigenaar @@ -442,7 +421,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' voor suggesties service.gui.PRESS_FOR_CALL_INFO=Klik voor gespreksinformatie service.gui.PRESS_TO_OPEN_CRM=Klik om CRM-applicatie te openen service.gui.PREVIOUS=Vorig -service.gui.PREVIOUS_TOOLTIP=Blader door oudere conversaties service.gui.PRINT=&Print service.gui.PROACTIVE_NOTIFICATION=is een bericht aan het schrijven service.gui.PROBLEMS_ENCOUNTERED=Problemen tegengekomen @@ -458,7 +436,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=U heeft te snel de verbinding met de ser service.gui.RE_REQUEST_AUTHORIZATION=&Opnieuw om autorisatie vragen service.gui.REFERRED_STATUS=Verwezen service.gui.REJECT=&Weigeren -service.gui.REMIND_ME_LATER=Herinner mij later service.gui.REMEMBER_PASSWORD=Wachtwoord herinneren service.gui.REMOVE=&Verwijderen service.gui.REMOVE_ACCOUNT=&Verwijder account @@ -484,29 +461,20 @@ service.gui.REVOKE_ADMIN=Beheerder intrekken service.gui.REVOKE_MODERATOR=Moderator intrekken service.gui.REVOKE_MEMBERSHIP=Deelname intrekken service.gui.REVOKE_VOICE=Stemgebruik intrekken -service.gui.ROOT_GROUP=Hoofd groep service.gui.SAVE=&Opslaan -service.gui.SAVE_AS_DEFAULT=Als standaard opslaan service.gui.SEARCH=&Zoeken service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Klik op de knop hieronder om alle bestaande chat rooms te tonen in de geselecteerde server. Selecteer vervolgens degene waar u deel aan wilt nemen en klik op de deelname knop. service.gui.SEARCH_STRING_CONTACT_SOURCE=Gezocht contactpersoon service.gui.SECURITY=Beveiliging -service.gui.SELECT_ACCOUNT=Selecteer account service.gui.SELECT_COLOR=Selecteer kleur service.gui.SELECT_GROUP=Selecteer groep -service.gui.SELECT_GROUP_WIZARD_MSG=De lijst hieronder bevat alle groepen in uw contactenlijst. Selecteer degene waar u het nieuwe contact wilt toevoegen. service.gui.SELECT_NO_GROUP=Geen groep -service.gui.SELECT_GROUP_WIZARD=Specificeer groep service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=De lijst hieronder bevat alle accounts die de meervoudige gebruikers chat functionaliteit gebruiken. Selecteer degene die u wilt gebruiken om uw chat room te maken. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=De lijst hieronder bevat alle geregistreerde accounts. Selecteer degene die u wilt gebruiken om te communiceren met het nieuwe contact. -service.gui.SELECT_PROVIDERS_WIZARD=Selecteer account service.gui.SELECT_VIDEO_CONFERENCE=Kies videoconferentie service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Kies een chatruimte uit de lijst en druk op OK om deze toe te voegen. service.gui.SEND=&Versturen service.gui.SEND_FILE=Verstuur &bestand -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Er is geen informatie voor dit contact. service.gui.SEND_MESSAGE=&Verstuur een bericht -service.gui.SEND_AS_SMS=Verstuur als SMS service.gui.SEND_PRIVATE_MESSAGE=Persoonlijk bericht versturen service.gui.SEND_SMS=&Verstuur SMS service.gui.SEND_SMS_DETAILS=Denk er aan dat u het nummer in internationaal formaat moet invoeren, bijvoorbeeld beginnend met +44 voor het Verenigd Koninkrijk, +447777000000 @@ -545,7 +513,6 @@ service.gui.STREET=Straat service.gui.SUBJECT=Onderwerp service.gui.SUMMARY=Samenvatting service.gui.TELEPHONY=Telefonie -service.gui.TODAY=Vandaag service.gui.TOOLS=&Gereedschap service.gui.TRANSFER=&Overdracht service.gui.TO=&Aan: @@ -555,7 +522,6 @@ service.gui.TRANSFER_CALL_TO=Overdragen aan: service.gui.TRANSPARENCY_NOT_ENABLED=Transparantie is niet ondersteund door uw huidige configuratie. service.gui.TYPE_YOUR_REQUEST=Typ uw verzoek hier service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Het is niet gelukt om de videokwaliteit voor dit gesprek te wijzigen. -service.gui.UNMUTE=Mute opheffen service.gui.USER_IDENTIFIER=Gebruiker identificator: service.gui.USER_EXISTS_ERROR=Deze gebruiker bestaat reeds op het geselecteerde netwerk. Kies een andere gebruiker of netwerk. service.gui.USERNAME_NULL=Voer uw gebruikersnaam en wachtwoord in. @@ -568,7 +534,6 @@ service.gui.USE_PROVISIONING=Gebruik online provisioning. service.gui.VALUE=Waarde service.gui.VIDEO_CALL=&Video gesprek service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Weergeven service.gui.VIEW_HISTORY=Bekijk &geschiedenis service.gui.VIEW_SMILEYS=Bekijk &smileys @@ -588,9 +553,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Volume aanpassen service.gui.WAITING_AUTHORIZATION=Wacht op autorisatie service.gui.WARNING=Waarschuwing service.gui.YES=Ja -service.gui.YESTERDAY=Gisteren -service.gui.EXISTING_ACCOUNT_ERROR=Het opgegeven account is reeds geïnstalleerd. -service.gui.NEW_MAIL=U heeft één nieuw email bericht
    Van: {0} {1}
    Onderwerp: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=U heeft een nieuw email bericht in uw {0} inbox:
    service.gui.NEW_GMAIL_MANY_HEADER=U heeft {2} nieuwe email berichten ontvangen in uw {0} inbox:
    service.gui.NEW_GMAIL_FOOTER=één ongelezen bericht in uw inbox.
    @@ -614,7 +576,6 @@ service.gui.SECURITY_ERROR=Beveiligingsfout service.gui.SPEED=Snelheid: service.gui.SILENT_MEMBER=stil lid service.gui.NON_SECURE_CONNECTION=Er kan geen beveiligde verbinding gemaakt worden voor account {0}. Als je verbinding wilt maken met een niet-beveiligide server, vink dan "Niet-beveiligde verbindingen toestaan" aan in accountinstellingen. -service.gui.UPDATE=Update service.gui.MOBILE_PHONE=Mobiel service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Werk @@ -649,12 +610,10 @@ service.gui.callinfo.CALL_INFORMATION=Telefoongesprekinformatie service.gui.callinfo.CALL_IDENTITY=Identiteit service.gui.callinfo.PEER_COUNT=Aantal deelnemers service.gui.callinfo.IS_CONFERENCE_FOCUS=Focus van conferentie -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Encryptie ingeschakeld service.gui.callinfo.CALL_TRANSPORT=Transportprotocol service.gui.callinfo.CALL_DURATION=Duur van het telefoongesprek service.gui.callinfo.TLS_PROTOCOL=TLS-protocol service.gui.callinfo.TLS_CIPHER_SUITE=TLS encryptiesuite -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Certificatenketen van de TLS server service.gui.callinfo.TLS_CERTIFICATE_CONTENT=De inhoud van het TLS servercertificaat wordt hieronder getoond. service.gui.callinfo.VIEW_CERTIFICATE=Certificaat weergeven service.gui.callinfo.CODEC=Codec / Frequentie @@ -664,7 +623,6 @@ service.gui.callinfo.AUDIO_INFO=Audio-info service.gui.callinfo.VIDEO_INFO=Video-info service.gui.callinfo.LOCAL_IP=Lokaal IP-adres / poort service.gui.callinfo.REMOTE_IP=Tegenpartij IP / Poort -service.gui.callinfo.BANDWITH=Bandbreedte service.gui.callinfo.LOSS_RATE=Verliesratio service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -674,10 +632,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Sleuteluitwisselingsprotocol service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE kandidaat uitgebreid type service.gui.callinfo.ICE_STATE=ICE verwerkingsstatus + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Kandidaten verzamelen service.gui.callinfo.ICE_STATE.RUNNING=Verbindingscontroles service.gui.callinfo.ICE_STATE.COMPLETED=Voltooid service.gui.callinfo.ICE_STATE.FAILED=Gefaald + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Lokaal IP-adres / poort service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Lokaal reflexief IP-adres / poort service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Lokaal doorgestuurd IP-adres / poort @@ -698,11 +659,12 @@ service.gui.ALWAYS_TRUST=Dit certificaat altijd vertrouwen service.gui.CERT_DIALOG_TITLE=Controleer certificaat service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} kan de identiteit van de server niet verifiëren tijdens de verbindingspoging
    naar {1}. Het certificaat is niet vertrouwd, wat betekent dat de serveridentiteit niet
    automatisch kan worden vastgesteld. Wilt u verder gaan met het opzetten van deze verbinding?

    Voor meer informatie, klik op ''Certificaat weergeven''. service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} kan de identiteit van de server niet verifiëren tijdens verbindingspoging
    naar {1}. Het certificaat is niet vertrouwd, wat betekent dat de serveridentiteit niet
    automatisch kan worden vastgesteld. Wilt u verder gaan met het opzetten van deze verbinding?

    Voor meer informatie, klik op ''Toon Certificaat''. -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} kan de identiteit van de verbinding makende cliënt niet vaststellen.

    Het certificaat is niet vertrouwd, wat betekent dat de cliëntidentiteit niet
    automatisch kan worden vastgesteld. Wilt u deze verbinding accepteren?

    Voor meer informatie, klik op ''Toon certificaat''. service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} kan de identiteit van de verbinding makende cliënt niet vaststellen.

    Het certificaat is niet vertrouwd, wat betekent dat de cliëntidentiteit niet
    automatisch kan worden vastgesteld. Wilt u deze verbinding accepteren?

    Voor meer informatie, klik op ''Certificaat weergeven''. service.gui.CONTINUE_ANYWAY=Toch doorgaan service.gui.CERT_INFO_CHAIN=Certificatenketen: service.gui.CERT_INFO_ISSUED_TO=Uitgegeven aan + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Algemene naam: service.gui.CERT_INFO_O=Organisatie: service.gui.CERT_INFO_C=Land Naam: @@ -721,12 +683,10 @@ service.gui.CERT_INFO_SIGN_ALG=Handtekeningsalgorithme service.gui.CERT_INFO_PUB_KEY_INFO=Info over publieke sleutel service.gui.CERT_INFO_ALG=Algorithme: service.gui.CERT_INFO_PUB_KEY=Publieke sleutel: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Exponent: service.gui.CERT_INFO_KEY_SIZE=Sleutelgrootte: service.gui.CERT_INFO_SIGN=Handtekening: -service.gui.CONTINUE=Verder service.gui.SHOW_CERT=Weergeven certificaat service.gui.HIDE_CERT=Verbergen certificaat @@ -749,12 +709,9 @@ service.gui.security.SECURE_AUDIO=Beveiligde audio service.gui.security.AUDIO_NOT_SECURED=Audio niet beveiligd service.gui.security.SECURE_VIDEO=Beveiligde video service.gui.security.VIDEO_NOT_SECURED=Video niet beveiligd -service.gui.security.NO_VIDEO=Geen video -service.gui.security.CIPHER=Codering: {0} service.gui.security.CALL_SECURED_TOOLTIP=Telefoongesprek beveiligd. Klik hier voor meer informatie. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Telefoongesprek niet beveiligd. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Klik hier om het beveiligingsgeheim te vergelijken met je partner. -service.gui.security.COMPARE_WITH_PARTNER=Vergelijk met uw partner en klik het padlock om te bevestigen. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Vergelijk met je partner: {0} service.gui.security.STRING_COMPARED=Regel vergeleken! @@ -772,20 +729,14 @@ service.gui.avatar.imagepicker.CLICK=Klik en lach service.gui.avatar.imagepicker.IMAGE_FILES=Afbeeldingsbestanden service.gui.avatar.imagepicker.IMAGE_PICKER=Afbeelding service.gui.avatar.imagepicker.IMAGE_SIZE=Afbeeldingsgrootte -service.gui.avatar.imagepicker.INITIALIZING=Initialiseren service.gui.avatar.imagepicker.RESET=Reset service.gui.avatar.imagepicker.SET=Instellen service.gui.avatar.imagepicker.TAKE_PHOTO=Neem een foto -service.gui.avatar.imagepicker.WEBCAM_ERROR=Webcam fout service.gui.security.encryption.required=Encryptie verplicht! service.protocol.ICE_FAILED=Kan verbinding niet tot stand brengen (ICE mislukt en geen relay beschikbaar) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Fout in opslag van SIP contactenlijst impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Resource {0} kan niet gelezen worden. Voor {1} @@ -815,9 +766,7 @@ impl.ldap.QUERY_CUSTOM=Aangepast zoeken impl.ldap.QUERY_CUSTOM_HINT=Gebruik {0} als plaatsvervanger voor de zoekterm. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Automatisch wildcards toevoegen aan zoekterm impl.ldap.QUERY_PHOTO_INLINE=Foto samen met andere attributen ophalen. -impl.ldap.NEW=Nieuw impl.ldap.EDIT=bewerken -impl.ldap.REMOVE=Verwijderen impl.ldap.ENABLED=Actief impl.ldap.SERVER_NAME=Servernaam impl.ldap.SERVER_NAME_EXAMPLE=Mijn LDAP server @@ -850,6 +799,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Telefoonvoorvoegsel impl.ldap.PHONE_PREFIX_EXAMPLE=Vb.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Adresboek plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=MacOSX adresboek doorzoeken inschakelen @@ -864,9 +817,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Maak Outlook de standaard email # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google contacten -impl.googlecontacts.NEW=Nieuw impl.googlecontacts.EDIT=bewerken -impl.googlecontacts.REMOVE=Verwijderen impl.googlecontacts.ENABLED=Actief impl.googlecontacts.ACCOUNT_NAME=Accountnaam impl.googlecontacts.SAVE=Opslaan @@ -905,11 +856,8 @@ plugin.accountinfo.ORGANIZATION=Naam van organisatie: plugin.accountinfo.JOB_TITLE=Werktitel: plugin.accountinfo.ABOUT_ME=Over Mij: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Gebruikersfoto's plugin.accountinfo.GLOBAL_ICON=Globaal icoon gebruiken plugin.accountinfo.LOCAL_ICON=Gebruik dit icoon: -plugin.accountinfo.CHANGE=Veranderen -plugin.accountinfo.ONLY_MESSAGE=Alleen berichten # connection info plugin.connectioninfo.TITLE=Verbindingsinformatie @@ -929,49 +877,12 @@ plugin.aimaccregwizz.USERNAME=AIM schermnaam: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Scherm naam en wachtwoord plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registreer nieuw account plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Heeft u geen AIM account, klik dan op deze knop om er een aan te maken. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Overschrijf standaard server opties # branding plugin.branding.ABOUT_WINDOW_TITLE=Over {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Instant Messaging -plugin.branding.LOADING=Laden plugin.branding.ABOUT_MENU_ENTRY=&Over -plugin.branding.WELCOME_MESSAGE=
    Het {1} wordt momenteel actief ontwikkeld. De versie die u nu draait is slechts experimenteel en werkt MOGELIJK niet zoals verwacht. Raadpleeg {2} voor meer informatie.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Alle rechten voorbehouden. Bezoek http://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi wordt gedistribueerd onder de voorwaarden van de LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Woordenboeken -plugin.dictaccregwizz.ANY_DICTIONARY=Willekeurig woordenboek -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Willekeurig woordenboek van {0} -plugin.dictaccregwizz.FIRST_MATCH=Eerste resultaat -plugin.dictaccregwizz.NO_MATCH=Geen resultaat -plugin.dictaccregwizz.MATCH_RESULT=Geen definities gevonden voor ''{0}'', misschien bedoeld u:\n -plugin.dictaccregwizz.INVALID_DATABASE=Het huidige woordenboek ''{0}'' bestaat niet langer op de server. -plugin.dictaccregwizz.INVALID_STRATEGY=De huidige strategie is niet beschikbaar op de server. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Het Dict dienst protocol -plugin.dictaccregwizz.HOST=Host -plugin.dictaccregwizz.SERVER_INFO=Serverinformatie -plugin.dictaccregwizz.STRATEGY_SELECTION=Strategie selectie -plugin.dictaccregwizz.STRATEGY_LIST=Lijst van strategieën: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Zoek binnen strategieën -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategieën worden gebruikt vergelijkbare woorden te vinden, wanneer een vertaling niet gevonden is, dankzij verschillende methodes. Bijvoorbeeld de Prefix strategie zoekt woorden die beginnen met het woord dat u zou willen vertalen. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict account informatie -plugin.dictaccregwizz.FIRST_ACCOUNT=Deze wizard maakt uw eerste Dict account aan op dict.org.\n\nU kunt nieuwe woordenboeken toevoegen door naar de Account Registratie Wizard te gaan. Vul het host veld met het woordenboek dat u toe wilt voegen. -plugin.dictaccregwizz.THREAD_CONNECT=Probeert verbinding te maken met de server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Verbindingspoging mislukt, dit is geen dict server of de server is offline -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Ophalen strategieën -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Geen strategie gevonden op de server -plugin.dictaccregwizz.POPULATE_LIST=Lijst aan het vullen -plugin.dictaccregwizz.CLOSING_CONNECTION=Verbinding aan het sluiten - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Om Facebook Chat te kunnen gebruiken, is het noodzakelijk een ''Gebruikersnaam'' aan te maken
    in uw ''Account instellingen'' pagina op Facebook.


    Aantekening: Wanneer u een gebruikersnaam aangemaakt heeft, moet u uitloggen van de webpagina >br> en kan het even duren voordat u in staat bent in te loggen met uw nieuwe gebruikersnaam!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Het Facebook Chat protocol -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Gebruikersnaam: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Gebruikersnaam en wachtwoord: + # generalconfig plugin.generalconfig.AUTO_START={0} automatisch starten wanneer de computer opnieuw opstart @@ -982,9 +893,6 @@ plugin.generalconfig.SHOW_HISTORY=Toon plugin.generalconfig.HISTORY_SIZE=recente berichten in nieuwe chats plugin.generalconfig.SEND_MESSAGES_WITH=Verstuur berichten met: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Breng chat venster naar de voorgrond -plugin.generalconfig.ERROR_PERMISSION=U heeft niet voldoende privileges om automatisch starten te verwijderen. -plugin.generalconfig.TRANSPARENCY=Transparantie -plugin.generalconfig.ENABLE_TRANSPARENCY=Transparantie aanzetten plugin.generalconfig.DEFAULT_LANGUAGE=Interfacetaal plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Uw wijzigingen worden effectief na de volgende herstart. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0} % vertaald @@ -1043,13 +951,13 @@ plugin.ircaccregwizz.EXAMPLE_SERVER=Vb.: chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Gebruik beveiligde verbinding plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Contactpersoonaanwezigheid inschakelen plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Aanwezigheid in chatruimte inschakelen +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} authenticatie +plugin.ircaccregwizz.SASL_USERNAME=Gebruikersnaam # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Het XMPP protocol plugin.jabberaccregwizz.USERNAME=XMPP-gebruikersnaam plugin.jabberaccregwizz.PASSWORD_CONFIRM=Bevestig wachtwoord -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID en wachtwoord plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Verbind met server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Activeer keep alive @@ -1065,13 +973,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Commentaar plugin.jabberaccregwizz.RESOURCE=Bron plugin.jabberaccregwizz.AUTORESOURCE=Genereer bron automatisch plugin.jabberaccregwizz.PRIORITY=Prioriteit -plugin.jabberaccregwizz.XMPP_ERROR=XMPP fout plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Onbekende XMPP-fout. ({0}) Controleer of de servernaam correct is. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=De wachtwoorden komen niet overeen. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Overschrijf standaard server opties -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Geavanceerde opties plugin.jabberaccregwizz.USE_ICE=Gebruik ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Gebruik Google's Jingle/ICE (experimenteel) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Ontdek STUN/TURN servers automatisch plugin.jabberaccregwizz.SUPPORT_TURN=Ondersteun TURN plugin.jabberaccregwizz.TURN_USERNAME=TURN gebruikersnaam @@ -1099,11 +1003,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Berichtkopiën uitschakelen plugin.jabberaccregwizz.DTMF_AUTO=Auto: Kies automatisch tussen RTP en in-band plugin.jabberaccregwizz.SERVER_OPTIONS=Server-opties plugin.jabberaccregwizz.CHANGE_PASSWORD=Wijzig account-wachtwoord -plugin.jabberaccregwizz.NEW_PASSWORD=Nieuw wachtwoord -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Bevestig wachtwoord plugin.jabberaccregwizz.PORT_FIELD_INVALID=Vul een geldig poortnummer in om door te gaan. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Het account moet ingelogd zijn om het wachtwoord te kunnen wijzigen. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Het wachtwoord is leeg. plugin.jabberaccregwizz.TLS_REQUIRED=De verbinding is niet beveiligd. De wachtwoordwijziging wordt niet uitgevoerd. plugin.jabberaccregwizz.PASSWORD_CHANGED=Het wachtwoord is succesvol gewijzigd. plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Het wijzigen van het wachtwoord wordt op deze XMPP-server niet ondersteund. @@ -1117,25 +1018,9 @@ plugin.jabberaccregwizz.RESET=Reset plugin.jabberaccregwizz.RESET_DESCRIPTION=Resetten naar globale instellingen plugin.jabberaccregwizz.DISABLE_JINGLE=Jingle uitschakelen (audio en video gesprekken met XMPP). -# mailbox -plugin.mailbox.OUTGOING=Uitgaand bericht: -plugin.mailbox.INCOMING=Binnenkomende berichten: -plugin.mailbox.WAIT_TIME=Wachttijd voordat telefoongesprek naar Voicemail wordt doorverwezen -plugin.mailbox.MAX_MESSAGE_TIME=Maximale binnenkomende gesprekstijd -plugin.mailbox.CONFIRM=Bevestig -plugin.mailbox.DEFAULTS=Standaardinstellingen -plugin.mailbox.MAILBOX=Mailbox - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Een protocol om verbinding te maken en gesprekken te voeren op de MSN dienst. -plugin.msnaccregwizz.USERNAME=Email: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID en wachtwoord - # plugin manager plugin.pluginmanager.INSTALL=Installeren plugin.pluginmanager.UNINSTALL=Deïnstalleren -plugin.pluginmanager.UPDATE=Update plugin.pluginmanager.PLUGINS=Plug-ins plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=Selecteer bestand @@ -1160,7 +1045,6 @@ plugin.sipaccregwizz.SERVER_PORT=Server poort plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Proxy poort plugin.sipaccregwizz.PREFERRED_TRANSPORT=Voorkeurstransport -plugin.sipaccregwizz.ADVANCED_OPTIONS=Geavanceerde opties plugin.sipaccregwizz.PROXY_OPTIONS=Proxy opties plugin.sipaccregwizz.PROXY_AUTO=Configureer proxy automatisch plugin.sipaccregwizz.ENABLE_PRESENCE=Activeer aanwezigheid (SIMPLE) @@ -1180,8 +1064,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Auto: Kies automatisch tussen RTP en in-band (gee plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=In-band -plugin.sipaccregwizz.REGISTER=REGISTREREN -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Overschrijf standaard server opties plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Activeer ondersteuning voor gecodeerde telefoongesprekken plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indicatie van ondersteuning voor ZRTP in signaling-protocol plugin.sipaccregwizz.AUTH_NAME=Autorisatienaam @@ -1202,10 +1084,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI voor Voicemail-controle plugin.sipaccregwizz.NOT_SAME_PASSWORD=Uw wachtwoorden komen niet overeen. plugin.sipaccregwizz.NO_CERTIFICATE= (gebruik reguliere authenticatie) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP-indicatie +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Uitgeschakeld (indicatie alleen RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Verplicht (bied aan en accepteer enkel RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Optioneel (biedt RTP/SAVP eerst aan, daarna RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=S-Descriptor inschakelen (staat ook bekend als SDES of SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Kies ingeschakelde encryptieprotocollen en hun prioriteit (bovenste protocol eerst): plugin.sipaccregwizz.CIPHER_SUITES=Ingeschakelde codeersuites: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} zal automatisch proberen al je gesprekken te beveiligen met ZRTP en jullie zullen beide een melding zien en horen als de beveiligide verbinding in stand gebracht is. Je zou de geavanceerde instellingen hieronder alleen moeten wijzigen als je goed weet wat je doet.
    @@ -1219,15 +1101,6 @@ plugin.skinmanager.DEFAULT_SKIN=Standaard skin plugin.skinmanager.ADD_NEW_SKIN=Voeg nieuwe skin toe... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=De standaard skin voor de applicatie. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Een protocol om verbinding te maken met externe machines over SSH. -plugin.sshaccregwizz.USERNAME=Account ID: -plugin.sshaccregwizz.IDENTITY_FILE=Identiteitsbestand: -plugin.sshaccregwizz.KNOWN_HOSTS=Bekende hosts: -plugin.sshaccregwizz.OPTIONAL=Optioneel -plugin.sshaccregwizz.ACCOUNT_DETAILS=Accountdetails - # status update plugin.autoaway.AUTO_STATUS=Automatisch Weg plugin.autoaway.ENABLE_CHANGE_STATUS=Verander status tijdens weg zijn @@ -1275,22 +1148,6 @@ plugin.whiteboard.DESELECT=Deselecteren plugin.whiteboard.DELETE=Verwijderen plugin.whiteboard.PROPERTIES=Eigenschappen -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Een protocol om verbinding te maken en gesprekken te voeren op de Yahoo!-dienst. -plugin.yahooaccregwizz.USERNAME=Gebruikersnaam: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID en wachtwoord: - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Het Zeroconf (Bonjour) dienst protocol. -plugin.zeroaccregwizz.FIRST_NAME=Voornaam: -plugin.zeroaccregwizz.LAST_NAME=Achternaam: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Onthouden Bonjour contacten? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID en wachtwoord -plugin.zeroaccregwizz.USERID=Gebruikers ID - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Het Google Talk protocol @@ -1304,19 +1161,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, het IP Telecommunicatie P plugin.iptelaccregwizz.USERNAME=Gebruikersnaam plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=lid worden van iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP en chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Gebruikersnaam plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Voor wachtwoord opnieuw in plugin.sip2sipaccregwizz.EMAIL=Email adres -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Voor help over deze dienst bezoek
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Het email adres wordt gebruikt om voicemail berichten te versturen,
    gemiste oproep notificaties en om een verloren wachtwoord te herstellen -plugin.sip2sipaccregwizz.INFO_NOTE=Voor help over deze dienst bezoek http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Bestaand ip2sip.info account -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Maak een gratis sip2sip.info account aan - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Instant Messaging plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Voor help over deze dienst bezoek
    http://ippi.fr @@ -1325,6 +1174,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Bestaand ippi account plugin.ippiaccregwizz.CREATE_ACCOUNT=Maak een gratis ippi account aan # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Sluit chat venster plugin.keybindings.CHAT_COPY=Kopiëren plugin.keybindings.CHAT_CUT=Knippen @@ -1347,10 +1197,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Naam plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Primaire sneltoets plugin.keybindings.globalchooser.SHORTCUT_SECOND=Secundaire sneltoets plugin.keybindings.globalchooser.PRESS_BTN=Druk om sneltoets in te stellen -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Wachten plugin.keybindings.globalchooser.PUSH_TO_TALK=Indrukken om te spreken plugin.keybindings.globalchooser.ENABLE_SPECIAL=Detectie van speciale toetsen inschakelen plugin.keybindings.PLUGIN_NAME=Toetsenconfiguratie +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat plugin.keybindings.MAIN=Main plugin.keybindings.GLOBAL=Globale sneltoetsen @@ -1378,6 +1228,7 @@ plugin.notificationconfig.tableheader.SOUND=Speel geluid af via het meldingenapp plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Speel geluid af via afspeelapparaat plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Speel een geluid af via PC speaker-apparaat plugin.notificationconfig.tableheader.DESCRIPTION=Beschrijving van gebeurtenis +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Binnenkomend gesprek plugin.notificationconfig.event.SecurityMessage=Beveiligingsbericht plugin.notificationconfig.event.IncomingFile=Binnenkomend bestand @@ -1479,6 +1330,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Periodieke intra-refresh impl.neomedia.configform.H264.defaultProfile=Standaard profiel om in te coderen: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Baseline impl.neomedia.configform.H264.defaultProfile.high=Hoog impl.neomedia.configform.H264.defaultProfile.main=Algemeen @@ -1509,7 +1361,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Huidig wachtwoord: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Voer nieuw wachtwoord in: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Voer wachtwoord opnieuw in: plugin.securityconfig.masterpassword.MP_TITLE=Hoofd wachtwoord: -plugin.securityconfig.masterpassword.MP_NOT_SET=(niet ingesteld) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=U heeft niet het correcte hoofd wachtwoord ingevoerd. Probeer het opnieuw. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Het hoofd wachtwoord is niet correct! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Wachtwoordwijziging niet geslaagd @@ -1525,7 +1376,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Wachtwoord plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(onbekend) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(kan niet decoderen) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Opgeslagen wachtwoorden -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Verwijderen plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Verwijder alle plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Weet u zeker dat u alle wachtwoorden wilt verwijderen? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Verwijder alle wachtwoorden @@ -1621,7 +1471,6 @@ plugin.globalproxy.PROXY_PORT=Proxy poort plugin.globalproxy.PROXY_USERNAME=Proxy gebruikersnaam plugin.globalproxy.PROXY_PASSWORD=Proxy wachtwoord plugin.globalproxy.DESCRIPTION={0} gebruikt de bovenstaande proxy instellingen voor alle netwerken waarmee u (opnieuw) verbinding maakt vanaf nu.\n Proxy ondersteuning is momenteel experimenteel en werkt alleen met sommige protocollen. Bekijk de tabel hieronder voor meer details: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Ook DNS proxy'en plugin.globalproxy.FWD_DNS_NOTE=Nuttig voor Tor. Dit helpt voorkomen dat DNS verzoeken lekken door alle DNS-verkeer te herleiden naar de Tor-proxy. Herstart nodig. @@ -1659,7 +1508,6 @@ plugin.provisioning.RESTART_WARNING=Merk op dat uw wijzigingen pas van kracht wo plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Kopieer UUID naar klembord plugin.provisioning.CLIPBOARD_FAILED=Kopiëren van UUID naar klembord mislukt -plugin.provisioning.EXIT_ON_FAIL=Sluit de applicatie als provisioning faalt plugin.provisioning.CREDENTIALS=Laatste opgeslagen provisioning-aanmeldgegevens plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Weet je zeker dat je het provisioning-wachtwoord wilt verwijderen? plugin.provisioning.PROV_FAILED=Provisioning is gefaald @@ -1726,8 +1574,6 @@ util.dns.DNSSEC_WARNING=
    {0} heeft geprobeerd om te verbin #plugin spellcheck plugin.spellcheck.TITLE=Spelling en Grammatica plugin.spellcheck.MENU=Toon Spelling en Grammatica -plugin.spellcheck.LANG=Taal -plugin.spellcheck.EDIT_PERSONAL_DICT=&Bewerken plugin.spellcheck.ENABLE_SPELL_CHECK=Spellingscontrole inschakelen plugin.spellcheck.dialog.FIND=Volgende zoeken plugin.spellcheck.dialog.REPLACE=Vervangen -- cgit v1.1 From f1163dbf2225963b557769a130cb2b01bcfbc6cf Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:50 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1470 of 1505 strings translated (4 fuzzy). --- resources/languages/resources_el.properties | 216 ++++------------------------ 1 file changed, 31 insertions(+), 185 deletions(-) diff --git a/resources/languages/resources_el.properties b/resources/languages/resources_el.properties index d9d9292..e60d690 100644 --- a/resources/languages/resources_el.properties +++ b/resources/languages/resources_el.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Εγώ service.gui.ACCOUNT_REGISTRATION_WIZARD=Οδηγός Καταχώρησης Λογαριασμού service.gui.ACCOUNTS=Λογαριασμοί service.gui.ADD=&Προσθήκη -service.gui.ADD_ACCOUNT=Προσθήκη λογαριασμού service.gui.ADD_CONTACT=&Προσθήκη επαφής service.gui.ADD_AUTHORIZED_CONTACT=Πρόσθεσε την/τον {0} στη λίστα των επαφών σου service.gui.ADD_CONTACT_TO_CONTACTLIST=Πρόσθεσε την επαφή στην λίστα των επαφών σου @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Σφάλμα προσθήκης επαφής service.gui.ADD_CONTACT_EXIST_ERROR=Η επαφή {0} υπάρχει ήδη στη λίστα επαφών σας. service.gui.ADD_CONTACT_NETWORK_ERROR=Ο διακομιστής δεν απάντησε στο αίτημα προσθήκης της επαφής με κωδικό: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Αποτυχία προσθήκης της επαφής με κωδικό: {0}. Η λειτουργία δεν υποστηρίζεται. -service.gui.ADD_CONTACT_IDENTIFIER=Εισάγετε στο παρακάτω πεδίο το αναγνωριστικό της επαφής που θέλετε να προσθέσετε. -service.gui.ADD_CONTACT_WIZARD=Οδηγός προσθήκης επαφής service.gui.ADD_CONTACT_NOT_CONNECTED=Θα πρέπει να είστε συνδεδεμένοι για να προσθέσετε μια επαφή. Παρακαλώ συνδεθείτε στον επιλεγμένο παροχέα υπηρεσιών και προσπαθείστε ξανά. service.gui.ADD_GROUP_LOCAL_ERROR=Αποτυχία προσθήκης της ομάδας με όνομα: {0}. Το πρόβλημα προέκυψε κατά τη διάρκεια μίας τοπικής λειτουργίας εισόδου/εξόδου. service.gui.ADD_GROUP_EXIST_ERROR=Η ομάδα {0} υπάρχει ήδη στη λίστα επαφών σας. Παρακαλώ επιλέξτε ένα άλλο όνομα. service.gui.ADD_GROUP_NET_ERROR=Αποτυχία προσθήκης της ομάδας με όνομα: {0}. Το πρόβλημα προέκυψε λόγω αποτυχίας του δικτύου. Παρακαλώ ελέγξτε τη σύνδεσή σας στο δίκτυο και δοκιμάστε ξανά. service.gui.ADD_GROUP_ERROR=Αποτυχία προσθήκης της ομάδας με όνομα: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Το όνομα της ομάδας δεν πρέπει να είναι κενό. -service.gui.ADD_GROUP=Δημιουργία ομάδας -service.gui.ADD_SUBCONTACT=&Προσθήκη υποεπαφής service.gui.ADDRESS=Διεύθυνση service.gui.ADMINISTRATOR=διαχειριστής service.gui.ADVANCED=&Για προχωρημένους -service.gui.ALL=&Όλα service.gui.ALL_CONTACTS=&Όλες οι επαφές service.gui.ALTERNATE_ADDRESS=Εναλλακτική διεύθυνση service.gui.APPLY=&Εφαρμογή @@ -65,7 +70,6 @@ service.gui.AT=σε service.gui.AUTHORIZE=&Εξουσιοδότησε service.gui.AUTHORIZATION_ACCEPTED=Ο/Η {0} αποδέχτηκε το αίτημά σας για εξουσιοδότηση. service.gui.AUTHENTICATION_FAILED=Η ταυτοποίηση απέτυχε για {0}. Ο κωδικός που εισάγατε δεν είναι έγκυρος. -service.gui.AUTHENTICATION_REQUESTED=Άιτηση ταυτοποίησης service.gui.AUTHENTICATION_REQUESTED_SERVER=Ο εξυπηρετητής {0} ζήτησε την ταυτοποίησή σας. service.gui.AUTHENTICATION_REJECTED=Ο χρήστης {0} απέρριψε την αίτηση εξουσιοδότησης που ζητήσατε. service.gui.AUTHENTICATION_WINDOW_TITLE={0} ταυτοποίηση @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Στο παρακάτω πεδίο μπορε service.gui.CHANGE_NICKNAME_ERROR=Παρουσιάστηκε σφάλμα κατα την αλλαγή του ψευδωνύμου service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Το ψευδόνυμο υπάρχει ήδη service.gui.CHANGE_VIDEO_QUALITY=Αλλαγή ποιότητας απομακρυσμένου βίντεο -service.gui.CHAT_CONFERENCE_LABEL=Συνέδρια service.gui.CHAT_CONFERENCE_ITEM_LABEL=Συνέδριο του {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Έχετε ήδη συνδεθεί στο δωμάτιο συζήτησης {0}. service.gui.CHAT_ROOM_CONFIGURATION=ρυθμίσεις του δωματίου συζήτησης {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=απσυνδέθηκε από το {0} service.gui.CHAT_ROOM_USER_KICKED=απομακρύνθηκε από το {0} service.gui.CHAT_ROOM_USER_QUIT=έφυγε από το {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Η αποστολή μηνυμάτων είναι απαγορευμένη (το δικαίωμα ομιλίας σας ανακλήθηκε) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Αποθήκευση του δωματίου συζήτησης για μελλονική χρήση -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Διαγραφή του επιλεγμένου δωματίου συζητήσεων από την λίστα των αποθηκευμένων δωματίων service.gui.CHAT_ROOM_NAME=Όνομα δωματίου συζήτησης service.gui.CLEAR_CUSTOM_MESSAGES=Διαγραφή προσαρμοσμένων μηνυμάτων service.gui.ROOM_NAME=Δωμάτιο συζήτησης -service.gui.AUTOJOIN=Αυτόματη σύνδεση service.gui.CHANGE_PASSWORD=Αλλαγή κωδικού πρόσβασης service.gui.CHAT_ROOM_NAME_INFO=Εισάγετε στο παρακάτω πεδίο το όνομα του δωματίου συζήτησης που θέλετε να δημιουργήσετε. service.gui.CHAT_ROOM_NOT_EXIST=Το δωμάτιο {0} δε βρέθηκε στον εξυπηρετητή {1}. Παρακαλώ επαληθεύστε ότι το όνομα που πληκτρολογήσατε είναι σωστό. service.gui.CHAT_ROOM_NOT_CONNECTED=Πρέπει να είστε συνδεδεμένος για να εισέλθετε στο δωμάτιο συζήτησης {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Πρέπει να είστε συνδεδεμένος για να μπορέσετε να φύγετε από ένα δωμάτιο συζήτησης. -service.gui.CHAT_ROOM_NOT_JOINED=Πρέπει πρώτα να έχετε εισέλθει στο δωμάτιο συζήτησης για να μπορέσετε να εκτελέσετε περαιτέρω ενέργειες με αυτό. service.gui.CHAT_ROOM_OPTIONS=Ρυθμίσεις δωματίου συζήτησης service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Το δωμάτιο συζήτησης {0} απαιτεί εγγραφή για να συνδεθείτε. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Το δωμάτιο συζήτησης {0} ζήτησε κωδικό πρόσβασης. @@ -151,22 +150,18 @@ service.gui.CLEAR=Καθαρισμός service.gui.CLOSE=Κλείσιμ&ο service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Λάβατε ένα νέο μήνυμα πριν από λιγότερο από 2 δευτερόλεπτα. Σίγουρα θέλετε να κλείσετε αυτή τη συζήτηση; service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Υπάρχουν μεταφορές αρχείων σε εξέλιξη. Σίγουρα θέλετε να τις ακυρώσετε; -service.gui.CONFIRM=Επιβεβαίωση service.gui.CONNECTED_STATUS=Συνδεθήκατε service.gui.CONNECTING=Γίνεται σύνδεση... service.gui.CONNECTING_STATUS=Συνδέεται service.gui.CONNECTING_EARLY_MEDIA_STATUS=Γίνεται σύνδεση... service.gui.CONNECTION=Σύνδεση -service.gui.CONNECTION_FAILED_MSG=Η σύνδεση απέτυχε για τον ακόλουθο λογαριασμό: Όνομα χρήστη: {0}, όνομα εξυπηρετητή: {1}. Παρακαλώ ελέγξτε τη σύνδεσή σας στο δίκτυο ή επικοινωνήστε με τον διαχειριστή δικτύου για περισσότερες πληροφορίες. service.gui.CONNECTION_EXPIRED_MSG=Είστε αποσυνδεδεμένος από τον εξυπηρετητή {0}. service.gui.CONTACT_NAME=Κωδικός Ταυτοποίησης ή Αριθμός -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Η επιλεγμένη επαφή {0} δεν υποστηρίζει τηλεφωνία. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Η επιλεγμένη επαφή {0} δεν υποστηρίζει συνδιάσκεψη με chat. service.gui.CONTACT_PAUSED_TYPING=Ο/Η {0} έπαυσε την πληκτρολόγηση του μηνύματος service.gui.CONTACT_TYPING=Ο/Η {0} πληκτρολογεί ένα μήνυμα service.gui.CONTACT_TYPING_SEND_FAILED=Ουπς.. δεν μπορέσαμε να ενημερώσουμε τον/την {0} οτι γράφατε service.gui.CONTACT_INFO=&Πληροφορίες επαφής -service.gui.CONTACTLIST=Λίστα επαφών service.gui.CONTACTS=Επαφές service.gui.COPY=&Αντιγραφή service.gui.COPY_LINK=Αντιγραφή &συνδέσμου @@ -176,17 +171,14 @@ service.gui.CREATE_CHAT_ROOM=&Δημιουργία δωματίου συζήτη service.gui.CREATE_CHAT_ROOM_ERROR=Απέτυχε η δημιουργία του δωματίου συζήτησης {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Οδηγός δημιουργίας δωματίου συζήτησης service.gui.CREATE_CONFERENCE_CALL=&Δημιουργία κλήσης για συνδιάσκεψη... -service.gui.CREATE_CONFERENCE_CHAT=&Δημιουργία συζήτησης για συνδιάσκεψη... service.gui.CREATE_GROUP=&Δημιουργία ομάδας... service.gui.CREATE_GROUP_NAME=Στο παρακάτω πεδίο εισάγετε το όνομα της ομάδας που θέλετε να δημιουργήσετε. -service.gui.CREATE_FIRST_GROUP_WIZARD=Η λίστα επαφών σας δεν περιέχει καμία ομάδα. Παρακαλώ δημιουργήστε πρώτα μία ομάδα (Αρχείο/Δημιουργία ομάδας). service.gui.CREATE_VIDEO_BRIDGE=Δημιουργία ενός &μεταγωγέα βίντεο... service.gui.CREATE_VIDEO_BRIDGE_MENU=Δημιουργία ενός &μεγαγωγέα βίντεο service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Δημιουργία / Σύνδεση τηλεδιάσκεψης service.gui.CREATE_VIDEO_CONFERENCE=Δημιουργία μιας νέας τηλεδιάσκεψης για αυτό το δωμάτιο συζητήσεων service.gui.CONTACT_INFO_NOT_SUPPORTED=Η επαφή αυτή δεν υποστηρίζει web contact info service.gui.CUT=Απο&κοπή -service.gui.DATE=Ημερομηνία service.gui.DELETE=Διαγραφή service.gui.DENY=&Άρνηση service.gui.DESKTOP_SHARING_WARNING=Είστε σίγουρα ότι θέλετε να ξεκινήσετε τον διαμοιρασμό οθόνης;
    Πατώντας ΟΚ θα επιτρέψετε στους συνομιλητές σας να βλέπουν την οθόνη σας. @@ -197,7 +189,6 @@ service.gui.DISCONNECTED_STATUS=Αποσυνδεθήκατε service.gui.DND_STATUS=Μην ενοχλείτε service.gui.DO_NOT_ASK_AGAIN=Μη με ξαναρωτήσεις service.gui.DO_NOT_SHOW_AGAIN=Μην εμφανίσεις ξανά αυτό το μήνυμα -service.gui.DOWNLOAD_NOW=&Κάντε download τώρα service.gui.DRAG_FOR_SHARING=Τραβήξτε εδώ ο,τιδήποτε θέλετε να μοιραστείτε service.gui.DURATION=διάρκεια service.gui.DESTROY_CHATROOM=Διαγράψτε το δωμάτιο συζητήσεων @@ -218,7 +209,6 @@ service.gui.ERROR_RECEIVED_FROM=Λάβαμε ένα σφάλμα από τον/ service.gui.ESTIMATED_TIME=Υπολογιζόμενος χρόνος: service.gui.EVENTS=Συμβάντα service.gui.EXIT=Έ&ξοδος -service.gui.EXTENDED_CRITERIA=Εκτεταμένα κριτήρια service.gui.GENERAL=Γενικά service.gui.GENERAL_ERROR=Γενικό σφάλμα service.gui.GROUP_NAME=Όνομα ομάδος @@ -260,7 +250,6 @@ service.gui.FONT_ITALIC=Πλάγια γράμματα service.gui.FONT_SIZE=Μέγεθος service.gui.FONT_STYLE=Στυλ service.gui.FONT_UNDERLINE=Υπογράμμιση -service.gui.FROM={0} από {1} service.gui.GRANT_OWNERSHIP=Απόδωση κυριότητος service.gui.GRANT_ADMIN=Ανάθεση Διαχειρστού .... service.gui.GRANT_MODERATOR=Ανάθεση διαμεσολαβητή @@ -286,7 +275,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Είστε βέβαιος ότι επιθ service.gui.HISTORY_REMOVE_ERROR=Παρουσιάστηκε σφάλμα κατα την διαγραφή των τοπικά αποθηκευμένα μηνυμάτων. service.gui.HOME=Οικία service.gui.HOME_PAGE=Αρχική σελίδα -service.gui.HOUR=Ώρα service.gui.ICE=ICE service.gui.IDENTIFIER=Αναγνωριστικό service.gui.IGNORE=&Παράβλεψη @@ -310,13 +298,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Πρόσκληση επαφών στ service.gui.INVITE_REASON=Λόγος πρόσκλησης service.gui.IS_CALLING=Ο/Η {0} καλεί... service.gui.IS_NOW=Το {0} είναι τώρα {1} -service.gui.JITSI_WARNING=Ο SIP Communicator άλλαξε πρόσφατα ονομασία στο Jitsi.
    Αν θέλετε η έκδοσή σας να είναι ενημερωμένη, τότε παρακαλώ κατεβάστε το Jitsi τώρα.

    Λυπούμαστε για την ό,ποια ταλαιπωρία που αυτό ίσως σας προκαλεί.

    Η ομάδα ανάπτυξης του Jitsi -service.gui.JITSI_WARNING_TITLE=Ο SIP Communicator έγινε τώρα Jitsi service.gui.JOIN=&Ελάτε να συμμετάσχετε και σεις service.gui.JOIN_AS=Να σ&υμμετέχετε ως service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Συνδεθείτε σε μια προυπάρχουσα τηλεδιάσκεψη service.gui.JOIN_VIDEO=Συνδεθείτε με βίντεο -service.gui.CLOSE_CHAT_ROOM_DIALOG=Κ&λείσιμο service.gui.JOB_TITLE=Τίτλος εργασίας service.gui.JOIN_CHAT_ROOM=&Μπείτε στο Δωμάτιο συνομιλίας chat service.gui.JOIN_CHAT_ROOM_TITLE=Μπείτε στο Δωμάτιο συνομιλίας chat @@ -329,7 +314,6 @@ service.gui.KICK_FAILED=Αποτυχία απόρριψης service.gui.KICK_FAILED_GENERAL_ERROR=Αποτυχία αποκλεισμού του {0}. Σημειώθηκε γενικό σφάλμα στον εξυπηρετητή. service.gui.KICK_FAILED_NOT_ALLOWED=Αποτυχία αποκλεισμού του {0}. Ο ιδιοκτήτης και ο διαχειριστής του δωματίου δεν μπορούν να αποκλειστούν. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Αποτυχία αποκλεισμού του {0}. Δεν έχετε αρκετά δικαιώματα γι' αυτή την ενέργεια. -service.gui.LAST=Τελευταίος/α service.gui.LAST_NAME=Επώνυμο service.gui.LEAVE=&Έξοδος service.gui.LIMIT_REACHED_FOR_IP=Διαθέτετε πάρα πολλές εγγραφές από την τοπική διεύθνση IP και ο διακομιστής {0} δεν σας επιτρέπει να ανοίξετε καμία επιπλέον. @@ -349,7 +333,6 @@ service.gui.MESSAGE=Μήνυμα service.gui.MISSED_CALLS_TOOL_TIP=Αναπάντητες κλήσεις από: service.gui.MISSED_CALLS_MORE_TOOL_TIP= και {0} επιπλέον service.gui.MODERATOR=μεσολαβητής (moderator) -service.gui.MORE=Δείτε περισσότερα service.gui.MORE_LABEL=Περισσότερα service.gui.MOVE=κίνηση service.gui.MOVE_SUBCONTACT=Μ&ετακινείστε την επαφή @@ -358,7 +341,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Η επαφή που επιλέξατε εί service.gui.MOVE_SUBCONTACT_QUESTION=Είστε βέβαιος ότι θέλετε να μετακινήσετε το {0} στο {1}; service.gui.MOVE_TO_GROUP=&Μετακινείστε στην ομάδα service.gui.MOVE_CONTACT=Μετακινείστε την επαφή -service.gui.MOVE_CONTACT_ERROR=&Η επαφή δεν μπορεί να μετακινηθεί service.gui.MSG_DELIVERY_FAILURE=Το παραπάνω μήνυμα δεν ήταν δυνατόν να παραδοθεί service.gui.MSG_DELIVERY_NOT_SUPPORTED=Το πρωτόκολλο που χρησιμοποιείτε δεν υποστηρίζει μηνύματα εκτός σύνδεσης. Μπορείτε να δοκιμάσετε να επικοινωνήσετε με τον/την {0} μέσω ενός άλλου πρωτοκόλλου ή αναμείνατε μέχρι να συνδεθεί. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Σημειώθηκε ένα εσωτερικό σφάλμα. Πρόκειται μάλλον για κάποιο bug. Παρακαλώ αναφέρατέ το εδώ: https://jitsi.org/Development/BugsAndIssues. @@ -372,7 +354,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Θα πρέπει να συνδεθεί service.gui.MULTIPLE_LOGINS=Συνδεθήκατε παραπάνω από μία φορά με τον ίδιο λογαριασμό. Ο εξής λογαριασμός: Όνομα χρήστη: {0}, Όνομα διακομιστή: {1} είναι αυτή τη στιγμή χωρίς σύνδεση. service.gui.MY_CHAT_ROOMS=Προσθήκη ενός δωματίου συζητήσεων service.gui.MY_CHAT_ROOMS_TITLE=Προσθήκη ενός δωματίου συζητήσεων -service.gui.MUTE=Σίγαση service.gui.MUTUALLY_ON_HOLD_STATUS=Κλήση σε κράτηση και από τους 2 συνομιλούντες service.gui.NAME=Όνομα service.gui.NETWORK=Δίκτυο @@ -404,7 +385,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=ΕκτόςΛίσταςΕπαφών service.gui.SD_QUALITY=Κανονική ποιότητα service.gui.OFFLINE=Χωρίς σύνδεση service.gui.OK=&Εντάξει -service.gui.OLDER_CALLS=Παλαιότερες κλήσεις service.gui.ONLINE=Με σύνδεση service.gui.OPEN=Άνοιξε service.gui.OPEN_FILE_FROM_IMAGE=Κάντε διπλό κλικ για να ανοίξετε το αρχείο. @@ -416,7 +396,6 @@ service.gui.OPEN_ON_ACTIVITY=Άνοιγμα όταν υπάρχει δραστη service.gui.OPEN_ON_MESSAGE=Άνοιγμα μόνο όταν υπάρχει κάποιο μύνημα service.gui.OPEN_ON_IMPORTANT_MESSAGE=Άνοιγμα μόνο όταν υπάρχει κάποιο σημαντικό μήνυμα service.gui.OR=ή -service.gui.OR_ENTER_PHONE_NUMBER=Ή πληκτρολογείστε έναν αριθμό τηλεφώνου εδώ... service.gui.ORGANIZATION=Οργανισμός service.gui.OTHER=Άλλο service.gui.chat.role.OWNER=Ιδιοκτήτης @@ -442,7 +421,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS="Enter" για υποδείξεις service.gui.PRESS_FOR_CALL_INFO=Πατήστε για πληροφορίες κλήσης service.gui.PRESS_TO_OPEN_CRM=Κάντε κλίκ για να ανοίξετε την εφαρμογή CRM service.gui.PREVIOUS=Προηγούμενος -service.gui.PREVIOUS_TOOLTIP=Αναζήτηση στις παλαιότερες συνομιλίες service.gui.PRINT=&Εκτύπωση service.gui.PROACTIVE_NOTIFICATION=γράφει ένα μήνυμα service.gui.PROBLEMS_ENCOUNTERED=Βρέθηκαν προβλήματα @@ -458,7 +436,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Συνδεθήκατε και αποσυ service.gui.RE_REQUEST_AUTHORIZATION=Νέα αίτηση εξουσιοδότησης service.gui.REFERRED_STATUS=Ανεφέρθη service.gui.REJECT=&Απόρριψη -service.gui.REMIND_ME_LATER=Υπενθύμισέ μου αργότερα service.gui.REMEMBER_PASSWORD=Κράτα τον Κωδικό Εισόδου στη μνήμη service.gui.REMOVE=&Διαγραφή service.gui.REMOVE_ACCOUNT=&Διαγραφή Λογαριασμού @@ -484,29 +461,20 @@ service.gui.REVOKE_ADMIN=Ανάκληση δικαιωμάτων Διαχειρ service.gui.REVOKE_MODERATOR=Ανάκληση μεσολαβητή (moderator) service.gui.REVOKE_MEMBERSHIP=Ανάκληση ιδιότητος Μέλους service.gui.REVOKE_VOICE=Ανάκληση φωνής -service.gui.ROOT_GROUP=Ομάδα Root service.gui.SAVE=&Αποθήκευση -service.gui.SAVE_AS_DEFAULT=Αποθήκευση ως προεπιλογή service.gui.SEARCH=&Αναζήτηση service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Κάντε κλικ στο παρακάτω κουμπί για να εμφανισθούν όλα τα Δωμάτια Chat στον επιλεχθέντα Διακομιστή. Κατόπιν επιλέξτε εκείνον στον οποίο θέλετε να μπείτε και κάντε κλικ στο κουμπί "Σύνδεση" service.gui.SEARCH_STRING_CONTACT_SOURCE=Αναζητημένη επαφή service.gui.SECURITY=Ασφάλεια -service.gui.SELECT_ACCOUNT=Επιλογή λογαριασμού service.gui.SELECT_COLOR=Επιλογή χρώματος service.gui.SELECT_GROUP=Επιλογή ομάδος -service.gui.SELECT_GROUP_WIZARD_MSG=Ο παρακάτω κατάλογος περιέχει όλες τις ομάδες στον Κατάλογο των επαφών σας. Επιλέξτε εκείνη στην οποία θέλετε να προσθέσετε την Νέα Επαφή. service.gui.SELECT_NO_GROUP=Καμία ομάδα -service.gui.SELECT_GROUP_WIZARD=Επιλέξτε την ομάδα service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Ο παρακάτω κατάλογος περιέχει όλους τους λογαριασμούς που υποστηρίζουν την δυνατότητα για ταυτόχρονο chat από πολλούς χρήστες. Επιλέξτε ποιον θα χρησιμοποιήσετε, για να φτιάξετε το δικό σας δωμάτιο chat. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Ο παρακάτω κατάλογος περιέχει όλους τους καταχωρημένους λογαριασμούς. Επιλέξτε εκείνον που θέλετε να χρησιμοποιείτε, για να επικοινωνείτε με την Νέα Επαφή. -service.gui.SELECT_PROVIDERS_WIZARD=Επιλογή λογαριασμού service.gui.SELECT_VIDEO_CONFERENCE=Επιλέξτε μια τηλεδιάσκεψη service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Επιλέξτε ένα δωμάτιο συζητήσεων από τη λίστα και πατήστε στο OK για να το προσθέσετε. service.gui.SEND=&Αποστολή service.gui.SEND_FILE=Αποστολή &αρχείου -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Δεν υπάρχουν πληροφορίες για αυτή την Επαφή. service.gui.SEND_MESSAGE=&Αποστολή ενός μηνύματος. -service.gui.SEND_AS_SMS=Αποστολή υπό μορφή SMS service.gui.SEND_PRIVATE_MESSAGE=Αποστολή ιδιωτικού μηνύματος service.gui.SEND_SMS=Α&ποστολή SMS service.gui.SEND_SMS_DETAILS=Να θυμάστε ότι πρέπει να καταχωρείτε τον αριθμό με την διεθνή μορφή, πχ. αρχίζοντας με το +30 για την Ελλάδα, +302311250040 @@ -545,7 +513,6 @@ service.gui.STREET=Οδός service.gui.SUBJECT=Θέμα service.gui.SUMMARY=Περίληψη service.gui.TELEPHONY=Τηλεφωνία -service.gui.TODAY=Σήμερα service.gui.TOOLS=&Εργαλεία service.gui.TRANSFER=Μετα&φορά service.gui.TO=@Σε: @@ -555,7 +522,6 @@ service.gui.TRANSFER_CALL_TO=Μεταφορά σε: service.gui.TRANSPARENCY_NOT_ENABLED=Οι τρέχουσες ρυθμίσεις σας δεν υποστηρίζουν την Διαφάνεια. service.gui.TYPE_YOUR_REQUEST=Πληκτρολογείστε το αίτημά σας εδώ service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Δεν ήταν δυνατό να αλλάξει η ποιότητα του βίντεο για αυτή την κλήση. -service.gui.UNMUTE=Διακοπή σίγασης service.gui.USER_IDENTIFIER=Κωδικός ταυτοποίησης Χρήστη: service.gui.USER_EXISTS_ERROR=Αυτός ο χρήστης υπάρχει ήδη στο επιλεγμένο δίκτυο. Παρακαλώ επιλέξτε ένα άλλο δίκτυο. service.gui.USERNAME_NULL=Παρακαλώ συμπληρώστε το όνομα χρήστη και τον κωδικό σας. @@ -568,7 +534,6 @@ service.gui.USE_PROVISIONING=Χρήση απ'ευθείας αρχικοποίη service.gui.VALUE=Τιμή service.gui.VIDEO_CALL=&Κλήση Βίντεο service.gui.VIA=μέσω -service.gui.VIA_SMS=Μέσω SMS service.gui.VIEW=&Εμφάνιση service.gui.VIEW_HISTORY=&Εμφάνιση Ιστορικού service.gui.VIEW_SMILEYS=Εμφάνιση &smileys @@ -588,9 +553,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Ρύθμιση ήχου service.gui.WAITING_AUTHORIZATION=Αναμονή εξουσιοδότησης service.gui.WARNING=Προειδοποίηση service.gui.YES=Ναι -service.gui.YESTERDAY=Χθες -service.gui.EXISTING_ACCOUNT_ERROR=Ο λογαριασμός που ορίσατε είναι ήδη καταχωρημένος. -service.gui.NEW_MAIL='Εχετε νέο Ταχυδρομείο!
    Από: {0} {1}
    Θέμα: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Παραλάβατε ένα νέο μήνυμα ταχυδρομείου στο {0} inbox:
    service.gui.NEW_GMAIL_MANY_HEADER=Παραλάβατε δύο νέα μηνύματα ταχυδρομείου στο {0} inbox:
    service.gui.NEW_GMAIL_FOOTER=ακόμη μία συνομιλία που δεν διαβάσατε στο inbox.
    @@ -614,7 +576,6 @@ service.gui.SECURITY_ERROR=Σφάλμα ασφαλείας service.gui.SPEED=Ταχύτητα: service.gui.SILENT_MEMBER=σιωπηλό μέλος service.gui.NON_SECURE_CONNECTION=Δε μπορεί να γίνει ασφαλής σύνδεση στο λογαριασμό {0}. Εάν επιθυμείτε να συνδεθείτε σε μη ασφαλή διακομιστή, ενεργοποιήστε την επιλογή "Να επιτρέπονται μη ασφαλείς συνδέσεις" στις ρυθμίσεις του λογαριασμού σας. -service.gui.UPDATE=Ενημέρωση service.gui.MOBILE_PHONE=Κινητό service.gui.VIDEO_PHONE=Βίντεο service.gui.WORK_PHONE=Εργασία @@ -649,12 +610,10 @@ service.gui.callinfo.CALL_INFORMATION=Πληροφορίες κλήσης service.gui.callinfo.CALL_IDENTITY=Ταυτότητα service.gui.callinfo.PEER_COUNT=Πλήθος συμμετεχόντων service.gui.callinfo.IS_CONFERENCE_FOCUS=Εστίαση συνεδρίασης -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Κρυπτογράφηση ενεργοποιημένη service.gui.callinfo.CALL_TRANSPORT=Μέσο του καναλιού σηματοδότησης service.gui.callinfo.CALL_DURATION=Διάρκεια κλήσης service.gui.callinfo.TLS_PROTOCOL=Πρωτόκολλο TLS service.gui.callinfo.TLS_CIPHER_SUITE=Κρυπτογράφηση TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Αλυσίδα πιστοποιητικών του διακομιστή TLS service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Το περιεχόμενο του πιστοποιητικού TLS εμφανίζεται παρακάτω. service.gui.callinfo.VIEW_CERTIFICATE=Προβολή πιστοποιητικού service.gui.callinfo.CODEC=Κωδικοποιητής / Συχνότητα @@ -664,7 +623,6 @@ service.gui.callinfo.AUDIO_INFO=Πληροφορίες ήχου service.gui.callinfo.VIDEO_INFO=Πληροφορίες βίντεο service.gui.callinfo.LOCAL_IP=Τοπική IP / Θύρα service.gui.callinfo.REMOTE_IP=Απομακρυσμένη IP / Θύρα -service.gui.callinfo.BANDWITH=Ταχύτητα σύνδεσης service.gui.callinfo.LOSS_RATE=Ποσοστό απώλειας service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Θόρυβος @@ -674,10 +632,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Πρωτόκολλο ανταλλαγής κλειδιών service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Εκτεταμένος τύπος υποψηφίου ICE service.gui.callinfo.ICE_STATE=Κατάσταση ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Συλλογή υποψηφίων διευθύνσεων service.gui.callinfo.ICE_STATE.RUNNING=Έλεγχος συνδεσιμότητας service.gui.callinfo.ICE_STATE.COMPLETED=Ολοκληρώθηκε service.gui.callinfo.ICE_STATE.FAILED=Απέτυχε + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Τοπική IP / Θύρα service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Local reflexive IP / Port service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Local relayed IP / Port @@ -698,11 +659,12 @@ service.gui.ALWAYS_TRUST=Να εμπιστεύεσαι πάντα αυτό το service.gui.CERT_DIALOG_TITLE=Επαλήθευση Πιστοποιητικού service.gui.CERT_DIALOG_DESCRIPTION_TXT=Το {0} δε μπορεί να επαληθεύσει τη ταυτότητα του διακομιστή κατά τη σύνδεση με
    {1}.

    Το πιστοποιητικό ασφαλείας δεν είναι αξιόπιστο, οπότε η ταυτότητα του διακομιστή δε μπορεί να πιστοποιηθεί αυτόματα.

    Θέλετε να συνδεθείτε;
    Για περισσότερες πληροφορίες κάντε κλικ στο "Εμφάνιση Πιστοποιητικού". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST=Το {0} δε μπορεί να επαληθεύσει τη ταυτότητα του πιστοποιητικού ασφαλείας του διακομιστή.

    Το πιστοποιητικό ασφαλείας δεν είναι αξιόπιστο, οπότε η ταυτότητα του διακομιστή δε μπορεί
    να πιστοποιηθεί αυτόματα. Θέλετε να συνδεθείτε;

    Για περισσότερες πληροφορίες επιλέξτε "Εμφάνιση Πιστοποιητικού". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT=Το {0} δε μπορεί να επαληθεύσει την ταυτότητα του συνδεόμενου πελάτη.

    Το πιστοποιητικό ασφαλείας δεν είναι αξιόπιστο, οπότε η ταυτότητα του διακομιστή δε μπορεί
    να πιστοποιηθεί αυτόματα. Θέλετε να δεχτείτε αυτή τη σύνδεση;

    Για περισσότερες πληροφορίες επιλέξτε "Εμφάνιση Πιστοποιητικού". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT=Το {0} δε μπορεί να επαληθεύσει την ταυτότητα του ομότιμου {1}.

    Το πιστοποιητικό ασφαλείας δεν είναι αξιόπιστο, οπότε η ταυτότητα του διακομιστή δε μπορεί να
    πιστοποιηθεί αυτόματα. Θέλετε να συνδεθείτε;

    Για περισσότερες πληροφορίες επιλέξτε "Εμφάνιση Πιστοποιητικού". service.gui.CONTINUE_ANYWAY=Αγνόηση και συνέχεια service.gui.CERT_INFO_CHAIN=Αλυσίδα πιστοποιητικών: service.gui.CERT_INFO_ISSUED_TO=Εκδόθηκε προς + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Κοινό Όνομα: service.gui.CERT_INFO_O=Οργανισμός: service.gui.CERT_INFO_C=Χώρα: @@ -721,12 +683,10 @@ service.gui.CERT_INFO_SIGN_ALG=Υπογραφή Αλγορίθμου: service.gui.CERT_INFO_PUB_KEY_INFO=Πληροφορίες Δημοσίου Κλειδιού service.gui.CERT_INFO_ALG=Αλγόριθμος: service.gui.CERT_INFO_PUB_KEY=Δημόσιο Κλειδί: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Εκθέτης: service.gui.CERT_INFO_KEY_SIZE=Μέγεθος κλειδί: service.gui.CERT_INFO_SIGN=Υπογραφή: -service.gui.CONTINUE=Συνέχεια service.gui.SHOW_CERT=Εμφάνιση Πιστοποιητικού service.gui.HIDE_CERT=Απόκρυψη Πιστοποιητικού @@ -749,12 +709,9 @@ service.gui.security.SECURE_AUDIO=Κρυπτογραφημένο ηχητικό service.gui.security.AUDIO_NOT_SECURED=Μη κρυπτογραφημένο ηχητικό σήμα service.gui.security.SECURE_VIDEO=Κρυπτογραφημένο βίντεο service.gui.security.VIDEO_NOT_SECURED=Βίντεο μη κρυπτογραφημένο -service.gui.security.NO_VIDEO=Χωρίς βίντεο -service.gui.security.CIPHER=Αλγόριθμος κρυπτογράφησης: {0} service.gui.security.CALL_SECURED_TOOLTIP=Κλήση κρυπτογραφημένη. Για περισσότερες πληροφορίες πατήστε εδώ. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Κλήση μη κρυπτογραφημένη. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Κάντε κλικ εδώ για να συγκρίνετε το μυστκό συνθηματικό με τον συνομιλητή σας. -service.gui.security.COMPARE_WITH_PARTNER=Συγκρίνατε με το συνομιλητή σας και κάντε κλικ στη κλειδαριά για επιβεβαίωση. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Συγκρίνατε με το συνομιλητή: service.gui.security.STRING_COMPARED=Το συνθηματικό πιστοποιήθηκε! @@ -772,20 +729,14 @@ service.gui.avatar.imagepicker.CLICK=Κάντε κλικ και Χαμογελά service.gui.avatar.imagepicker.IMAGE_FILES=Αρχεία Εικόνας service.gui.avatar.imagepicker.IMAGE_PICKER=Φωτογραφία service.gui.avatar.imagepicker.IMAGE_SIZE=Μέγεθος εικόνας -service.gui.avatar.imagepicker.INITIALIZING=Αρχικοποίηση σε εξέλιξη service.gui.avatar.imagepicker.RESET=Reset service.gui.avatar.imagepicker.SET=Καθορισμός (Set) service.gui.avatar.imagepicker.TAKE_PHOTO=Λήψη φωτογραφίας -service.gui.avatar.imagepicker.WEBCAM_ERROR=Σφάλμα της κάμερας service.gui.security.encryption.required=Απαιτείται κρυπτογράφηση! service.protocol.ICE_FAILED=Δεν ήταν δυνατή η δημιουργία σύνδεσης (το ICE απέτυχε και δεν βρέθηκε αναμεταδότης) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Παρουσιάστηκε σφάλμα στη λίστα επαφών SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Ο πόρος {0} δεν μπόρεσε να διαβαστεί. Λογαριασμός: {1} @@ -815,9 +766,7 @@ impl.ldap.QUERY_CUSTOM=Προσαρμοσμένο ερώτημα impl.ldap.QUERY_CUSTOM_HINT=Χρησιμοποιήστε το {0} ως σύμβολο κράτησης θέσης για την αναζήτηση. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Αυτόματη προσθήκη μπαλαντέρ στον όρο του ερωτήματος impl.ldap.QUERY_PHOTO_INLINE=Λήψη φωτογραφιών μαζί με τα άλλα χαρακτηριστικά -impl.ldap.NEW=Νέος/ Νέα impl.ldap.EDIT=επεξεργασία -impl.ldap.REMOVE=Απομάκρυνση impl.ldap.ENABLED=Ενεργοποιήθηκε impl.ldap.SERVER_NAME=Όνομα διακομιστή impl.ldap.SERVER_NAME_EXAMPLE=Ο LDAP διακομιστής μου @@ -850,6 +799,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=τηλέφωνοΣπιτιού impl.ldap.PHONE_PREFIX=Πρόθεμα τηλεφώνου impl.ldap.PHONE_PREFIX_EXAMPLE=Πχ: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Κατάλογος Διευθύνσεων plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Ενεργοποίηση αναζήτησης στο Βιβλίο Διευθύνσεων MacOSX Address @@ -864,9 +817,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Κάντε το Outlook τον # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Επαφές Google -impl.googlecontacts.NEW=Νέος/ Νέα impl.googlecontacts.EDIT=επεξεργασία -impl.googlecontacts.REMOVE=Απομάκρυνση impl.googlecontacts.ENABLED=Ενεργοποιήθηκε impl.googlecontacts.ACCOUNT_NAME=Όνομα λογαριασμού impl.googlecontacts.SAVE=Αποθήκευση @@ -905,11 +856,8 @@ plugin.accountinfo.ORGANIZATION=Όνομα οργανισμού: plugin.accountinfo.JOB_TITLE=Τίτλος εργασίας: plugin.accountinfo.ABOUT_ME=Σχετικά με μένα: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Φωτογραφίες Χρήστη plugin.accountinfo.GLOBAL_ICON=Χρηση του γενικού εικονιδίου plugin.accountinfo.LOCAL_ICON=Χρήση αυτού του εικονιδίου: -plugin.accountinfo.CHANGE=Αλλαγή -plugin.accountinfo.ONLY_MESSAGE=Μόνον μηνύματα # connection info plugin.connectioninfo.TITLE=Πληροφορίες σύνδεσης @@ -929,49 +877,12 @@ plugin.aimaccregwizz.USERNAME=Όνομα οθόνης για το ΑΙΜ plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Όνομα Οθόνης και Κωδικός Εισόδου plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Καταχώρηση νέου λογαριασμού plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Σε περίπτωση που δεν έχετε έναν λογαριασμό AIM, κάντε κλικ σε αυτό το κουμπί για να φτιάξετε έναν καινούργιο. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Παράκαμψη των προκαθορισμένων επιλογών του Διακομιστή # branding plugin.branding.ABOUT_WINDOW_TITLE=Σχετικά με το {0} plugin.branding.LOGO_MESSAGE=VoIP Ανοικτού Κώδικα && Υπηρεσία Άμεσων Μηνυμάτων (Instant Messaging) -plugin.branding.LOADING=Φορτώνει plugin.branding.ABOUT_MENU_ENTRY=&Περί -plugin.branding.WELCOME_MESSAGE=
    Το {1} είναι τρεχόντως υπό ανάπτυξη. Η έκδοση που τρέχετε είναι απλώς πειραματική και ΙΣΩΣ ΝΑ ΜΗ δουλέψει όπως θα αναμένατε. Για παραπάνω πληροφορίες, παρακαλώ ανατρέξτε στο {2}.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Με την επιφύλαξη όλων των νομίμων δικαιωμάτων. Επισκεφθείτε το http://jitsi.org.
    -plugin.branding.LICENSE=
    Το Jitsi διανέμεται με τους όρους της LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Λεξικά -plugin.dictaccregwizz.ANY_DICTIONARY=Οποιοδήποτε Λεξικό -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Οποιοδήποτε Λεξικό από το {0} -plugin.dictaccregwizz.FIRST_MATCH=Πρώτο ταίρασμα -plugin.dictaccregwizz.NO_MATCH=Δεν έγινε εφικτό κανένα ταίριασμα -plugin.dictaccregwizz.MATCH_RESULT=Δεν βρέθηκαν ορισμοί για το "{0}", ίσως να εννοείτε:\n -plugin.dictaccregwizz.INVALID_DATABASE=Το τρέχον Λεξικό "{0}" δεν υπάρχει πλέον σε αυτόν τον διακομιστή. -plugin.dictaccregwizz.INVALID_STRATEGY=Η τρέχουσα στρατηγική δεν είναι διαθέσιμη στον διακομιστή. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Το Πρωτόκολλο υπηρεσιών Dict -plugin.dictaccregwizz.HOST=Κεντρικός Υπολογιστής -plugin.dictaccregwizz.SERVER_INFO=Πληροφορίες για τον Διακομιστή -plugin.dictaccregwizz.STRATEGY_SELECTION=Επιλογή Στρατηγικής -plugin.dictaccregwizz.STRATEGY_LIST=Κατάλογος στρατηγικών: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Αναζήτηση των στρατηγικών -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Η στρατηγική σε χρήση, για αναζήτηση παρόμοιων λέξεων, αν δεν βρεθεί μία μετάφραση, χάρη σε διαφορετικές προσεγγίσεις. Για παράδειγμα, οι στρατηγικές Prefix θα αναζητήσουν λέξεις που να αρχίζουν όπως και η λέξη που θέλατε να μεταφράσετε. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Πληροφορίες Λογαριασμού Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Αυτός ο Βοηθός (wizard) θα σας φτιάξει τον πρώτο σας Λογαρισμό Dict, στο dict.org.\n\nΜπορείτε να προσθέσετε ένα νέο λεξικό πηγαίνοντας στον Βοηθό Καταχώρησης Λογαριασμών. Συμπληρώστε το Πεδίο για τον host, με το λεξικό που θα θέλατε να προσθέσετε. -plugin.dictaccregwizz.THREAD_CONNECT=Προσπάθεια σύνδεσης με τον Διακομιστή -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Αποτυχία της προσπάθειας σύνδεσης. Είτε αυτός δεν είναι ένας διακομιστής dict, είτε ο διακομιστής είναι χωρίς σύνδεση. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Στρατηγικές ανάκτησης -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Δεν εντοπίσθηκε καμία στρατηγική στον Διακομιστή -plugin.dictaccregwizz.POPULATE_LIST=Γεμίζει τον Κατάλογο -plugin.dictaccregwizz.CLOSING_CONNECTION=Κλείσιμο σύνδεσης - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Για να χρησιμοποιήσετε το Facebook Chat, πρέπει να φτιάξετε έναν "Username"
    από τη σελίδα με τις "Ρυθμίσεις του Λογαριασμού" σας, στο Facebook.


    Σημείωση: Όταν φτιάχνετε ένα Όνομα χρήστη, πρέπει να αποσυνδεθείτε από την ιστοσελίδα
    και μπορεί να χρειασθεί αρκετή ώρα μέχρι να μπορέσετε να μπείτε με το νέο σας όνομα χρήστη!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Το Πρωτόκολλο για το Facebook Chat -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Όνομα χρήστη: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Όνομα χρήστη και Κωδικός πρόσβασης + # generalconfig plugin.generalconfig.AUTO_START=Αυτόματη εκκίνηση του {0} όταν ο υπολογιστής επανεκκινεί. @@ -982,9 +893,6 @@ plugin.generalconfig.SHOW_HISTORY=Εμφάνιση plugin.generalconfig.HISTORY_SIZE=πρόσφατα μηνύματα σε νέα chats plugin.generalconfig.SEND_MESSAGES_WITH=Στείλτε μηνύματα με το: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Μεταφορά του παραθύρου chat στο προσκήνιο. -plugin.generalconfig.ERROR_PERMISSION=Δεν διαθέτετε επαρκή δικαιώματα για την απομάκρυνση του autostart -plugin.generalconfig.TRANSPARENCY=Διαφάνεια -plugin.generalconfig.ENABLE_TRANSPARENCY=Ενεργοποίηση διαφάνειας plugin.generalconfig.DEFAULT_LANGUAGE=Διεπαφή Γλώσσας plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Οι αλλαγές σας θα ενεργοποιηθούν με την επόμενη επανεκκίνηση. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% μεταφρασμένο @@ -1043,13 +951,13 @@ plugin.ircaccregwizz.EXAMPLE_SERVER=Π.χ.: chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Χρησιμοποιήστε ασφαλή σύνδεση plugin.ircaccregwizz.ENABLE_CONTACT_PRESENCE=Ενεργοποίηση παρουσίας plugin.ircaccregwizz.ENABLE_CHAT_ROOM_PRESENCE=Ενεργοποίηση παρουσίας στα δωμάτια συζητήσεων +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} ταυτοποίηση +plugin.ircaccregwizz.SASL_USERNAME=Όνομα χρήστη # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Το πρωτόκολλο XMPP plugin.jabberaccregwizz.USERNAME=XMPP όνομα χρήστη plugin.jabberaccregwizz.PASSWORD_CONFIRM=Επιβεβαίωση κωδικού πρόσβασης -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=Ταυτοποίηση και Κωδικός πρόσβασης plugin.jabberaccregwizz.CSERVER=Διακομιστής plugin.jabberaccregwizz.SERVER=Σύνδεση με τον διακομιστή plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Ενεργοποίηση λειτουργίας keep alive @@ -1065,13 +973,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Σχόλιο plugin.jabberaccregwizz.RESOURCE=Πόροι plugin.jabberaccregwizz.AUTORESOURCE=Αυτόματη δημιουργία πόρων plugin.jabberaccregwizz.PRIORITY=Προτεραιότητα -plugin.jabberaccregwizz.XMPP_ERROR=Σφάλμα XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Άγνωστο σφάλμα XMPP ({0}). Ελέγξτε ότι το όνομα του διακομιστή είναι σωστό. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Οι κωδικοί πρόσβασης δε ταιριάζουν. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Παράκαμψη των προκαθορισμένων επιλογών του διακομιστή -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Προχωρημένες επιλογές plugin.jabberaccregwizz.USE_ICE=Χρήση του ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Χρησιμοποίησε το Jingle/ICE της Google (πειραματικό) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Αυτόματος εντοπισμός (Auto-discover) διακομιστών STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=Υποστήριξη του TURN plugin.jabberaccregwizz.TURN_USERNAME=Όνομα χρήστη για το TURN @@ -1099,11 +1003,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Απενεργοποίηση των μη plugin.jabberaccregwizz.DTMF_AUTO=Αυτόματο: Να γίνεται αυτόματη επιλογή μεταξύ RTP και Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Επιλογές εξυπηρετητή plugin.jabberaccregwizz.CHANGE_PASSWORD=Αλλαγή κωδικού πρόσβασης λογαριασμού -plugin.jabberaccregwizz.NEW_PASSWORD=Νέος κωδικός πρόσβασης -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Επιβεβαίωση του νέου κωδικού πρόσβασης plugin.jabberaccregwizz.PORT_FIELD_INVALID=Παρακαλώ συμπληρώστε ένα έγκυρο αριθμό θύρας για να συνεχίσετε. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Πρέπει να είστε συνδεδεμένος για να αλλάξετε τον κωδικό πρόσβασης σας. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Το συνθηματικό είναι κενό. plugin.jabberaccregwizz.TLS_REQUIRED=Η σύνδεση δεν χρησιμοποιεί TLS, δεν θα επιχειρηθεί αλλαγή συνθηματικού. plugin.jabberaccregwizz.PASSWORD_CHANGED=Το συνθηματικό άλλαξε με επιτυχία. plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Ο διακομιστής XMPP δεν υποστηρίζει την αλλαγή συνθηματικού. @@ -1117,25 +1018,9 @@ plugin.jabberaccregwizz.RESET=Επαναφορά plugin.jabberaccregwizz.RESET_DESCRIPTION=Επαναφορά στις γενικές ρυθμίσεις plugin.jabberaccregwizz.DISABLE_JINGLE=Απενεργοποίηση Jingle (κλήσεις με εικόνα και ήχο μέσω XMPP). -# mailbox -plugin.mailbox.OUTGOING=Εξερχόμενο Μήνυμα: -plugin.mailbox.INCOMING=Εισερχόμενα Μηνύματα: -plugin.mailbox.WAIT_TIME=Καθυστέρησε ωσότου η κλήση σταλεί στο φωνητικό Ταχυδρομείο (Voicemail) -plugin.mailbox.MAX_MESSAGE_TIME=Μέγιστη Διάρκεια Εισερχομένου Μυνήματος -plugin.mailbox.CONFIRM=Επιβεβαίωση -plugin.mailbox.DEFAULTS=Προκαθορισμένες επιλογές -plugin.mailbox.MAILBOX=Γραμματοκιβώτιο - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Ένα Πρωτόκολλο για σύνδεση και chat με την υπηρεσία MSN. -plugin.msnaccregwizz.USERNAME=Email: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Ταυτοποίηση και Κωδικός πρόσβασης - # plugin manager plugin.pluginmanager.INSTALL=Εγκατάσταη plugin.pluginmanager.UNINSTALL=Απεγκατάσταση -plugin.pluginmanager.UPDATE=Ενημέρωση plugin.pluginmanager.PLUGINS=Πρόσθετα Plug-ins plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=Επιλογή Αρχείου @@ -1160,7 +1045,6 @@ plugin.sipaccregwizz.SERVER_PORT=Θύρα Διακομιστή plugin.sipaccregwizz.PROXY=Διακομιστής διαμεσολάβησης (Proxy) plugin.sipaccregwizz.PROXY_PORT=Θύρα διακομιστή διαμεσολάβησης (Proxy) plugin.sipaccregwizz.PREFERRED_TRANSPORT=Προτιμώμενη μεταφορά -plugin.sipaccregwizz.ADVANCED_OPTIONS=Προχωρημένες επιλογές plugin.sipaccregwizz.PROXY_OPTIONS=Επιλογές Διακομιστή διαμεσολάβησης (Proxy) plugin.sipaccregwizz.PROXY_AUTO=Αυτόματη Ρύθμιση διακομιστή διαμεσολάβησης plugin.sipaccregwizz.ENABLE_PRESENCE=Ενεργοποίηση της Παρουσίας (ΑΠΛΟ) @@ -1180,8 +1064,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Αυτόματο: Να γίνεται αυτόμ plugin.sipaccregwizz.DTMF_RTP=RTP ( σύμφωνα με τις προτάσεις RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Εντός εύρους -plugin.sipaccregwizz.REGISTER=ΕΓΓΡΑΦΗ -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Παράκαμψη των προκαθορισμένων επιλογών του διακομιστή plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Ενεργοποίηση υποστήριξης για απόκρυψη κλήσεων plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Αναφέρετε την υποστήριξη της ZRTP στο πρωτόκολλο σηματοδότησης plugin.sipaccregwizz.AUTH_NAME=Όνομα εξουσιοδότησης @@ -1202,10 +1084,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Διεύθυνση ελέγχου τη plugin.sipaccregwizz.NOT_SAME_PASSWORD=Οι κωδικοί πρόσβασης που δώσατε δε ταιριάζουν. plugin.sipaccregwizz.NO_CERTIFICATE=<κανένα> (χρησιμοποίησε κανονική πιστοποίηση) plugin.sipaccregwizz.SAVP_OPTION=Ένδειξη RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Απενεργοποιημένο (υπόδειξη μόνο RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Υποχρεωτικό (προσφορά και αποδοχή μόνο RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Προαιρετικό (προσφορά RTP/SAVP πρώτα, μετά RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Ενεργοποίηση S-Descriptor (αλλιώς γνωστό ως SDES ή SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Επιλέξτε τα ενεργοποιημένα πρωτόκολλα κρυπτογράφησης και την προτεραιότητά τους: plugin.sipaccregwizz.CIPHER_SUITES=Ενεργοποιημένες σουίτες κρυπτογράφησης: plugin.sipaccregwizz.SECURITY_WARNING=
    το {0} θα προσπαθήσει να ασφαλίσει τις κλήσεις σας αυτόματα με το ZRTP και θα σας ειδοποιήσει ηχητικά και οπτικά μόλις εδραιώσει μια ασφαλή σύνδεση. Αλλάξτε τις παρακάτω ρυθμίσεις μόνο εάν ξέρετε πολύ καλά τι κάνετε.
    @@ -1219,15 +1101,6 @@ plugin.skinmanager.DEFAULT_SKIN=Προεπιλεγμένο skin plugin.skinmanager.ADD_NEW_SKIN=Προσθήκη νέου skin... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Το προκαθορισμένο skin της εφαρμογής. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Ένα Πρωτόκολλο για την σύνδεση απομεμακρυσμένων μηχανημάτων μέσω SSH. -plugin.sshaccregwizz.USERNAME=Ταυτοποίηση λογαρισμού: -plugin.sshaccregwizz.IDENTITY_FILE=Ταυτότητα Αρχείου: -plugin.sshaccregwizz.KNOWN_HOSTS=Καταγεγραμμένοι υπολογιστές: -plugin.sshaccregwizz.OPTIONAL=Προαιρετικό -plugin.sshaccregwizz.ACCOUNT_DETAILS=Λεπτομέρειες λογαριασμού - # status update plugin.autoaway.AUTO_STATUS=Auto Away plugin.autoaway.ENABLE_CHANGE_STATUS=Αλλαγή καταστάσεως (status) όταν είμαστε μακριά @@ -1275,22 +1148,6 @@ plugin.whiteboard.DESELECT=Αποεπιλογή plugin.whiteboard.DELETE=Διαγραφή plugin.whiteboard.PROPERTIES=Ιδιότητες -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Ένα πρωτόκολλο για συνομιλία μέσω της υπηρεσίας Yahoo. -plugin.yahooaccregwizz.USERNAME=Όνομα χρήστη: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Ταυτοποίηση και Κωδικός πρόσβασης: - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Πρωτόκολλο της υπηρεσίας Zeroconf (Bonjour) -plugin.zeroaccregwizz.FIRST_NAME=Όνομα: -plugin.zeroaccregwizz.LAST_NAME=Επίθετο: -plugin.zeroaccregwizz.EMAIL=Email: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Θυμάσαι τις επαφές Bonjour ; -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Ταυτοποίηση και Κωδικός πρόσβασης: -plugin.zeroaccregwizz.USERID=Ταυτότητα Χρήστη: - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Το Πρωτόκολλο Google Talk @@ -1304,19 +1161,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, the IP Telecommunications plugin.iptelaccregwizz.USERNAME=Όνομα χρήστη plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Εγγραφείτε στο iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP και chat +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Όνομα χρήστη plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Πληκτρολογείστε ξανά τον Κωδικό πρόσβασης plugin.sip2sipaccregwizz.EMAIL=Διεύθυνση Email -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Για παραπάνω βοήθεια με αυτή την υπηρεσία επισκεφθείτε το
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Η διεύθυνση email χρησιμοποιείται για αποστολή φωνητικών μηνυμάτων,
    ειδοποιήσεων περί αναπάντητων κλήσεων και για ανάκτηση χαμένων κωδικών πρόσβασης -plugin.sip2sipaccregwizz.INFO_NOTE=Για παραπάνω βοήθεια με αυτή την υπηρεσία επισκεφθείτε τοhttp://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Υπάρχων λογαριασμός sip2sip.info -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Δημιουργία ενός δωρεάν λογαριασμού sip2sip.info - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && Υπηρεσία ανταλλαγής Άμεσων Μηνυμάτων (Instant Messaging) plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Για παραπάνω βοήθεια με αυτή την υπηρεσία επισκεφθείτε το
    http://ippi.fr @@ -1325,6 +1174,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Υπάρχων λογαριασμός ipp plugin.ippiaccregwizz.CREATE_ACCOUNT=Δημιουργείστε έναν δωρεάν λογαριασμό ippi # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Κλείσιμο του παραθύρου του chat plugin.keybindings.CHAT_COPY=Αντι&γραφή plugin.keybindings.CHAT_CUT=Απο&κοπή @@ -1347,10 +1197,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Όνομα plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Πρωτεύουσα συντόμευση plugin.keybindings.globalchooser.SHORTCUT_SECOND=Δευτερεύουσα συντόμευση plugin.keybindings.globalchooser.PRESS_BTN=Πιέστε για να θέσετε τη συντόμευση -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Αναμονή plugin.keybindings.globalchooser.PUSH_TO_TALK=Κουμπί ομιλίας plugin.keybindings.globalchooser.ENABLE_SPECIAL=Ενεργοποίηση ανίχνευσης ειδικών πλήκτρων plugin.keybindings.PLUGIN_NAME=Keybindings +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Συζητήσεις plugin.keybindings.MAIN=Κυρίως plugin.keybindings.GLOBAL=Γενικές συντομεύσεις @@ -1378,6 +1228,7 @@ plugin.notificationconfig.tableheader.SOUND=Αναπαραγωγή ήχου μέ plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Αναπαραγωγή ήχου μέσω της συσκευής αναπαραγωγής plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Αναπαραγωγή ήχου μέσω του ηχείου συστήματος plugin.notificationconfig.tableheader.DESCRIPTION=Περιγραφή συμβάντος +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Εισερχόμενη κλήση plugin.notificationconfig.event.SecurityMessage=Μήνυμα ασφαλείας plugin.notificationconfig.event.IncomingFile=Εισερχόμενο αρχείο @@ -1479,6 +1330,7 @@ impl.neomedia.configform.VIDEO=Βίντεο impl.neomedia.configform.H264=Η.264 impl.neomedia.configform.H264.defaultIntraRefresh=Περιοδική ενδοανανέωση impl.neomedia.configform.H264.defaultProfile=Προεπιλεγμένο προφίλ κωδικοποίησης: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Βάση Η.264 impl.neomedia.configform.H264.defaultProfile.high=Υψηλή impl.neomedia.configform.H264.defaultProfile.main=Κυρίως @@ -1509,7 +1361,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Τρέχων Κωδικό plugin.securityconfig.masterpassword.ENTER_PASSWORD=Βάλτε έναν νέο Κωδικό: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Ξαναπληκτρολογείστε τον Κωδικό πρόσβασης: plugin.securityconfig.masterpassword.MP_TITLE=Γενικός Κωδικός Πρόσβασης -plugin.securityconfig.masterpassword.MP_NOT_SET=(δεν καθορίσθηκε) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Δεν πληκτρολογήσατε τον σωστό Γενικό Κωδικό Πρόσβασης. Δοκιμάστε ξανά. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Ο Γενικός Κωδικός Πρόσβασης δεν είναι ορθός! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Η Αλλαγή Κωδικού πρόσβασης απέτυχε @@ -1525,7 +1376,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Κωδικός πρόσβασ plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(άγνωστος) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(δεν μπορεί να αποκρυπτογραφήσει) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Αποθηκευμένοι κωδικοί πρόσβασης -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Απομάκρυνση plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Απομάκρυνση όλων plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Είστε βέβαιος ότι θέλετε να απομακρύνετε όλους τους κωδικούς ; plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Απομάκρυνση όλων των κωδικών πρόσβασης @@ -1621,7 +1471,6 @@ plugin.globalproxy.PROXY_PORT=Θύρα διακομιστή διαμεσολάβ plugin.globalproxy.PROXY_USERNAME=Όνομα χρήστη Proxy plugin.globalproxy.PROXY_PASSWORD=Κωδικός πρόσβασης Proxy plugin.globalproxy.DESCRIPTION=To {0} θα χρησιμοποιεί τις παραπάνω ρυθμίσεις proxy για όλα τα δίκτυα με τα οποία συνδέεσθε ή επανασυνδέεσεθε, από τώρα και στο εξής. \nΗ υποστήριξη Proxy αυτή τη στιγμή είναι σε πειραματικό στάδιο και δουλεύει μόνο με μερικά πρωτόκολλα. Ελέγξτε τον παρακάτω πίνακα για περισσότερες λεπτομέρειες: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Χρησιμοποιήση του διακομιστή μεσολάβησης και για το DNS plugin.globalproxy.FWD_DNS_NOTE=Χρήσιμο όταν χρησιμοποιείτε το Tor. Αποτρέπει τη δημοσιοποίηση των δεδομένων DNS ανακατευθύνοντας μέσω του μεσολάβητή Tor όλα τα δεδομένα DNS. Δεν τίθεται σε ισχύ μέχρι να κάνετε επανεκκίνηση. @@ -1659,7 +1508,6 @@ plugin.provisioning.RESTART_WARNING=Σημειώστε ότι οι αλλαγέ plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Αντιγραφή του UUID στο πρόχειρο plugin.provisioning.CLIPBOARD_FAILED=Αποτυχία αντιγραφής του UUID στο πρόχειρο -plugin.provisioning.EXIT_ON_FAIL=Τερματισμός εφαρμογής αν η αυτόματη τροφοδοσία ρυθμίσεων αποτύχει plugin.provisioning.CREDENTIALS=Πιο πρόσφατα αποθηκευμένα διαπιστευτήρια αυτόματης τροφοδοσίας ρυθμίσεων plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Είστε σίγουροι ότι θέλετε να σβήσετε το συνθηματικό για την αυτόματη τροφοδοσία ρυθμίσεων; plugin.provisioning.PROV_FAILED=Η παροχή πληροφοριών απέτυχε @@ -1726,8 +1574,6 @@ util.dns.DNSSEC_WARNING=
    Το {0} επιχείρησε ν #plugin spellcheck plugin.spellcheck.TITLE=Ορθογραφία και γραμματική plugin.spellcheck.MENU=Δείξε την ορθογραφία και γραμματική -plugin.spellcheck.LANG=Γλώσσα -plugin.spellcheck.EDIT_PERSONAL_DICT=Επεξεργασία plugin.spellcheck.ENABLE_SPELL_CHECK=Ενεργοποίηση ορθογράφου plugin.spellcheck.dialog.FIND=Βρες το επόμενο plugin.spellcheck.dialog.REPLACE=Αντικατάσταση -- cgit v1.1 From 2934f4f86736676e6c4b7bdf45c1608b98219169 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:54:58 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1463 of 1505 strings translated (11 fuzzy). --- resources/languages/resources_bg.properties | 207 ++++------------------------ 1 file changed, 29 insertions(+), 178 deletions(-) diff --git a/resources/languages/resources_bg.properties b/resources/languages/resources_bg.properties index c61c18e..4c3f380 100644 --- a/resources/languages/resources_bg.properties +++ b/resources/languages/resources_bg.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Аз service.gui.ACCOUNT_REGISTRATION_WIZARD=Регистрация на профил service.gui.ACCOUNTS=Профили service.gui.ADD=&Добави -service.gui.ADD_ACCOUNT=Добави профил service.gui.ADD_CONTACT=&Добави контакт service.gui.ADD_AUTHORIZED_CONTACT=Добави {0} към списъка с контакти service.gui.ADD_CONTACT_TO_CONTACTLIST=Добавяне на контакта към списък ви с контакти @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Грешка при добавяне на к service.gui.ADD_CONTACT_EXIST_ERROR=Контактът {0} вече съществува във вашият списък с контакти. service.gui.ADD_CONTACT_NETWORK_ERROR=Сървърът не отговори на опита ни да добавим контакт: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Грешка при добавяне на {0}. Операцията не се поддържа. -service.gui.ADD_CONTACT_IDENTIFIER=В полето по-долу въведете идентификатора на контакта, който бихте искали да добавите. -service.gui.ADD_CONTACT_WIZARD=Добавяне на контакт service.gui.ADD_CONTACT_NOT_CONNECTED=Трябва да се свържете преди да добавите контакт. Моля свържете се и опитайте отново. service.gui.ADD_GROUP_LOCAL_ERROR=Възникна грешка при добавяне на група {0}. Проблемът е възникнал по време на входно-изходно операция. service.gui.ADD_GROUP_EXIST_ERROR=Групата {0} е вече добавена към вашия списък с контакти. service.gui.ADD_GROUP_NET_ERROR=Възникна грешка при добавяне на група {0}. Проблемът е възникнал по време на мрежова операция. Проверете мрежовите си настройки и опитайте отново. service.gui.ADD_GROUP_ERROR=Неуспешно добавяне на група: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Името на групата не трябва да е празно -service.gui.ADD_GROUP=Грешка при добавяне на група -service.gui.ADD_SUBCONTACT=&Добавяне на подконтакт service.gui.ADDRESS=Адрес service.gui.ADMINISTRATOR=администратор service.gui.ADVANCED=&Експертни -service.gui.ALL=&Всички service.gui.ALL_CONTACTS=&Всички контаки service.gui.ALTERNATE_ADDRESS=Алтернативен адрес service.gui.APPLY=&Приложи @@ -65,7 +70,6 @@ service.gui.AT=от service.gui.AUTHORIZE=&Разреши service.gui.AUTHORIZATION_ACCEPTED={0} прие молбата за легитимация. service.gui.AUTHENTICATION_FAILED=Неуспешна проверка на самоличността за {0}. Въвели сте невалидна парола. -service.gui.AUTHENTICATION_REQUESTED=Молба за добавяне service.gui.AUTHENTICATION_REQUESTED_SERVER=Идентификация за сървър {0}. service.gui.AUTHENTICATION_REJECTED={0} отказа молбата за легитимация. service.gui.AUTHENTICATION_WINDOW_TITLE=Проверка на самоличността @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Въдете новия прякор. service.gui.CHANGE_NICKNAME_ERROR=Грешка при смяната на псевдонима service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Псевдонимът вече съществува service.gui.CHANGE_VIDEO_QUALITY=Качество на видеото от събеседника ви -service.gui.CHAT_CONFERENCE_LABEL=Конференции service.gui.CHAT_CONFERENCE_ITEM_LABEL=Конференцията на {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Вече сте влезли в стая {0}. service.gui.CHAT_ROOM_CONFIGURATION={0} конфигуриране на стая @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=напусна {0} service.gui.CHAT_ROOM_USER_KICKED=беше изритан от {0} service.gui.CHAT_ROOM_USER_QUIT=напусна {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Изпращането на съобщения е забранено (гласът е анулиран) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Запазва чат стаята за бъдеща употреба -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Премахва избраната стая от списъка на запазените стаи service.gui.CHAT_ROOM_NAME=Име на стая service.gui.CLEAR_CUSTOM_MESSAGES=Изтрий персонализираните статуси service.gui.ROOM_NAME=Стая за разговори -service.gui.AUTOJOIN=Авт. влизане service.gui.CHANGE_PASSWORD=Промени паролата service.gui.CHAT_ROOM_NAME_INFO=Моля въведете името на стаята която желаете да създадете. service.gui.CHAT_ROOM_NOT_EXIST=Не успях да намеря стая {0} на сървър {1}. Моля проверете дали правилно сте написали името. service.gui.CHAT_ROOM_NOT_CONNECTED=Трябва да се свържете към мрежата преди да напуснете стая {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Трябва да се свържете преди да напуснете стаята (парадоксално, а :) ). -service.gui.CHAT_ROOM_NOT_JOINED=Трябва да сте в стаята за да можете да оперирате с нея. service.gui.CHAT_ROOM_OPTIONS=Настройки на стаята service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Нужно е да се регистрирате за да влезнете в стая {0}. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Нужна е парола за стая {0}. @@ -157,16 +156,13 @@ service.gui.CONNECTING=Свързване... service.gui.CONNECTING_STATUS=Свързване service.gui.CONNECTING_EARLY_MEDIA_STATUS=Свързване... service.gui.CONNECTION=Връзка -service.gui.CONNECTION_FAILED_MSG=Връзката към сървър {1} е прекъсната за потребител {0}. service.gui.CONNECTION_EXPIRED_MSG=В момента не сте свързани с {0}. service.gui.CONTACT_NAME=ID или номер -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY={0} не поддържа телефонните разговори. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF={0} не поддържа чат конференции. service.gui.CONTACT_PAUSED_TYPING={0} спря да пише service.gui.CONTACT_TYPING={0} пише съобщение service.gui.CONTACT_TYPING_SEND_FAILED=оп...не успяхме да предупредим {0}, че пишете service.gui.CONTACT_INFO=&Информация за контакта -service.gui.CONTACTLIST=Контакт листа service.gui.CONTACTS=Контакти service.gui.COPY=&Копирай service.gui.COPY_LINK=Копирай &връзка @@ -176,17 +172,14 @@ service.gui.CREATE_CHAT_ROOM=&Създай стая за разговори... service.gui.CREATE_CHAT_ROOM_ERROR=Неуспешен опит за създаване на стая: {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Асистент по създаване на стая за разговори service.gui.CREATE_CONFERENCE_CALL=&Създай телефонна конференция... -service.gui.CREATE_CONFERENCE_CHAT=&Създай чат конференция service.gui.CREATE_GROUP=&Създай групa... service.gui.CREATE_GROUP_NAME=Въведете името на групата, която бихте искали да създадете. -service.gui.CREATE_FIRST_GROUP_WIZARD=Списъкът ви с контакти не съдържа групи. Моля добавете група от меню Файл/Добави група. service.gui.CREATE_VIDEO_BRIDGE=Създай &видео мост... service.gui.CREATE_VIDEO_BRIDGE_MENU=Създай &видео мост service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Създай / присъедини се към видео конференция service.gui.CREATE_VIDEO_CONFERENCE=Създаване на нова видео-конференция за тази чат стая service.gui.CONTACT_INFO_NOT_SUPPORTED=Контактът не поддържа уеб информация service.gui.CUT=О&трежи -service.gui.DATE=Дата service.gui.DELETE=Изтрий service.gui.DENY=&Откажи service.gui.DESKTOP_SHARING_WARNING=Сигурен ли сте че искате да споделите екрана си?
    Ако натиснете OK останалите участници в обаждането ще могат да видят екрана ви. @@ -197,7 +190,6 @@ service.gui.DISCONNECTED_STATUS=Край на разговора service.gui.DND_STATUS=Не ме безпокойте service.gui.DO_NOT_ASK_AGAIN=Не ме питай повече service.gui.DO_NOT_SHOW_AGAIN=Повече не ми показвай това съобщение -service.gui.DOWNLOAD_NOW=&Свали сега service.gui.DRAG_FOR_SHARING=Довлачете тука прозорците, които искате да покажете service.gui.DURATION=продължителност service.gui.DESTROY_CHATROOM=Унищожаване на чат стаята @@ -218,7 +210,6 @@ service.gui.ERROR_RECEIVED_FROM=Получена грешка от {0} service.gui.ESTIMATED_TIME=Приблизително време: service.gui.EVENTS=Събития service.gui.EXIT=И&зход -service.gui.EXTENDED_CRITERIA=Допълнителни условия service.gui.GENERAL=Общи service.gui.GENERAL_ERROR=Обща грешка service.gui.GROUP_NAME=Име на групата @@ -260,7 +251,6 @@ service.gui.FONT_ITALIC=Курсив service.gui.FONT_SIZE=Размер service.gui.FONT_STYLE=Стил service.gui.FONT_UNDERLINE=Подчертан -service.gui.FROM={0} от {1} service.gui.GRANT_OWNERSHIP=Даване на собственост... service.gui.GRANT_ADMIN=Даване на администраторски права... service.gui.GRANT_MODERATOR=Даване на роля на модератор @@ -286,7 +276,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Сигурни ли сте, че иска service.gui.HISTORY_REMOVE_ERROR=Грешка при изтриването на локално запазените съобщения. service.gui.HOME=Домашен service.gui.HOME_PAGE=Начална страница -service.gui.HOUR=Час service.gui.ICE=ICE service.gui.IDENTIFIER=Ключ service.gui.IGNORE=&Пренебрегни @@ -310,13 +299,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Покани контакти във service.gui.INVITE_REASON=Текст на поканата service.gui.IS_CALLING={0} се обажда... service.gui.IS_NOW={0} вече е {1} -service.gui.JITSI_WARNING=Скоро преименувахме СИП Комуникатор и го нарекохме Жици (Jitsi).
    Ако желаете да продължите да получавате известия за нови версии ще трябва да свалите Жици сега.

    Съжаляваме ако това ви причинява неудобство!

    Разработчиците на Жици -service.gui.JITSI_WARNING_TITLE=СИП Комуникатор се прекръства на Жици service.gui.JOIN=&Влез service.gui.JOIN_AS=В&лез като service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Присъединяване към съществуваща видео-конференция service.gui.JOIN_VIDEO=Присъедини видео -service.gui.CLOSE_CHAT_ROOM_DIALOG=&Затвори service.gui.JOB_TITLE=Длъжност service.gui.JOIN_CHAT_ROOM=&Влез в стая за разговори... service.gui.JOIN_CHAT_ROOM_TITLE=Влизане в стая за разговори @@ -329,7 +315,6 @@ service.gui.KICK_FAILED=Неуспешен опит за изритване service.gui.KICK_FAILED_GENERAL_ERROR=При опит за изритване на {0} възникна грешка на сървъва. Опитът е неуспешен. service.gui.KICK_FAILED_NOT_ALLOWED=Неуспешен опит за изритване на {0}. Собствениците и администраторите на една стая не могат да бъдат изритвани. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Нямата правата необходими за изритването на {0}. -service.gui.LAST=Последно service.gui.LAST_NAME=Фамилия service.gui.LEAVE=&Напусни service.gui.LIMIT_REACHED_FOR_IP=Имате прекалено много регистрации от текущия ви адрес и сървърт на {0} не разрешава отварянето на нови. @@ -349,7 +334,6 @@ service.gui.MESSAGE=Съобщение service.gui.MISSED_CALLS_TOOL_TIP=Пропуснати обаждания от: service.gui.MISSED_CALLS_MORE_TOOL_TIP= и {0} други service.gui.MODERATOR=модератор -service.gui.MORE=Повече service.gui.MORE_LABEL=Повече service.gui.MOVE=Премести service.gui.MOVE_SUBCONTACT=Пре&мести подконтакт @@ -358,7 +342,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Подконтактът вече се нам service.gui.MOVE_SUBCONTACT_QUESTION=Сигурни ли сте, че искате да преместите {0} в {1}? service.gui.MOVE_TO_GROUP=Пре&мести в група service.gui.MOVE_CONTACT=Пре&мести контакт -service.gui.MOVE_CONTACT_ERROR=Контактът не може да бъде преместен service.gui.MSG_DELIVERY_FAILURE=Доставката на горното съобщение се провали service.gui.MSG_DELIVERY_NOT_SUPPORTED=Протоколът който използвате не позволява съобщенията към не включени потребители. Опитайте да се свържете с {0} чрез друг протокол или изчакайте да се включи. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Възникна грешка в програмата. Това най-вероятно е бъг. Ще ви бъдем благодарни ако ни уведомите: http://www.jitsi.org/index.php/Development/BugsAndIssues @@ -372,7 +355,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Трябва да се свържете service.gui.MULTIPLE_LOGINS=Свързали сте се повече от веднъж с един и същ профил. Потребител {0} на сървър {1} ше бъде изключен. service.gui.MY_CHAT_ROOMS=Добави чат стая service.gui.MY_CHAT_ROOMS_TITLE=Добави чат стая -service.gui.MUTE=Спри микрофона service.gui.MUTUALLY_ON_HOLD_STATUS=Взаимно се изчакваме service.gui.NAME=Име service.gui.NETWORK=Мрежа @@ -404,7 +386,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Временни контакти service.gui.SD_QUALITY=Стандартно качество service.gui.OFFLINE=Изключен service.gui.OK=&ОК -service.gui.OLDER_CALLS=Предишни обаждания service.gui.ONLINE=Включен service.gui.OPEN=Отвори service.gui.OPEN_FILE_FROM_IMAGE=Кликнете два пъти върху файла, за да го отворите. @@ -416,7 +397,6 @@ service.gui.OPEN_ON_ACTIVITY=При активност service.gui.OPEN_ON_MESSAGE=Само на нови съобщения service.gui.OPEN_ON_IMPORTANT_MESSAGE=Само на важни съобщения service.gui.OR=или -service.gui.OR_ENTER_PHONE_NUMBER=Или въведете телефонен номер тук... service.gui.ORGANIZATION=Организация service.gui.OTHER=Други service.gui.chat.role.OWNER=Собственик @@ -442,7 +422,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' за предложения service.gui.PRESS_FOR_CALL_INFO=Информация за обаждането service.gui.PRESS_TO_OPEN_CRM=Повече информация от външен източник service.gui.PREVIOUS=На&зад -service.gui.PREVIOUS_TOOLTIP=Разглеждане на по-ранни разговори service.gui.PRINT=&Печат service.gui.PROACTIVE_NOTIFICATION=ви пише service.gui.PROBLEMS_ENCOUNTERED=Намерени са проблеми @@ -458,7 +437,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Осъществихте няколко service.gui.RE_REQUEST_AUTHORIZATION=Ново искане на оторизация service.gui.REFERRED_STATUS=Препратен service.gui.REJECT=&Отказ -service.gui.REMIND_ME_LATER=Напомни ми по-късно service.gui.REMEMBER_PASSWORD=Запомни паролата service.gui.REMOVE=&Премахни service.gui.REMOVE_ACCOUNT=&Изтриване на профила @@ -484,9 +462,7 @@ service.gui.REVOKE_ADMIN=Отнеми администраторските пр service.gui.REVOKE_MODERATOR=Отнеми модераторските права service.gui.REVOKE_MEMBERSHIP=Отнеми членството service.gui.REVOKE_VOICE=Отнеми правото на изказване -service.gui.ROOT_GROUP=Група корен service.gui.SAVE=&Запази -service.gui.SAVE_AS_DEFAULT=Запиши по подразбиране service.gui.SEARCH=&Търси service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Използвайе бутона за да видите всички стаи от избрания сървър и с бутона Влез, изберете тази, в която искате да влезете. service.gui.SEARCH_STRING_CONTACT_SOURCE=Търсен контакт @@ -494,19 +470,13 @@ service.gui.SECURITY=Сигурност service.gui.SELECT_ACCOUNT=Изберете потребител service.gui.SELECT_COLOR=Изберете цвят service.gui.SELECT_GROUP=Изберете група -service.gui.SELECT_GROUP_WIZARD_MSG=Списъкът по-долу съдържа всички групи от вашата контакт листа. Изберете тази, в която искате да добавите новия контакт. service.gui.SELECT_NO_GROUP=Без група -service.gui.SELECT_GROUP_WIZARD=Изберете група service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Списъкът по-долу съдържа всички профили, които поддържат разговори с повече участници. Изберете този, в който желаете да създадете нова стая. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Списъкът по-долу съдържа всички регистрирани профили. Изберете този, който желаете да ползвате за разговори с новия контакт. -service.gui.SELECT_PROVIDERS_WIZARD=Изберете профил(и) service.gui.SELECT_VIDEO_CONFERENCE=Избери видео конференция service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Изберете чат стая от списъка и натиснете ОК да я добавите. service.gui.SEND=&Изпрати service.gui.SEND_FILE=Изпрати &файл -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Няма информация за този контакт. service.gui.SEND_MESSAGE=&Изпрати съобщение -service.gui.SEND_AS_SMS=Изпратете като SMS service.gui.SEND_PRIVATE_MESSAGE=Изпрати поверително съобщение service.gui.SEND_SMS=И&зпрати SMS service.gui.SEND_SMS_DETAILS=Не забравяйте да въведете и международния телефонен код. За български номера например започнете с +359 @@ -545,7 +515,6 @@ service.gui.STREET=Улица service.gui.SUBJECT=Тема service.gui.SUMMARY=Обобщение service.gui.TELEPHONY=Телефония -service.gui.TODAY=Днес service.gui.TOOLS=&Инструменти service.gui.TRANSFER=Трансфер service.gui.TO=На: @@ -555,7 +524,6 @@ service.gui.TRANSFER_CALL_TO=Прехвърли към: service.gui.TRANSPARENCY_NOT_ENABLED=Прозрачността не се поддържа от текущата ви конфигурация. service.gui.TYPE_YOUR_REQUEST=Въведете молбата си тук service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Не успяхме да променим видео качеството на обаждането. -service.gui.UNMUTE=Активирай микрофона service.gui.USER_IDENTIFIER=Номер: service.gui.USER_EXISTS_ERROR=Потребителят вече съществува на избраната мрежа. Моля изберете друг потребител или друга мрежа. service.gui.USERNAME_NULL=Моля въведете име и парола. @@ -568,7 +536,6 @@ service.gui.USE_PROVISIONING=Конфигуриране от мрежата (З service.gui.VALUE=Стойност service.gui.VIDEO_CALL=&Видео обаждане service.gui.VIA=през -service.gui.VIA_SMS=По СМС service.gui.VIEW=&Преглед service.gui.VIEW_HISTORY=Преглед на &историята service.gui.VIEW_SMILEYS=Показвай &усмивките @@ -588,9 +555,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Нагласяване силата на з service.gui.WAITING_AUTHORIZATION=Чакаме на оторизация service.gui.WARNING=Предупреждение service.gui.YES=Да -service.gui.YESTERDAY=Вчера -service.gui.EXISTING_ACCOUNT_ERROR=Въведеният профил е вече инсталиран. -service.gui.NEW_MAIL=Имате един нов мейл!
    От: {0} {1}
    Заглавие: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Получихте ново писмо във вашата {0} кутия:
    service.gui.NEW_GMAIL_MANY_HEADER=Получихте {2} нови писма във вашата {0} кутия:
    service.gui.NEW_GMAIL_FOOTER=Остава оше един непрочетен разговор във вашата кутия.
    @@ -614,7 +578,6 @@ service.gui.SECURITY_ERROR=Грешка в сигурността service.gui.SPEED=Скорост: service.gui.SILENT_MEMBER=тих член service.gui.NON_SECURE_CONNECTION=Невъзможно е да се установи сигурна връзка за профил {0}. Ако искате да се свържете по незащитен начин, моля отметнете полето "Разреши незащитено свързване" в настройките на профила си. -service.gui.UPDATE=Обновяване service.gui.MOBILE_PHONE=Мобилен service.gui.VIDEO_PHONE=Видео service.gui.WORK_PHONE=Работен @@ -649,12 +612,10 @@ service.gui.callinfo.CALL_INFORMATION=Информация за обаждане service.gui.callinfo.CALL_IDENTITY=Самоличност service.gui.callinfo.PEER_COUNT=Брой участници service.gui.callinfo.IS_CONFERENCE_FOCUS=Конферентен фокус -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Активирано криптиране service.gui.callinfo.CALL_TRANSPORT=Сигнализационен транспорт service.gui.callinfo.CALL_DURATION=Продължителност service.gui.callinfo.TLS_PROTOCOL=TLS протокол service.gui.callinfo.TLS_CIPHER_SUITE=TLS шифър -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=верига на сървърния TLS сертификат service.gui.callinfo.TLS_CERTIFICATE_CONTENT=Следва съдържанието на сървърния TLS сертификат: service.gui.callinfo.VIEW_CERTIFICATE=Преглед на сертификат service.gui.callinfo.CODEC=Кодек / Честота @@ -664,7 +625,6 @@ service.gui.callinfo.AUDIO_INFO=Аудио инфо service.gui.callinfo.VIDEO_INFO=Видео инфо service.gui.callinfo.LOCAL_IP=Локален IP / Порт service.gui.callinfo.REMOTE_IP=Отсрещен IP / Порт -service.gui.callinfo.BANDWITH=Дебит service.gui.callinfo.LOSS_RATE=% Загуба service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Джитър @@ -674,10 +634,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Обмяна на ключове service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE кандидати service.gui.callinfo.ICE_STATE=ICE състояние + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Събиране на кандидати service.gui.callinfo.ICE_STATE.RUNNING=Connectivity checks service.gui.callinfo.ICE_STATE.COMPLETED=Завършен service.gui.callinfo.ICE_STATE.FAILED=Провал + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Локален IP / Порт service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Продължителност на жътвата service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Локален пренасочван IP / Порт @@ -698,11 +661,12 @@ service.gui.ALWAYS_TRUST=Занапред винаги се доверявай service.gui.CERT_DIALOG_TITLE=Проверка на сертификата service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} не можа да провери самоличността на сървър
    {1}.

    .Сървърът използва непознат или недоверен сертификат, което означава, че самоличността на сървъра не може да бъде автоматично потвърдена.

    Желаете ли да се свържете въпреки това?
    За повече информация натиснете "Покажи сертификата" service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} не можа да провери самоличността на сървъра.

    Сървърът използва непознат или недоверен сертификат, което означава, че самоличността на сървъра не може да бъде автоматично потвърдена. Желаете ли да се свържете въпреки това?

    За повече информация натиснете "Покажи сертификата" -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} не можа да провери самоличността на клиента {1}:{2}.

    Събеседникът ви използва непознат или недоверен сертификат, което означава, че самоличността му не може да бъде автоматично потвърдена. Желаете ли да се свържете въпреки това?

    За повече информация натиснете "Покажи сертификата" service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} не можа да провери самоличността на събеседника {1}.

    Сертификатът е недоверен или непознат , което пречи проверката да бъде
    извършена автоматично. Желаете ли да се свържете въпреки това?

    За повече информация натиснете "Покажи сертификата". service.gui.CONTINUE_ANYWAY=Продължавам въпреки това service.gui.CERT_INFO_CHAIN=Верига от сертификати: service.gui.CERT_INFO_ISSUED_TO=Издаден за + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Обичайно име: service.gui.CERT_INFO_O=Организация: service.gui.CERT_INFO_C=Държава: @@ -721,12 +685,10 @@ service.gui.CERT_INFO_SIGN_ALG=Алгоритъм на подписа: service.gui.CERT_INFO_PUB_KEY_INFO=Информация за публичен ключ service.gui.CERT_INFO_ALG=Алгоритъм: service.gui.CERT_INFO_PUB_KEY=Публичен ключ: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} байтове: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} битове service.gui.CERT_INFO_EXP=Експонента: service.gui.CERT_INFO_KEY_SIZE=Размер на ключа: service.gui.CERT_INFO_SIGN=Подпис: -service.gui.CONTINUE=Продължи service.gui.SHOW_CERT=Покажи сертификата service.gui.HIDE_CERT=Скрий сертификата @@ -749,12 +711,9 @@ service.gui.security.SECURE_AUDIO=Защитено аудио service.gui.security.AUDIO_NOT_SECURED=Незащитено аудио service.gui.security.SECURE_VIDEO=Защитено видео service.gui.security.VIDEO_NOT_SECURED=Незащитено видео -service.gui.security.NO_VIDEO=Няма видео -service.gui.security.CIPHER=Шифър: {0} service.gui.security.CALL_SECURED_TOOLTIP=Защитено обаждане. За повече информация натиснете тук. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Незащитено обаждане. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Натиснете тук за да сравните тайната парола с партньора си. -service.gui.security.COMPARE_WITH_PARTNER=Сравнете със събеседника си и натиснете катинарчето ако съвпадат. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Сравнете със събеседника си: service.gui.security.STRING_COMPARED=Паролата е сравнена! @@ -772,20 +731,14 @@ service.gui.avatar.imagepicker.CLICK=Натисни и се усмихни service.gui.avatar.imagepicker.IMAGE_FILES=Файлове service.gui.avatar.imagepicker.IMAGE_PICKER=Картинка service.gui.avatar.imagepicker.IMAGE_SIZE=Размер на картинката -service.gui.avatar.imagepicker.INITIALIZING=Инициализиране service.gui.avatar.imagepicker.RESET=Реинициализация service.gui.avatar.imagepicker.SET=Сложи service.gui.avatar.imagepicker.TAKE_PHOTO=Направи снимка -service.gui.avatar.imagepicker.WEBCAM_ERROR=Проблем с камерката service.gui.security.encryption.required=Изисква се криптиране! service.protocol.ICE_FAILED=Не може да се осъществи връзка (неуспешен ICE, не е намерено реле) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Грешка при съхраняване на СИП списъка с контакти impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Не можем да прочетем ресурс {0}. За {1} @@ -815,9 +768,7 @@ impl.ldap.QUERY_CUSTOM=Персонализиране на заявката impl.ldap.QUERY_CUSTOM_HINT=Използвайте като заместител на търсения текст. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Автоматично разширяване на заявката до всички подобни резултати impl.ldap.QUERY_PHOTO_INLINE=Изтегляне на снимката заедно с атрибутите -impl.ldap.NEW=&Нов impl.ldap.EDIT=промени -impl.ldap.REMOVE=Премахни impl.ldap.ENABLED=Активиран impl.ldap.SERVER_NAME=Име impl.ldap.SERVER_NAME_EXAMPLE=Моят LDAP указател @@ -850,6 +801,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=homePhone impl.ldap.PHONE_PREFIX=Телефонен префикс impl.ldap.PHONE_PREFIX_EXAMPLE=Пр.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Адресник plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Активирай търсенето в адресника на Mac OS X @@ -864,9 +819,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Outlook приложение п # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google Контакти -impl.googlecontacts.NEW=Нов impl.googlecontacts.EDIT=промени -impl.googlecontacts.REMOVE=Премахни impl.googlecontacts.ENABLED=Активиран impl.googlecontacts.ACCOUNT_NAME=Име на профил impl.googlecontacts.SAVE=Запази @@ -905,11 +858,8 @@ plugin.accountinfo.ORGANIZATION=Организация: plugin.accountinfo.JOB_TITLE=Длъжност: plugin.accountinfo.ABOUT_ME=За мен: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Снимки: plugin.accountinfo.GLOBAL_ICON=Използвай глобална иконка plugin.accountinfo.LOCAL_ICON=Използвай тази иконка: -plugin.accountinfo.CHANGE=Промени -plugin.accountinfo.ONLY_MESSAGE=Само съобщения # connection info plugin.connectioninfo.TITLE=Информация за връзката @@ -929,49 +879,12 @@ plugin.aimaccregwizz.USERNAME=АИМ потребилско име: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Потребителско име и парола plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Регистриране на нов профил plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Ако нямата профил при АИМ, натиснете тук за да се регистрирате. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Използвай ръчни настройки # branding plugin.branding.ABOUT_WINDOW_TITLE=Относно {0} plugin.branding.LOGO_MESSAGE=Телефония и съобщения с отворен код -plugin.branding.LOADING=Зареждане plugin.branding.ABOUT_MENU_ENTRY=Относно -plugin.branding.WELCOME_MESSAGE=
    The {1} е в процес на интензивна разработка. Версията която ползвате е експериментална и е ВЪЗМОЖНО ДА НЕ РАБОТИ както бихте очаквали. Моля обърнете се към {2} за повече информация.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Всички права запазени. Посетете http://jitsi.org.
    -plugin.branding.LICENSE=
    The Жици се разпространява под лиценз LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Речници -plugin.dictaccregwizz.ANY_DICTIONARY=Всички речници -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Всички речници от {0} -plugin.dictaccregwizz.FIRST_MATCH=Първи резултат -plugin.dictaccregwizz.NO_MATCH=Няма резултати -plugin.dictaccregwizz.MATCH_RESULT=Не са намерени дефиниции за "{0}", може би имахте предвид:\n -plugin.dictaccregwizz.INVALID_DATABASE=Текущия речник "{0}" вече не съществува на сървъра. -plugin.dictaccregwizz.INVALID_STRATEGY=Текущата стратегия не се поддържа от сървъра. -plugin.dictaccregwizz.PROTOCOL_NAME=Речник -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Протокол за достъп до он-лайн речници -plugin.dictaccregwizz.HOST=Адрес -plugin.dictaccregwizz.SERVER_INFO=Информация от сървъра -plugin.dictaccregwizz.STRATEGY_SELECTION=Избор на стратегия -plugin.dictaccregwizz.STRATEGY_LIST=Списък със стратегиите: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Стратегии на търсене -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Стратегиите се използват при търсене на подобни думи. Това е необходимо когато зададена от вас дума не е намерена във вида, в който е зададена и е нужно да се разшири търсенето. Стратегия "Префикс" например ще търси сред всички думи, които започват със зададената от вас дума. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Информация за Речник профила ви -plugin.dictaccregwizz.FIRST_ACCOUNT=Този асистент ще създаде профил свързан към dict.org.\n\nВ последствие ще можете да добавите нови профили и сървъри. Попълнете полето "Адрес" с речника който искате да добавите. -plugin.dictaccregwizz.THREAD_CONNECT=Свъзване към сървъра -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Неуспешен опит за свързване. Сървърът не съществува или не поддържа протокол Речник -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Изтегляне на стратегиите -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Не са намерени стратегии на сървъра -plugin.dictaccregwizz.POPULATE_LIST=Зареждане на списъка -plugin.dictaccregwizz.CLOSING_CONNECTION=Затваряне на връзката - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Преди да можете да използвате Фейсбук Чат, трябва да създадете "Потребителско име" (Username)
    чрез вашата Фейсбук страница ("Account Settings").


    Моля имайте предвид,че след като създадете Потребителското си име ще трябва да излезате от страницата. В някой случаи е възможно да се наложи да изчакате.
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Фейсбук чат протокол -plugin.facebookaccregwizz.PROTOCOL_NAME=Фейсбук -plugin.facebookaccregwizz.USERNAME=Потребителско име: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Потребителско име и парола + # generalconfig plugin.generalconfig.AUTO_START=Автоматично стартиране на {0} след включване на компютъра @@ -982,9 +895,6 @@ plugin.generalconfig.SHOW_HISTORY=Покажи plugin.generalconfig.HISTORY_SIZE=Скорошни съобщения в нови разговори plugin.generalconfig.SEND_MESSAGES_WITH=Изпращане на съобщенията с: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Отваряне на чат прозореца на преден план -plugin.generalconfig.ERROR_PERMISSION=Нямате привилегиите нужни за премахването на автоматичното стартиране -plugin.generalconfig.TRANSPARENCY=Прозрачност -plugin.generalconfig.ENABLE_TRANSPARENCY=Активиране на прозрачността plugin.generalconfig.DEFAULT_LANGUAGE=Език plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Промените ви ще бъдат отчетени след рестартиране на приложението. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% преведени @@ -1065,13 +975,10 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Коментар plugin.jabberaccregwizz.RESOURCE=Ресурс plugin.jabberaccregwizz.AUTORESOURCE=Автоматично генериране на ресурс plugin.jabberaccregwizz.PRIORITY=Приоритет -plugin.jabberaccregwizz.XMPP_ERROR=XMPP грешка plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Непозната XMPP грешка ({0}). Проверете, че името на сървъра е правилно. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Паролата ви не съответства. plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Изрично въвеждане на сървърни параметри -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Разширени настройки plugin.jabberaccregwizz.USE_ICE=Използване на ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Използване на ICE и Jingle от Google (тестово) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Автоматично откриване на STUN и TURN сървъри plugin.jabberaccregwizz.SUPPORT_TURN=Поддържа TURN plugin.jabberaccregwizz.TURN_USERNAME=TURN потребителско име @@ -1099,11 +1006,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Изключване на копие на plugin.jabberaccregwizz.DTMF_AUTO=Автоматично: Избор между RTP и Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Настройки на сървъра plugin.jabberaccregwizz.CHANGE_PASSWORD=Смени паролата на сметката -plugin.jabberaccregwizz.NEW_PASSWORD=Нова парола -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Потвърждаване на паролата plugin.jabberaccregwizz.PORT_FIELD_INVALID=Моля въведете валиден номер на порт за да продължите. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Сметката трябва да е включена, за да промените паролата. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Полето за парола е празно. plugin.jabberaccregwizz.TLS_REQUIRED=Конекцията не използва TLS, смяната на паролата няма да се осъществи. plugin.jabberaccregwizz.PASSWORD_CHANGED=Паролата беше сменена успешно plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Вашият XMPP сървър не позволява смяна на паролата. @@ -1117,21 +1021,6 @@ plugin.jabberaccregwizz.RESET=Реинициализация plugin.jabberaccregwizz.RESET_DESCRIPTION=Реинициализирай глобалните настройки plugin.jabberaccregwizz.DISABLE_JINGLE=Изключи Jingle (аудио и видео разговори с XMPP) -# mailbox -plugin.mailbox.OUTGOING=Изходящо съобщение -plugin.mailbox.INCOMING=Входящи съобщения: -plugin.mailbox.WAIT_TIME=Забавяне преди активиране на гласовата поща -plugin.mailbox.MAX_MESSAGE_TIME=Максимална продължителност на съобщенията -plugin.mailbox.CONFIRM=Потвърди -plugin.mailbox.DEFAULTS=По подразбиране -plugin.mailbox.MAILBOX=Гласова поща - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Протокол за връзка с MSN услугата -plugin.msnaccregwizz.USERNAME=Е-мейл: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Име и парола - # plugin manager plugin.pluginmanager.INSTALL=Инсталиране plugin.pluginmanager.UNINSTALL=Дезинсталация @@ -1160,7 +1049,6 @@ plugin.sipaccregwizz.SERVER_PORT=Порт на сървъра plugin.sipaccregwizz.PROXY=Прокси plugin.sipaccregwizz.PROXY_PORT=Порт за проксито plugin.sipaccregwizz.PREFERRED_TRANSPORT=Предпочитан транспортен протокол -plugin.sipaccregwizz.ADVANCED_OPTIONS=Разширени настройки plugin.sipaccregwizz.PROXY_OPTIONS=Настройки на проксито plugin.sipaccregwizz.PROXY_AUTO=Автоматично настройване на проксито plugin.sipaccregwizz.ENABLE_PRESENCE=Активирай чат и статуси на присъствие (SIMPLE) @@ -1180,8 +1068,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Автоматично: Избор между RTP plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband (в аудио потока) -plugin.sipaccregwizz.REGISTER=Регистрационни съобщения (REGISTER) -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Изрично задаване на сървърни настройки plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Активирай поддръжката за кодирани разговори plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Обявявай ZRTP поддръжката в сигнализационния протокол plugin.sipaccregwizz.AUTH_NAME=Име за оторизация @@ -1202,10 +1088,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Адрес за проверка на plugin.sipaccregwizz.NOT_SAME_PASSWORD=Паролата ви не съответства. plugin.sipaccregwizz.NO_CERTIFICATE= (използване на регулярен израз) plugin.sipaccregwizz.SAVP_OPTION=Обявяване на RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Изключено (обявяване само на RTP/AVP) plugin.sipaccregwizz.SAVP_OPTION_1=Задължително (предлагане и приемане само на RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Незадължително (предлагане на 1. RTP/SAVP и 2. RTP/AVP) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Активиране на S-Descriptor (също известно като SDES или SRTP) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Избери активните протоколи за криптиране и техния приоритет (най-предпочитания най-отгоре) plugin.sipaccregwizz.CIPHER_SUITES=Активирани шифри: plugin.sipaccregwizz.SECURITY_WARNING=
    {0} ще се опита автоматично да защити всичките ви разговори със ZRTP и ще ви уведоми звуково и визуално при установяването на сигурна връзка. Препоръчваме ви да променяте настройките по-долу само ако знаете какво точно правите.
    @@ -1219,15 +1105,6 @@ plugin.skinmanager.DEFAULT_SKIN=Скин по подразбиране plugin.skinmanager.ADD_NEW_SKIN=Добавяне на нов скин ... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Скин по подразбиране -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Модул за свързване към SSH машини -plugin.sshaccregwizz.USERNAME=Потребител: -plugin.sshaccregwizz.IDENTITY_FILE=Файл със самоличност: -plugin.sshaccregwizz.KNOWN_HOSTS=Познати машини: -plugin.sshaccregwizz.OPTIONAL=По избор -plugin.sshaccregwizz.ACCOUNT_DETAILS=Настройки на профила - # status update plugin.autoaway.AUTO_STATUS=Автоматично преминаване в режим Далече plugin.autoaway.ENABLE_CHANGE_STATUS=Промяна на статуса докато сте далече @@ -1275,22 +1152,6 @@ plugin.whiteboard.DESELECT=Отмени избор plugin.whiteboard.DELETE=Изтрий plugin.whiteboard.PROPERTIES=Свойства -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Протокол за чат на Yahoo! -plugin.yahooaccregwizz.USERNAME=Потребител: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Име и парола: - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Протокол Zeroconf (Бонжур) -plugin.zeroaccregwizz.FIRST_NAME=Име: -plugin.zeroaccregwizz.LAST_NAME=Фамилия: -plugin.zeroaccregwizz.EMAIL=Е-мейл: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Запазване на бонжур контактите? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Име и парола -plugin.zeroaccregwizz.USERID=Потребител - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Протокол за връзка с услугата Гугъл Толк @@ -1304,19 +1165,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, Портал за Инт plugin.iptelaccregwizz.USERNAME=Потребител plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Регистрация в iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=Интернет телефония и чат +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Потребител plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Напишете отново plugin.sip2sipaccregwizz.EMAIL=Адрес на ел. поща -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=За помощ по тази услуга отидете на
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Електронния адрес се използва при получаване на гласова поща,
    пропуснати повиквания и възстановяване на загубена парола -plugin.sip2sipaccregwizz.INFO_NOTE=За помощ по тази услуга отидете на http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Съществуващ sip2sip.info потребител -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Създайте безплатно нов sip2sip.info потребител - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=Интернет телефония и чат plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=За помощ по тази услуга отидете на
    http://ippi.fr @@ -1325,6 +1178,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Съществуващ ippi профил plugin.ippiaccregwizz.CREATE_ACCOUNT=Създаване на безплатен ippi профил # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Затваряне на чат прозореца plugin.keybindings.CHAT_COPY=&Копирай plugin.keybindings.CHAT_CUT=О&трежи @@ -1347,10 +1201,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Име plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Основна комбинация plugin.keybindings.globalchooser.SHORTCUT_SECOND=Втора комбинация plugin.keybindings.globalchooser.PRESS_BTN=Натиснете за да настроите -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Изчакване plugin.keybindings.globalchooser.PUSH_TO_TALK=Натисни за да говориш (режим радио станция) plugin.keybindings.globalchooser.ENABLE_SPECIAL=Засичане на специални клавиши plugin.keybindings.PLUGIN_NAME=Клавишни комбинации +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Чат plugin.keybindings.MAIN=Основни plugin.keybindings.GLOBAL=Глобални комбинации @@ -1378,6 +1232,7 @@ plugin.notificationconfig.tableheader.SOUND=Възпроизвеждане на plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Възпроизвеждане на звук през устройството за playback plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Възпроизвеждане на звук през говорителите plugin.notificationconfig.tableheader.DESCRIPTION=Описание на събитие +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Входящо обаждане plugin.notificationconfig.event.SecurityMessage=Сигурност plugin.notificationconfig.event.IncomingFile=Входящ файл @@ -1479,6 +1334,7 @@ impl.neomedia.configform.VIDEO=Видео impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Периодично вътрешно опресняване impl.neomedia.configform.H264.defaultProfile=Подразбиращ се профил на кодиране: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Базов (Baseline) impl.neomedia.configform.H264.defaultProfile.high=Висококачествен (High) impl.neomedia.configform.H264.defaultProfile.main=Главен (Main) @@ -1509,7 +1365,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Настояща паро plugin.securityconfig.masterpassword.ENTER_PASSWORD=Въведете нова парола: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Въведете отново: plugin.securityconfig.masterpassword.MP_TITLE=Главна парола -plugin.securityconfig.masterpassword.MP_NOT_SET=(невъведена) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Въведохте грешна главна парола. Опитайте отново! plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Грешна главна парола! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Неуспешна смяна на паролата @@ -1621,7 +1476,6 @@ plugin.globalproxy.PROXY_PORT=Прокси порт plugin.globalproxy.PROXY_USERNAME=Потребител за проксито plugin.globalproxy.PROXY_PASSWORD=Парола за проксито plugin.globalproxy.DESCRIPTION={0} ще използва прокси настройките за всички мрежи към които се свързва отсега нататък.\nПоддръжката на прокси сървъри в момента е експериментална. За справки таблицата по-долу: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Посредничи също и DNS plugin.globalproxy.FWD_DNS_NOTE=Полезно с Тор. Помага за избягване на DNS утечки чрез препредаване на целия DNS трафик към Тор проксито. Изисква рестарт. @@ -1659,7 +1513,6 @@ plugin.provisioning.RESTART_WARNING=Промените ви ще се отраз plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Копиране на уникалния идентификатор plugin.provisioning.CLIPBOARD_FAILED=Грешка при копирането -plugin.provisioning.EXIT_ON_FAIL=Излезте от приложението ако мрежовото настройване се провали plugin.provisioning.CREDENTIALS=Последно запаметена парола за настройването plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Сигурни ли сте, че искате да изтриете паролата за мрежово настройване? plugin.provisioning.PROV_FAILED=Захранването пропадна @@ -1726,8 +1579,6 @@ util.dns.DNSSEC_WARNING=
    {0} се опита да се в #plugin spellcheck plugin.spellcheck.TITLE=Правопис и граматика plugin.spellcheck.MENU=Покажи правописа и граматиката -plugin.spellcheck.LANG=Език -plugin.spellcheck.EDIT_PERSONAL_DICT=Редактирай plugin.spellcheck.ENABLE_SPELL_CHECK=Активирай проверката на правописа plugin.spellcheck.dialog.FIND=Намери отново plugin.spellcheck.dialog.REPLACE=Замени -- cgit v1.1 From 26c0bdf5642af50b8d525af1f9400004813e8553 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:59:37 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 951 of 1505 strings translated (64 fuzzy). --- resources/languages/resources_pt.properties | 195 +++++++--------------------- 1 file changed, 47 insertions(+), 148 deletions(-) diff --git a/resources/languages/resources_pt.properties b/resources/languages/resources_pt.properties index 3f959e5..037763c 100644 --- a/resources/languages/resources_pt.properties +++ b/resources/languages/resources_pt.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Eu service.gui.ACCOUNT_REGISTRATION_WIZARD=Assistente de criação de contas service.gui.ACCOUNTS=Contas service.gui.ADD=&Adicionar -service.gui.ADD_ACCOUNT=Adicionar conta service.gui.ADD_CONTACT=&Adicionar contato service.gui.ADD_AUTHORIZED_CONTACT=Adicionar {0} a sua lista de contatos service.gui.ADD_CONTACT_TO_CONTACTLIST=Adicionar este contato à sua lista @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Erro na adição do contato service.gui.ADD_CONTACT_EXIST_ERROR=O contato {0} já existe na sua lista de contatos. service.gui.ADD_CONTACT_NETWORK_ERROR=O servidor não respondeu ao seu pedido de adição de contato com o id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Falha ao adicionar o contato de ID: {0}. Operação não suportada. -service.gui.ADD_CONTACT_IDENTIFIER=Insira no campo abaixo o identificador do contato que pretende adicionar. -service.gui.ADD_CONTACT_WIZARD=Assistente para adicionar contato service.gui.ADD_CONTACT_NOT_CONNECTED=Você precisa de estar conectado para poder adicionar um contacto. Por favor registre-se no provedor selecionado e tente novamente. service.gui.ADD_GROUP_LOCAL_ERROR=Não foi possível adicionar o grupo com o nome: {0}. O problema ocorreu durante uma operação de IO local. service.gui.ADD_GROUP_EXIST_ERROR=O grupo {0} já existe na sua lista de contatos. Escolha outro nome. service.gui.ADD_GROUP_NET_ERROR=Não foi possível adicionar o grupo com o nome: {0}. O problema ocorreu devido a uma falha de rede. Por favor verifique a sua conexão de rede e tente de novo. service.gui.ADD_GROUP_ERROR=Não foi possível adicionar o grupo com o nome: {0}. service.gui.ADD_GROUP_EMPTY_NAME=O nome do grupo não pode estar vazio. -service.gui.ADD_GROUP=Criar grupo -service.gui.ADD_SUBCONTACT=&Adicionar subcontato service.gui.ADDRESS=Endereço service.gui.ADMINISTRATOR=administrador service.gui.ADVANCED=&Avançadas -service.gui.ALL=&Todos service.gui.ALL_CONTACTS=&Todos os contactos service.gui.ALTERNATE_ADDRESS=Endereço alternativo service.gui.APPLY=&Aplicar @@ -65,7 +70,6 @@ service.gui.AT=em service.gui.AUTHORIZE=&Autorizar service.gui.AUTHORIZATION_ACCEPTED={0} rejeitou o seu pedido de autorização. service.gui.AUTHENTICATION_FAILED=Falha na autenticação da conta para {0}. A senha utilizada é inválida. -service.gui.AUTHENTICATION_REQUESTED=Pedido de autorização submetido service.gui.AUTHENTICATION_REQUESTED_SERVER=O {0} servidor pede que se autentique. service.gui.AUTHENTICATION_REJECTED={0} rejeitou o seu pedido de autorização. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autenticação @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=No campo em baixo, pode inserir a sua nova alc service.gui.CHANGE_NICKNAME_ERROR=Erro ao alterar a alcunha service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nome já existe service.gui.CHANGE_VIDEO_QUALITY=Mudar a qualidade do video remoto -service.gui.CHAT_CONFERENCE_LABEL=Conferencias service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}''s conferencia service.gui.CHAT_ROOM_ALREADY_JOINED=Já está participando na sala {0}. service.gui.CHAT_ROOM_CONFIGURATION=configuração da sala {0} @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT={0} saiu da sala service.gui.CHAT_ROOM_USER_KICKED={0} foi expulso da sala service.gui.CHAT_ROOM_USER_QUIT={0} saiu da sala service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=O envio da mensagem foi negado (voz não permitida) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Salvar a sala de conversa para usos futuros -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Eliminar a sala de conversa selecionada da lista de salas salvas service.gui.CHAT_ROOM_NAME=Nome da sala service.gui.CLEAR_CUSTOM_MESSAGES=Limpar mensagens personalizadas service.gui.ROOM_NAME=Sala de conversa -service.gui.AUTOJOIN=Participar automaticamente service.gui.CHANGE_PASSWORD=Mudar password service.gui.CHAT_ROOM_NAME_INFO=Insira no campo abaixo o nome da sala que pretende criar. service.gui.CHAT_ROOM_NOT_EXIST=A sala {0} não foi encontrada no servidor {1}. Por favor verifique se inseriu o nome correctamente. service.gui.CHAT_ROOM_NOT_CONNECTED=Precisa estar ligado para poder entrar na sala {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Precisa estar ligado para poder sair de uma sala. -service.gui.CHAT_ROOM_NOT_JOINED=Você tem de estar a participar numa sala para poder realizar operações sobre ela. service.gui.CHAT_ROOM_OPTIONS=Opções da sala service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Precisa estar registado para poder entrar na sala {0}. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=A sala {0} necessita que insira uma palavra-passe. @@ -150,22 +149,18 @@ service.gui.CLEAR=Limpar service.gui.CLOSE=Fechar service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Você recebeu uma nova mensagem há menos de 2 segundos. Tem a certeza que deseja fechar esta conversa? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Você tem transferências de ficheiros activas. Tem a certeza que as deseja cancelar? -service.gui.CONFIRM=Confirmar service.gui.CONNECTED_STATUS=Ligação estabelecida service.gui.CONNECTING=Ligando-se... service.gui.CONNECTING_STATUS=Ligando-se service.gui.CONNECTING_EARLY_MEDIA_STATUS=Conectando* service.gui.CONNECTION=Ligação -service.gui.CONNECTION_FAILED_MSG=A ligação falhou para a seguinte conta: Nome de utilizador: {0}, Nome do servidor: {1}. POr favor verifique a sua ligação de rede ou contacte o seu administrador de rede para mais informação. service.gui.CONNECTION_EXPIRED_MSG=Você encontra-se de momento desligado do servidor {0}. service.gui.CONTACT_NAME=ID ou número -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=O contacto {0} não suporta chamadas. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=O contacto {0} não suporta conferências de mensagens escritas. service.gui.CONTACT_PAUSED_TYPING={0} parou de escrever a mensagem service.gui.CONTACT_TYPING={0} está a escrever uma messagem service.gui.CONTACT_TYPING_SEND_FAILED=hoooo... não conseguimos dizer se {0} está a escrever service.gui.CONTACT_INFO=&Informação do contacto -service.gui.CONTACTLIST=Lista de contato service.gui.CONTACTS=Contactos service.gui.COPY=&Copiar service.gui.COPY_LINK=Copiar &hiperligação @@ -175,17 +170,14 @@ service.gui.CREATE_CHAT_ROOM=&Criar sala de conversa... service.gui.CREATE_CHAT_ROOM_ERROR=Falha na criação da sala com o nome: {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Assistente de criação de sala service.gui.CREATE_CONFERENCE_CALL=&Criar uma chamada com múltiplos participantes... -service.gui.CREATE_CONFERENCE_CHAT=&Iniciar uma conversa com múltiplos participantes... service.gui.CREATE_GROUP=&Criar grupo... service.gui.CREATE_GROUP_NAME=Insira no campo abaixo o nome do grupo que pretende criar. -service.gui.CREATE_FIRST_GROUP_WIZARD=A sua lista de contactos não contêm grupos. Por favor primeiro crie um grupo (Ficheiro/Criar grupo). service.gui.CREATE_VIDEO_BRIDGE=Criar uma ligação de video... service.gui.CREATE_VIDEO_BRIDGE_MENU=Criar uma ligação de video service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Crie / Junte-se a uma videoconferencia service.gui.CREATE_VIDEO_CONFERENCE=Crie uma nova videoconferencia para esta sala de conversa service.gui.CONTACT_INFO_NOT_SUPPORTED=Este contacto não suporta informação de contacto via web service.gui.CUT=C&ortar -service.gui.DATE=Data service.gui.DELETE=Apagar service.gui.DENY=&Negar service.gui.DESKTOP_SHARING_WARNING=Tem a certeza que deseja iniciar o compartilhamento de tela?
    Clique em OK para as pessoas nesta conversa verem sua tela. @@ -195,7 +187,6 @@ service.gui.DISCONNECTED_STATUS=Desconectado service.gui.DND_STATUS=Não perturbar service.gui.DO_NOT_ASK_AGAIN=Não pergunte de novo service.gui.DO_NOT_SHOW_AGAIN=Não mostrar esta mensagem novamente -service.gui.DOWNLOAD_NOW=&Baixar agora service.gui.DRAG_FOR_SHARING=Arraste para aqui qualquer coisa que deseje partilhar... service.gui.DURATION=duração service.gui.DESTROY_CHATROOM=Destruir sala de conversação @@ -216,7 +207,6 @@ service.gui.ERROR_RECEIVED_FROM=Erro recebido de {0} service.gui.ESTIMATED_TIME=Tempo estimado: service.gui.EVENTS=Eventos service.gui.EXIT=S&air -service.gui.EXTENDED_CRITERIA=Critérios alargados service.gui.GENERAL=Geral service.gui.GENERAL_ERROR=Erro geral service.gui.GROUP_NAME=Nome do grupo @@ -258,7 +248,6 @@ service.gui.FONT_ITALIC=Itálico service.gui.FONT_SIZE=Tamanho service.gui.FONT_STYLE=Estilo service.gui.FONT_UNDERLINE=Sublinhado -service.gui.FROM={0} de {1} service.gui.GRANT_OWNERSHIP=Conceder a posse... service.gui.GRANT_ADMIN=Conceder administrador... service.gui.GRANT_MODERATOR=Conceder categoria de moderador @@ -284,12 +273,12 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Tem certeza que deseja remover permanente service.gui.HISTORY_REMOVE_ERROR=Erro ao remover as mensagens armazenadas localmente. service.gui.HOME=Casa service.gui.HOME_PAGE=Página inicial -service.gui.HOUR=Hora service.gui.ICE=ICE service.gui.IDENTIFIER=Identificador service.gui.IGNORE=&Ignorar service.gui.INSERT_SMILEY=Inserir smiley service.gui.INCOMING_CALL=Chamadas recebidas de: {0} +service.gui.INCOMING_SCREEN_SHARE=Chamadas recebidas de: {0} service.gui.INCOMING_CALL_STATUS=Chamada recebida service.gui.INSTANT_MESSAGINGS=IM's service.gui.IM=IM @@ -306,13 +295,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Convidar contactos para a videoconfer service.gui.INVITE_REASON=Razão do convite service.gui.IS_CALLING={0} está a chamar... service.gui.IS_NOW={0} está {1} -service.gui.JITSI_WARNING=O SIP Communicator foi recentemente renomeado para Jitsi.
    Se pretender manter a sua versão actualizada, faça o download do Jitsi agora.

    Pedimos desculpa por qualquer inconveniente que possa causar-lhe.

    A equipa de desenvolvimento do Jisti -service.gui.JITSI_WARNING_TITLE=O SIP Comunicator tornou-se Jitsi service.gui.JOIN=&Entrar service.gui.JOIN_AS=E&ntrar como service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Associar-se a uma videoconferência existente service.gui.JOIN_VIDEO=Juntar video -service.gui.CLOSE_CHAT_ROOM_DIALOG=F&echar service.gui.JOB_TITLE=Cargo service.gui.JOIN_CHAT_ROOM=&Entrar no chat room... service.gui.JOIN_CHAT_ROOM_TITLE=Entrar no chat room @@ -325,7 +311,6 @@ service.gui.KICK_FAILED=Falha na expulsão service.gui.KICK_FAILED_GENERAL_ERROR=Falha na expulsão {0}. Um erro geral do servidor ocorreu. service.gui.KICK_FAILED_NOT_ALLOWED=Falha na expulsão {0}. Não foi possível expulsar o proprietário e o administrador da sala. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Falha na expulsão {0}. Voçê não tem previlégios para a operação desejada. -service.gui.LAST=Último service.gui.LAST_NAME=Apelido service.gui.LEAVE=&Abandonar service.gui.LIMIT_REACHED_FOR_IP=Você tem demasiados registos em uso a partir do mesmo endereço IP local, o {0} servidor não permite abrir mais registos. @@ -345,7 +330,6 @@ service.gui.MESSAGE=Mensagem service.gui.MISSED_CALLS_TOOL_TIP=Chamadas perdidas de: service.gui.MISSED_CALLS_MORE_TOOL_TIP= e {0} mais service.gui.MODERATOR=moderador -service.gui.MORE=Ver mais service.gui.MORE_LABEL=Mais service.gui.MOVE=Mover service.gui.MOVE_SUBCONTACT=M&over contacto @@ -354,7 +338,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=O contato que escolheu é o mesmo que o \n co service.gui.MOVE_SUBCONTACT_QUESTION=Tem a certeza que pretende mover {0} para {1}? service.gui.MOVE_TO_GROUP=&Mover para o grupo service.gui.MOVE_CONTACT=M&over Subcontato -service.gui.MOVE_CONTACT_ERROR=&Não é possível mover o contacto service.gui.MSG_DELIVERY_FAILURE=Não foi possível entregar a mensagem acima service.gui.MSG_DELIVERY_NOT_SUPPORTED=O protocolo que está a usar não suporta mensagens em offline. Pode tentar alcançar {0} usando outro protocolo ou esperar até que ele/ela fique disponível. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Um erro interno ocorreu. Isto é provavelmente um bug. Por favor informe em: https://jitsi.org/Development/BugsAndIssues. @@ -368,7 +351,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Necessita estar ligado para poder enviar service.gui.MULTIPLE_LOGINS=Ligou mais de uma vez com a mesma conta. A conta seguinte: Nome de usuário: {0}, Nome do servidor: {1} encontra-se desligada de momento. service.gui.MY_CHAT_ROOMS=Adicionar sala de conversação service.gui.MY_CHAT_ROOMS_TITLE=Adicionar sala de conversação -service.gui.MUTE=Silenciar service.gui.MUTUALLY_ON_HOLD_STATUS=Ambos em espera service.gui.NAME=Nome service.gui.NETWORK=Rede @@ -379,6 +361,7 @@ service.gui.NEW_MESSAGE=Nova mensagem service.gui.NEW_NAME=Novo nome service.gui.NEW_STATUS_MESSAGE=Nova mensagem de estado service.gui.NEW_STATUS_MESSAGE_SAVE=Guardar como mensagem personalizada +service.gui.NICKNAME=Alcunha service.gui.NO=Não service.gui.NONE=Nenhum service.gui.NO_CAMERA_AVAILABLE=Nenhuma câmara disponivel @@ -399,7 +382,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Nao está na lista de contactos service.gui.SD_QUALITY=Qualidade normal service.gui.OFFLINE=Desligado service.gui.OK=&OK -service.gui.OLDER_CALLS=Chamadas antigas service.gui.ONLINE=Ligado service.gui.OPEN=Abrir service.gui.OPEN_FILE_FROM_IMAGE=Duplo clique para abrir o ficheiro. @@ -411,9 +393,12 @@ service.gui.OPEN_ON_ACTIVITY=Aberto em actividade service.gui.OPEN_ON_MESSAGE=Aberto apenas com mensagem service.gui.OPEN_ON_IMPORTANT_MESSAGE=Aberto apenas com mensagens importantes service.gui.OR=ou -service.gui.OR_ENTER_PHONE_NUMBER=Ou insira o número de telefone aqui... service.gui.ORGANIZATION=Organização service.gui.OTHER=Outro +service.gui.chat.role.ADMINISTRATOR=administrador +service.gui.chat.role.MODERATOR=moderador +service.gui.chat.role.MEMBER=membro +service.gui.chat.role.SILENT_MEMBER=membro silencioso service.gui.OWNER=dono da sala service.gui.ON_MOBILE_TOOLTIP=(no telemóvel) service.gui.PASSWORD=Palavra-passe @@ -430,7 +415,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' para sugestões service.gui.PRESS_FOR_CALL_INFO=Prima para informações de chamada service.gui.PRESS_TO_OPEN_CRM=Prima para abrir a aplicação de CRM service.gui.PREVIOUS=Anterior -service.gui.PREVIOUS_TOOLTIP=Procure conversações antigas service.gui.PRINT=&Imprimir service.gui.PROACTIVE_NOTIFICATION=está escrevendo uma mensagem service.gui.PROBLEMS_ENCOUNTERED=Encontrados problemas @@ -446,7 +430,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Voçê está ligando e religando-se ao s service.gui.RE_REQUEST_AUTHORIZATION=Voltar a pedir autorização service.gui.REFERRED_STATUS=Mencionados service.gui.REJECT=&Rejeitar -service.gui.REMIND_ME_LATER=Lembrar-me mais tarde service.gui.REMEMBER_PASSWORD=Lembrar palavra-chave service.gui.REMOVE=&Remover service.gui.REMOVE_ACCOUNT=&Remover conta @@ -472,29 +455,20 @@ service.gui.REVOKE_ADMIN=Retirar estado de administrador service.gui.REVOKE_MODERATOR=Retirar estado de moderador service.gui.REVOKE_MEMBERSHIP=Retirar estado de membro service.gui.REVOKE_VOICE=Retirar voz -service.gui.ROOT_GROUP=Grupo raiz service.gui.SAVE=&Salvar -service.gui.SAVE_AS_DEFAULT=Salvar como por defeito service.gui.SEARCH=&Buscar service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Clique no botão de baixo para mostrar todos os chat rooms existentes no servidor selecionado. Depois escolha o chat room que pretende participar e clique no botão Entrar. service.gui.SEARCH_STRING_CONTACT_SOURCE=Contacto procurado service.gui.SECURITY=Segurança -service.gui.SELECT_ACCOUNT=Escolher conta service.gui.SELECT_COLOR=Escolher cor service.gui.SELECT_GROUP=Escolher grupo -service.gui.SELECT_GROUP_WIZARD_MSG=A lista abaixo contém todos os grupos a sua Lista de Contatos. Escolha um grupo aonde gostaria de adicionar o novo contato. service.gui.SELECT_NO_GROUP=Sem grupo -service.gui.SELECT_GROUP_WIZARD=Escolher grupo service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=A lista abaixo contém todas as contas que suportam a função de chat com múltiplos usuários. Selecione a lista que pretende usar para a criação do seu chat room. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=A lista abaixo contém todas as contas registadas. Selecione uma das listas que pretende usar para se comunicar com o novo contato. -service.gui.SELECT_PROVIDERS_WIZARD=Selecionar conta service.gui.SELECT_VIDEO_CONFERENCE=Seleccionar videoconferencia service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Seleccione uma conversação da lista e pressione OK para a adicionar. service.gui.SEND=&Enviar service.gui.SEND_FILE=E&nviar ficheiro -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Não existe informação sobre este contato. service.gui.SEND_MESSAGE=&Enviar uma mensagem -service.gui.SEND_AS_SMS=Enviar como SMS service.gui.SEND_PRIVATE_MESSAGE=Enviar uma mensagem privada service.gui.SEND_SMS=Enviar SMS service.gui.SEND_SMS_DETAILS=Lembre-se que tem de introduzir o numero no formato internacional; iniciar com +44 para UK; por exemplo: +447777000000 @@ -533,7 +507,6 @@ service.gui.STREET=Rua service.gui.SUBJECT=Assunto service.gui.SUMMARY=Sumário service.gui.TELEPHONY=Telefonia -service.gui.TODAY=Hoje service.gui.TOOLS=&Ferramentas service.gui.TRANSFER=Transferencia service.gui.TO=&Para: @@ -543,7 +516,6 @@ service.gui.TRANSFER_CALL_TO=Transferir para: service.gui.TRANSPARENCY_NOT_ENABLED=Transparência não é suportada pela configuração actual. service.gui.TYPE_YOUR_REQUEST=Escreva o seu pedido aqui service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Não fomos capazes de alterar a qualidade do vídeo para esta chamada. -service.gui.UNMUTE=Ativar som service.gui.USER_IDENTIFIER=Identificador do utilizador: service.gui.USER_EXISTS_ERROR=Este utilizador já existe na rede seleccionada. Escolha outro utilizador ou outra rede. service.gui.USERNAME_NULL=Preencha com o seu nome de utilizador e password. @@ -556,7 +528,6 @@ service.gui.USE_PROVISIONING=Use provisionamento online service.gui.VALUE=Valor service.gui.VIDEO_CALL=&Chamada de vídeo service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Visualizar service.gui.VIEW_HISTORY=Mostrar &histórico service.gui.VIEW_SMILEYS=Mostrar &smileys @@ -576,9 +547,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Ajustar o volume service.gui.WAITING_AUTHORIZATION=A aguardar autorização service.gui.WARNING=Aviso service.gui.YES=Sim -service.gui.YESTERDAY=Ontem -service.gui.EXISTING_ACCOUNT_ERROR=A conta que introduziu já está instalada. -service.gui.NEW_MAIL=Tem novo Correio!
    De: {0} {1}
    Assunto: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Recebeu novo correio no seu {0} inbox:
    service.gui.NEW_GMAIL_MANY_HEADER=Recebeu {2} novas mensagens na sua {0} inbox:
    service.gui.NEW_GMAIL_FOOTER=mais uma conversação por ler na sua inbox.
    @@ -602,7 +570,6 @@ service.gui.SECURITY_ERROR=Erro de segurança service.gui.SPEED=Velocidade: service.gui.SILENT_MEMBER=membro silencioso service.gui.NON_SECURE_CONNECTION=Pode ser feira uma conexão não segura pela conta {0}. Se pretender conectar-se a um servidor não seguro, marque "Permitir conexão não segura" na sua configuração da conta -service.gui.UPDATE=Actualizar service.gui.MOBILE_PHONE=Telemóvel service.gui.VIDEO_PHONE=Vídeo service.gui.WORK_PHONE=Trabalho @@ -637,12 +604,10 @@ service.gui.callinfo.CALL_INFORMATION=Informação de chamada service.gui.callinfo.CALL_IDENTITY=Identidade service.gui.callinfo.PEER_COUNT=Contador de participante service.gui.callinfo.IS_CONFERENCE_FOCUS=Realçar conferencia -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Encriptação activa service.gui.callinfo.CALL_TRANSPORT=Transporte da chamada de sinalização service.gui.callinfo.CALL_DURATION=Duração da chamada service.gui.callinfo.TLS_PROTOCOL=Protocolo TLS service.gui.callinfo.TLS_CIPHER_SUITE=Arquivo de cifras do TLS -service.gui.callinfo.TLS_SERVER_CERTIFICATE_CHAIN=Chave de certificação do servidor TLS service.gui.callinfo.TLS_CERTIFICATE_CONTENT=O conteudo do certificado do servidor TLS é apresentado abaixo. service.gui.callinfo.VIEW_CERTIFICATE=Mostrar certificado service.gui.callinfo.CODEC=Codec / Frequencia @@ -662,10 +627,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Protocolo de troca de chaves service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Candidado ICE de tipo extendido service.gui.callinfo.ICE_STATE=Estado de Processamento ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Reunir candidatos service.gui.callinfo.ICE_STATE.RUNNING=Verificações de ligação service.gui.callinfo.ICE_STATE.COMPLETED=Terminado service.gui.callinfo.ICE_STATE.FAILED=Falhou + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Computador local IP / Porta service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Reflexção local IP / Porta service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Retransmissão local IP / Porta @@ -686,9 +654,10 @@ service.gui.ALWAYS_TRUST=Sempre confiar neste certificado service.gui.CERT_DIALOG_TITLE=Verificar Certificado service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} não foi possivel verificar a identidade do servidor durante a ligação a
    {1}.

    O certificado não é confiavel, o quer quer dizer que a identidade do servidor não pode ser verificada automaticamente.

    Deseja continuar com a ligação?
    Para mais informações, clique em "Mostrar Certificado". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} não foi possivel verificar a identidade do certificado do servidor.

    O certificado não é confiavel, o que quer dizer que a identidade do servidor não pode
    ser verificada automaticamente. Deseja continuar com a ligação?

    Para mais informações clique em "Mostrar Certificado". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} não é possivel a identidade do cliente.

    O certificado não é confiavel, o que quer dizer que a identidade do cliente não pode
    ser verificada automaticamente. Deseja aceitar a ligação?

    Para mais informação, clique em "Mostrar Certificado". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} não é possiver verificar a identidade da origem {1}.

    O certificado não é confiavel, o que quer dizer que a identidade da origem não pode ser
    verificada automaticamente. Deseja prosseguir com a ligação?

    Para mais informações, clique em "Mostrar Certificado". service.gui.CONTINUE_ANYWAY=Continuar na mesma + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nome Comum: service.gui.CERT_INFO_O=Organização: service.gui.CERT_INFO_C=Nome do País: @@ -705,12 +674,10 @@ service.gui.CERT_INFO_SIGN_ALG=Algoritmo usado para a assinatura: service.gui.CERT_INFO_PUB_KEY_INFO=Informações de Chave Pública service.gui.CERT_INFO_ALG=Algoritmo: service.gui.CERT_INFO_PUB_KEY=Chave Publica: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Expoente: service.gui.CERT_INFO_KEY_SIZE=Tamanho da Chave: service.gui.CERT_INFO_SIGN=Assinatura: -service.gui.CONTINUE=Continuar service.gui.SHOW_CERT=Mostrar Certificado service.gui.HIDE_CERT=Esconder Certificado @@ -733,12 +700,9 @@ service.gui.security.SECURE_AUDIO=Audio seguro service.gui.security.AUDIO_NOT_SECURED=Audio não seguro service.gui.security.SECURE_VIDEO=Video seguro service.gui.security.VIDEO_NOT_SECURED=Video não seguro -service.gui.security.NO_VIDEO=Sem video -service.gui.security.CIPHER=Cifra: {0} service.gui.security.CALL_SECURED_TOOLTIP=Chamada segura. Para mais informações carregue aqui. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Chamada não segura. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Prima aqui pata comparar a sua segurança com a do seu parceiro. -service.gui.security.COMPARE_WITH_PARTNER=Verifique com o parceiro, e clique no cadeado para confirmar. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparar com o parceiro: service.gui.security.STRING_COMPARED=String comparada! @@ -756,20 +720,14 @@ service.gui.avatar.imagepicker.CLICK=Clique e Sorria service.gui.avatar.imagepicker.IMAGE_FILES=Ficheiros de imagem service.gui.avatar.imagepicker.IMAGE_PICKER=Imagem service.gui.avatar.imagepicker.IMAGE_SIZE=Tamanho da imagem -service.gui.avatar.imagepicker.INITIALIZING=Inicializando service.gui.avatar.imagepicker.RESET=Repor service.gui.avatar.imagepicker.SET=Definir service.gui.avatar.imagepicker.TAKE_PHOTO=Tirar fotografia -service.gui.avatar.imagepicker.WEBCAM_ERROR=Erro da camara service.gui.security.encryption.required=É requerida encriptação! service.protocol.ICE_FAILED=Não foi possivel estabelecer ligação (Falha de ICE e encaminhamento não encontrado) -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Erro no arquivo de contactos SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=O recurso não pode ser lido {0}. Para {1} @@ -799,9 +757,7 @@ impl.ldap.QUERY_CUSTOM=Consulta personalizada impl.ldap.QUERY_CUSTOM_HINT=Use {0} como um espaço reservado para o termo de pesquisa. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Adicionar automaticamente expressoes para termos de procura impl.ldap.QUERY_PHOTO_INLINE=Trazer foto juntamento com outros atributos. -impl.ldap.NEW=Novo impl.ldap.EDIT=editar -impl.ldap.REMOVE=Remover impl.ldap.ENABLED=Activo impl.ldap.SERVER_NAME=Nome do servidor impl.ldap.SERVER_NAME_EXAMPLE=Servidor LDAP @@ -834,6 +790,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=telefoneCasa impl.ldap.PHONE_PREFIX=Prefixo telefonico impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Livro de endereços plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Activar procura no Livro de Endereços do MacOSX @@ -848,9 +808,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Definir o Outlook como cliente # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Contactos do Google -impl.googlecontacts.NEW=Novo impl.googlecontacts.EDIT=Alterar -impl.googlecontacts.REMOVE=Remover impl.googlecontacts.ENABLED=Activo impl.googlecontacts.ACCOUNT_NAME=Nome da conta impl.googlecontacts.SAVE=Salvar @@ -869,6 +827,7 @@ plugin.accountinfo.DISPLAY_NAME=Mostrar nome: plugin.accountinfo.FIRST_NAME=Nome Próprio: plugin.accountinfo.MIDDLE_NAME=Nome do Meio: plugin.accountinfo.LAST_NAME=Apelido: +plugin.accountinfo.NICKNAME=Alcunha: plugin.accountinfo.URL=URL: plugin.accountinfo.AGE=Idade: plugin.accountinfo.BDAY=Data de Nascimento: @@ -888,11 +847,8 @@ plugin.accountinfo.ORGANIZATION=Nome da Organização plugin.accountinfo.JOB_TITLE=Cargo: plugin.accountinfo.ABOUT_ME=Acerca de mim: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Imagens do utilizador plugin.accountinfo.GLOBAL_ICON=Usar icone global plugin.accountinfo.LOCAL_ICON=Usar este icone: -plugin.accountinfo.CHANGE=Modificar -plugin.accountinfo.ONLY_MESSAGE=Só mensagens # connection info plugin.connectioninfo.TITLE=Informações da Ligação @@ -912,46 +868,11 @@ plugin.aimaccregwizz.USERNAME=Nome de utilizador do AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nome de usuário e senha plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Registrar nova conta plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Caso você não tenha uma conta AIM, clique neste botão para criar uma. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Substituir as opções predefinidas no servidor # branding plugin.branding.LOGO_MESSAGE=Open Source VoIP && Instant Messaging -plugin.branding.LOADING=Carregando plugin.branding.ABOUT_MENU_ENTRY=&Sobre -plugin.branding.WELCOME_MESSAGE=
    A {1} está actualmente em activo desenvolvimento. A versão que está a usar é apenas experimental e PODE NÃO FUNCIONAR como se espera. Contacte {2} para mais informação.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Todos os direitos reservados. Visite https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi é distribuido sob o termos LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Dicionários -plugin.dictaccregwizz.ANY_DICTIONARY=Qualquer Dicionario -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Qualquer Dicionario de {0} -plugin.dictaccregwizz.FIRST_MATCH=Primeira equivalência -plugin.dictaccregwizz.NO_MATCH=Nenhuma equivalência -plugin.dictaccregwizz.MATCH_RESULT=Nenhumas definições encontradas para "{0}", talvez queira dizer:\n -plugin.dictaccregwizz.INVALID_DATABASE=O dicionario actual "{0}" já não existe no servidor. -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=O protocolo do serviço AIM -plugin.dictaccregwizz.HOST=Servidor -plugin.dictaccregwizz.SERVER_INFO=Informações do servidor -plugin.dictaccregwizz.STRATEGY_SELECTION=Seleccionar estrategia -plugin.dictaccregwizz.STRATEGY_LIST=Lista de estrategias: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Procurar estrategias -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=A estrategia é usada para procurar palavras semelhantes, se a tradução não for encontrada, graças a diferentes abordagens. Por exemplo, as estratégias de prefixo irá procurar palavras que começam como a palavra que se traduziria. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informação da conta Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Este assistente ajuda-o a criar a sua primeira conta Dict em dict.org.\n\nPode adicionar um novo dicionario, indo ao Assistente de Registo de Conta. Preencha o campo de entrada com dicionário que gostaria de adicionar. -plugin.dictaccregwizz.THREAD_CONNECT=A tentar ligar ao servidor -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Tentativa de conexção falhada, não é um servidor dict ou o servidor não está acessivel. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=A obter estrategias -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Não foram encontradas estratégias no servidor -plugin.dictaccregwizz.POPULATE_LIST=Preenchendo a lista -plugin.dictaccregwizz.CLOSING_CONNECTION=Fechando a conexão - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Para poder usar a Conversação por Facebook você precisa de criar um "Utilizador"
    e ativar a Conversação a partir de Definições de Conta na página do Facebook.


    Nota: Quando você cria um utilizador, você tem que fechar a sessão na página web
    e pode demorar algum tempo até que possa entrar com o seu novo utilizador!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=O protocolo de Conversação do Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nome do usuário: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nome do usuário e senha + # generalconfig plugin.generalconfig.AUTO_START=Início automático {0} após o computador reiniciar @@ -960,9 +881,6 @@ plugin.generalconfig.LOG_HISTORY=Gravar histórico das conversas plugin.generalconfig.SHOW_HISTORY=Mostrar plugin.generalconfig.HISTORY_SIZE=mensagens recentes em novas conversas plugin.generalconfig.BRING_WINDOW_TO_FRONT=Trazer a janela de conversação para a frente -plugin.generalconfig.ERROR_PERMISSION=Não tem previlegios suficientes para remover o arranque automatico -plugin.generalconfig.TRANSPARENCY=Transparencia -plugin.generalconfig.ENABLE_TRANSPARENCY=Activar transparencia plugin.generalconfig.DEFAULT_LANGUAGE=Idioma da interface plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=As suas alterações terão efeito no proximo reinicio. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% traduzido @@ -972,6 +890,7 @@ plugin.generalconfig.SIP_SSL_PROTOCOLS=Activar os protocolos SSL/TLS plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Converter letras em números de telefone plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=Exemplo: +1-800-MEUNUMERO -> +1-800-638686376 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP plugin.generalconfig.OPUS_CONFIG=Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Taxa de amostragem: plugin.generalconfig.OPUS_BITRATE=Taxa media da codificação (kbps): @@ -1000,6 +919,7 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Registar uma conta nova plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=Protocolo IRC. plugin.ircaccregwizz.USERNAME_AND_PASSWORD=UIN e palavra-passe +plugin.ircaccregwizz.USERNAME=Alcunha plugin.ircaccregwizz.INFO_PASSWORD=A maioria dos servidores IRC não requerem password. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Alterar automaticamente a alcunha quando já estiver a ser usada plugin.ircaccregwizz.USE_DEFAULT_PORT=Usar a porta predefinida @@ -1007,13 +927,14 @@ plugin.ircaccregwizz.HOST=Nome da máquina: plugin.ircaccregwizz.IRC_SERVER=Servidor plugin.ircaccregwizz.EXAMPLE_SERVER=Exemplo: chat.freenode.net plugin.ircaccregwizz.USE_SECURE_CONNECTION=Usar conexão segura +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autenticação +plugin.ircaccregwizz.SASL_USERNAME=Nome do utilizador # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=O protocolo XMPP plugin.jabberaccregwizz.USERNAME=Nome de Usuário do XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmar senha -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID e Senha plugin.jabberaccregwizz.CSERVER=Servidor plugin.jabberaccregwizz.SERVER=Conectar ao Servidor plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS=Ativar notificações do Gmail para novas mensagens @@ -1042,11 +963,8 @@ plugin.jabberaccregwizz.AUTO_DISCOVER_JN=Auto-descobrir retransmissões de Jingl plugin.jabberaccregwizz.ADD_JINGLE_NODE=Adicionar Jingle Node plugin.jabberaccregwizz.EDIT_JINGLE_NODE=Editar Jingle Node plugin.jabberaccregwizz.JID_ADDRESS=Endereço JID -plugin.jabberaccregwizz.NEW_PASSWORD=Nova senha -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirmar nova senha plugin.jabberaccregwizz.PORT_FIELD_INVALID=Por favor, entre com um número de porta válida para continuar. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=A conta tem que ser registrada antes de mudar a senha. -plugin.jabberaccregwizz.PASSWORD_EMPTY=A senha está vazia. plugin.jabberaccregwizz.TLS_REQUIRED=A conexão não usa TLS, assim não tentará uma mudança de senha. plugin.jabberaccregwizz.PASSWORD_CHANGED=A senha foi alterada com sucesso. plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Seu servidor XMPP não suporte mudanças de senha @@ -1055,21 +973,9 @@ plugin.jabberaccregwizz.VIDEO=Vídeo plugin.jabberaccregwizz.RESET=Repor plugin.jabberaccregwizz.DISABLE_JINGLE=Desativar Jingle (chamadas de áudio e vídeo com XMPP). -# mailbox -plugin.mailbox.CONFIRM=Confirmar -plugin.mailbox.DEFAULTS=Padrões -plugin.mailbox.MAILBOX=Caixa de Correio - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Um protocolo para conectar no serviço MSN. -plugin.msnaccregwizz.USERNAME=E-mail: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID e Senha - # plugin manager plugin.pluginmanager.INSTALL=Instalar plugin.pluginmanager.UNINSTALL=Desinstalar -plugin.pluginmanager.UPDATE=Actualizar plugin.pluginmanager.PLUGINS=Plugins plugin.pluginmanager.URL=URL plugin.pluginmanager.NEW=Novo @@ -1078,6 +984,8 @@ plugin.pluginmanager.NEW=Novo plugin.simpleaccregwizz.LOGIN_USERNAME=Nome do utilizador # sipaccregwizz +plugin.sipaccregwizz.PROTOCOL_NAME=SIP +plugin.sipaccregwizz.PROTOCOL_DESCRIPTION=O protocolo XMPP plugin.sipaccregwizz.USERNAME=ID SIP plugin.sipaccregwizz.USERNAME_AND_PASSWORD=Nome do usuário e senha plugin.sipaccregwizz.CLIENT_CERTIFICATE=Certificado TLS do cliente @@ -1086,7 +994,6 @@ plugin.sipaccregwizz.SERVER_PORT=Porta do Servidor plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Porta do proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Transporte preferido -plugin.sipaccregwizz.ADVANCED_OPTIONS=Opções avançadas plugin.sipaccregwizz.PROXY_OPTIONS=Opções de Proxy plugin.sipaccregwizz.PROXY_AUTO=Configurar proxy automaticamente plugin.sipaccregwizz.ENABLE_PRESENCE=Ativar presença (SIMPLES) @@ -1101,17 +1008,15 @@ plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=Entre 1 e 3600 segundos plugin.sipaccregwizz.DISPLAY_NAME=Mostrar o nome plugin.sipaccregwizz.CREATE_ACCOUNT=Criar nova conta XMPP plugin.sipaccregwizz.XCAP_PASSWORD=Palavra-passe +#used from SecurityPanel # skin manager -# ssh accregwizz -plugin.sshaccregwizz.USERNAME=Informação da Conta ID: -plugin.sshaccregwizz.OPTIONAL=Configurar - # status update # updatechecker plugin.updatechecker.BUTTON_CLOSE=Fechar +plugin.updatechecker.BUTTON_INSTALL=Instalar # usersearch @@ -1121,41 +1026,33 @@ plugin.whiteboard.COLOR=Cor plugin.whiteboard.MODIFICATION=Notificações plugin.whiteboard.DELETE=Apagar -# yahoo accregwizz -plugin.yahooaccregwizz.USERNAME=Nome do usuário: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=UIN e palavra-passe - -# zero accregwizz -plugin.zeroaccregwizz.FIRST_NAME=Nome: -plugin.zeroaccregwizz.LAST_NAME=Apelido: -plugin.zeroaccregwizz.EMAIL=E-mail: -plugin.zeroaccregwizz.USERID_AND_PASSWORD=UIN e palavra-passe - # gtalk accregwizz # iptel accregwizz plugin.iptelaccregwizz.USERNAME=Nome do utilizador -# sip2sip accregwizz -plugin.sip2sipaccregwizz.USERNAME=Nome do utilizador - # ippi accregwizz +plugin.sip2sipaccregwizz.USERNAME=Nome do utilizador plugin.ippiaccregwizz.CREATE_ACCOUNT=Criar nova conta XMPP # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=Copiar plugin.keybindings.CHAT_CUT=C&ortar plugin.keybindings.CHAT_PASTE=Colar plugin.keybindings.MAIN_RENAME=Re&nomear contato plugin.keybindings.globalchooser.SHORTCUT_NAME=Nome plugin.keybindings.PLUGIN_NAME=Teclas de atalho +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Conversar # Notification Configuration Form plugin.notificationconfig.ENABLE_NOTIF=Activo plugin.notificationconfig.DESCRIPTION=Descrição +plugin.notificationconfig.RESTORE=Restaurar padrões plugin.notificationconfig.SOUND_FILE=Ficheiro de som: plugin.notificationconfig.BROWSE_SOUND=Escolha um ficheiro de som +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Chamada recebida plugin.notificationconfig.event.IncomingFile=Chamada recebida plugin.notificationconfig.event.HangUp=Desligar @@ -1173,9 +1070,11 @@ impl.media.security.zrtp.PUB_KEYS=Chaves publicas impl.media.configform.AUDIO_NOTIFY=&Notificações: impl.media.configform.VIDEO_RESOLUTION=Resolução do vídeo +impl.media.configform.VIDEO_RESET=Restaurar padrões impl.neomedia.configform.VIDEO=Vídeo +#in JNIEncoder impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTP # The callrecordingconfig plugin was never really committed into trunk and its @@ -1193,7 +1092,6 @@ plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS_MSG=Alteração da passwo plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS_MSG=Alteração da password com sucesso plugin.securityconfig.masterpassword.COL_NAME=Nome plugin.securityconfig.masterpassword.COL_PASSWORD=Palavra-passe -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Remover plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Remover todas as senhas plugin.securityconfig.masterpassword.SHOW_PASSWORDS_BUTTON=Mostrar Senhas plugin.securityconfig.masterpassword.HIDE_PASSWORDS_BUTTON=Esconder Senhas @@ -1215,6 +1113,7 @@ plugin.otr.authbuddydialog.I_HAVE_NOT=Eu não tenho plugin.otr.configform.MY_PRIVATE_KEYS=Minhas Chaves Privadas plugin.otr.configform.GENERATE=Gerar plugin.otr.configform.REGENERATE=Gerar novamente +plugin.otr.configform.FINGERPRINT=Digitais plugin.otr.configform.COLUMN_NAME_CONTACT=Contatos plugin.otr.configform.COLUMN_NAME_VERIFIED_STATUS=Confirmado plugin.otr.configform.COLUMN_VALUE_VERIFIED_TRUE=Sim @@ -1257,7 +1156,7 @@ net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Ignorar net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=&Recusar #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=Editar +plugin.spellcheck.UNINSTALL_DICTIONARY=Desinstalar #Certificate configuration plugin -- cgit v1.1 From 39d73179b7d220db1f9a135ac0548f3132871be0 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:59:44 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1378 of 1505 strings translated (18 fuzzy). --- resources/languages/resources_sr.properties | 210 ++++------------------------ 1 file changed, 29 insertions(+), 181 deletions(-) diff --git a/resources/languages/resources_sr.properties b/resources/languages/resources_sr.properties index 3c9e19d..24c9b05 100644 --- a/resources/languages/resources_sr.properties +++ b/resources/languages/resources_sr.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Ја service.gui.ACCOUNT_REGISTRATION_WIZARD=Чаробњак за регистрацију налога service.gui.ACCOUNTS=Налози service.gui.ADD=&Додај -service.gui.ADD_ACCOUNT=Додај налог service.gui.ADD_CONTACT=&Додај контакт service.gui.ADD_AUTHORIZED_CONTACT=Додај {0}у листу контаката service.gui.ADD_CONTACT_TO_CONTACTLIST=Додај контакт на листу контаката @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Грешка код додавања кон service.gui.ADD_CONTACT_EXIST_ERROR=Контакт {0} већ постоји у листи контаката. service.gui.ADD_CONTACT_NETWORK_ERROR=Сервер није препознао захтев за додавање контакта са ид: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Неуспело додавење контаката са ид: {0}. Операција није подржана. -service.gui.ADD_CONTACT_IDENTIFIER=У поље испод унесите идентификацију контакта кога желите додати. -service.gui.ADD_CONTACT_WIZARD=Чаробњак за додавање контакта service.gui.ADD_CONTACT_NOT_CONNECTED=Морате бити повезани да би додали контакт. Повежите се на одабраног провајдера и пробајте поново. service.gui.ADD_GROUP_LOCAL_ERROR=Неуспело додавање групе са именом: {0}. Проблем се догодио током локален ИО операције. service.gui.ADD_GROUP_EXIST_ERROR=Група {0} већ постоји у вашој контакт листи. Молим одаберите друго име. service.gui.ADD_GROUP_NET_ERROR=Неуспело додавање групе са именом: {0}. Проблем се догодио због лоше везе. Молим проверите вашу мрежу и пробајте поново. service.gui.ADD_GROUP_ERROR=Неуспело додавање групе са именом: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Група не мора бити празна. -service.gui.ADD_GROUP=Направи групу -service.gui.ADD_SUBCONTACT=&Додај потконтакт service.gui.ADDRESS=Адреса service.gui.ADMINISTRATOR=администратор service.gui.ADVANCED=&Напредно -service.gui.ALL=&Сви service.gui.ALL_CONTACTS=&Сви контакти service.gui.ALTERNATE_ADDRESS=Резервна адреса service.gui.APPLY=&Примени @@ -65,7 +70,6 @@ service.gui.AT=у service.gui.AUTHORIZE=&Овласти service.gui.AUTHORIZATION_ACCEPTED={0} је прихватио захтев за овлашћење. service.gui.AUTHENTICATION_FAILED=Пријава је неуспела за {0}. Унета лозинка није исправна. -service.gui.AUTHENTICATION_REQUESTED=Потребна идентификација service.gui.AUTHENTICATION_REQUESTED_SERVER=Сервер {0} захтева вашу идентификацију. service.gui.AUTHENTICATION_REJECTED={0} је одбацио ваш захтев за идентификацију. service.gui.AUTHENTICATION_WINDOW_TITLE={0} идентификација @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=У поље испод можете унети service.gui.CHANGE_NICKNAME_ERROR=Грешка код промене надимка service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Надимак већ постоји service.gui.CHANGE_VIDEO_QUALITY=Промени квалитет видеа -service.gui.CHAT_CONFERENCE_LABEL=Конференција service.gui.CHAT_CONFERENCE_ITEM_LABEL={0}''име конференције service.gui.CHAT_ROOM_ALREADY_JOINED=Соба {0} за ћаскање је већ приступила. service.gui.CHAT_ROOM_CONFIGURATION=Подешавање {0} собе за ћаскање @@ -121,18 +124,14 @@ service.gui.CHAT_ROOM_USER_LEFT=наустио {0} service.gui.CHAT_ROOM_USER_KICKED=избачен је из {0} service.gui.CHAT_ROOM_USER_QUIT=напустио {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Слање поруке је забрањено -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Чување собе за ћаскање за будуће коришћење -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Уклоните одабрану собу са листе сачуваних соба service.gui.CHAT_ROOM_NAME=Име собе за ћаскање service.gui.CLEAR_CUSTOM_MESSAGES=Избриши произвољне поруке service.gui.ROOM_NAME=Соба за ћаскање -service.gui.AUTOJOIN=Ауто-прикључење service.gui.CHANGE_PASSWORD=Промена лозинке service.gui.CHAT_ROOM_NAME_INFO=У поље испод унесите име собе за ћаскање коју би желели да креирате. service.gui.CHAT_ROOM_NOT_EXIST=Соба није нађена на серверу. Молим проверите да ли сте унели исправно име. service.gui.CHAT_ROOM_NOT_CONNECTED=Потребно је да будете пријављени да би приступили {0} соби за ћаскање service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Морате бити пријављени да би напустили собу за ћаскање. -service.gui.CHAT_ROOM_NOT_JOINED=Морате бити пријављени у собу за ћаскање за даље операције. service.gui.CHAT_ROOM_OPTIONS=Поставке собе за ћаскање service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Соба {0} за ћаскање захтева регистрацију за прикључивање. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Соба {0} за ћаскање захтева лозинку. @@ -150,21 +149,17 @@ service.gui.CLEAR=Очисти service.gui.CLOSE=За&твори service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Не можете примити нову поруку за мање од 2 секунде. Да ли сте сигурни да желите затворити ово ћаскање? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Имате активан пренос фајла. Да ли сте сигурни да желите на прекинете? -service.gui.CONFIRM=Потврди service.gui.CONNECTED_STATUS=Повезан service.gui.CONNECTING=Повезивање... service.gui.CONNECTING_STATUS=Успостављам везу service.gui.CONNECTING_EARLY_MEDIA_STATUS=Успостављам везу* service.gui.CONNECTION=Веза -service.gui.CONNECTION_FAILED_MSG=Повезивање није исправно за налог: Корисничко име: {0}, Име сервера: {1}. Молим проверите вашу мрежу или контактирајте администратора за више информација. service.gui.CONNECTION_EXPIRED_MSG=Веза са сервером је {0} прекинута. service.gui.CONTACT_NAME=ИД или број -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Изабрани {0} контакт не подржава телефонију. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Изабрани {0} контакт не подржава конференције. service.gui.CONTACT_PAUSED_TYPING={0} застој код куцања поруке service.gui.CONTACT_TYPING={0} куца поруку service.gui.CONTACT_INFO=&Контакт подаци -service.gui.CONTACTLIST=Листа контаката service.gui.CONTACTS=Контакти service.gui.COPY=&Умножи service.gui.COPY_LINK=Умножи &везу @@ -174,17 +169,14 @@ service.gui.CREATE_CHAT_ROOM=&Креирај собу за ћаскање... service.gui.CREATE_CHAT_ROOM_ERROR=Неуспело креирање {0} собе за ћаскање. service.gui.CREATE_CHAT_ROOM_WIZARD=Креирај чаробњак собе за ћаскање service.gui.CREATE_CONFERENCE_CALL=&Креирај конференцијски позив... -service.gui.CREATE_CONFERENCE_CHAT=&Креирај конференцијско ћаскање... service.gui.CREATE_GROUP=&Креирај групу... service.gui.CREATE_GROUP_NAME=У поље испод унеси име групе коју желите да креирате. -service.gui.CREATE_FIRST_GROUP_WIZARD=Ваша контакт листа не садржи групе. Моли прво креирајте групу (Фајл/Креирај гурпу). service.gui.CREATE_VIDEO_BRIDGE=Креирај &видео везу... service.gui.CREATE_VIDEO_BRIDGE_MENU=Креирај &видео везу service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Креирај / Приступи видео конференцији service.gui.CREATE_VIDEO_CONFERENCE=Креирај нову видео конференцију за ову собу service.gui.CONTACT_INFO_NOT_SUPPORTED=Овај контакт не подржава веб контакт податке service.gui.CUT=И&сеци -service.gui.DATE=Датум service.gui.DELETE=Обриши service.gui.DENY=&Одбиј service.gui.DESKTOP_SHARING_WARNING=Да ли сте сигурни да желите дељење екрана?
    Кликом на У реду особе на овом позиву ће видети ваш екран. @@ -194,7 +186,6 @@ service.gui.DISCONNECTED_STATUS=Прекинута веза service.gui.DND_STATUS=Не узнемиравај service.gui.DO_NOT_ASK_AGAIN=Не питај поново service.gui.DO_NOT_SHOW_AGAIN=Не показуј ову поруку поново -service.gui.DOWNLOAD_NOW=&Преузми сада service.gui.DRAG_FOR_SHARING=Превуци овде било шта што желиш да делиш... service.gui.DURATION=трајање service.gui.DESTROY_CHATROOM=Уништи собу за ћаскање @@ -215,7 +206,6 @@ service.gui.ERROR_RECEIVED_FROM=Грешка је примљена од {0} service.gui.ESTIMATED_TIME=Процењено преостало време: service.gui.EVENTS=Догађаји service.gui.EXIT=И&злаз -service.gui.EXTENDED_CRITERIA=Проширени критеријуми service.gui.GENERAL=Опште service.gui.GENERAL_ERROR=Опште грешке service.gui.GROUP_NAME=Име групе @@ -257,7 +247,6 @@ service.gui.FONT_ITALIC=Искошено service.gui.FONT_SIZE=Величина service.gui.FONT_STYLE=Изглед service.gui.FONT_UNDERLINE=Подвучено -service.gui.FROM={0} од {1} service.gui.GRANT_OWNERSHIP=Додели власништво... service.gui.GRANT_ADMIN=Додели администратора... service.gui.GRANT_MODERATOR=Додели модератора @@ -283,7 +272,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=Да ли сте сигурни да же service.gui.HISTORY_REMOVE_ERROR=Грешка код уклањања локално сачуваних порука. service.gui.HOME=Лично service.gui.HOME_PAGE=Матична страна -service.gui.HOUR=Сат service.gui.ICE=ICE service.gui.IDENTIFIER=Идентификатор service.gui.IGNORE=&Игнориши @@ -305,13 +293,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Позови контакте за в service.gui.INVITE_REASON=Разлог позивања service.gui.IS_CALLING={0} позива... service.gui.IS_NOW={0} је сад {1} -service.gui.JITSI_WARNING=SIP комуникатор је недавно преименован у Jitsi.
    Ако желите да ваша верзија буде ажурирана, преузмите одмах Jitsi.

    Извињавамо се због непријатности коју смо можда изазвали.

    Jitsi развојни тим -service.gui.JITSI_WARNING_TITLE=SIP комуникатор постаје Jitsi service.gui.JOIN=&Прикључи service.gui.JOIN_AS=П&рикључи ка service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Прикључи се постојећој видео конференцији service.gui.JOIN_VIDEO=Прикључи видео -service.gui.CLOSE_CHAT_ROOM_DIALOG=З&атвори service.gui.JOB_TITLE=Занимање service.gui.JOIN_CHAT_ROOM=&Придружи се ћаскању... service.gui.JOIN_CHAT_ROOM_TITLE=Придружи се ћаскању @@ -324,7 +309,6 @@ service.gui.KICK_FAILED=Неуспело избацивање service.gui.KICK_FAILED_GENERAL_ERROR=Неуспело избацивање {0}. Грешка на серверу. service.gui.KICK_FAILED_NOT_ALLOWED=Неуспело избацивање {0}. Власник и администратор собе не могу бити избачени. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Неуспело избацивање {0}. Немате довољно овлашћења да то учините. -service.gui.LAST=Последњи service.gui.LAST_NAME=Презиме service.gui.LEAVE=&Напусти service.gui.LIMIT_REACHED_FOR_IP=Имате превише регистрација са локалне ИП адресе и {0} сервер не дозвољава отварање нових адреса. @@ -344,7 +328,6 @@ service.gui.MESSAGE=Порука service.gui.MISSED_CALLS_TOOL_TIP=Пропуштени позив од: service.gui.MISSED_CALLS_MORE_TOOL_TIP= и {0} више service.gui.MODERATOR=модератор -service.gui.MORE=Погледај више service.gui.MORE_LABEL=Више service.gui.MOVE=Премести service.gui.MOVE_SUBCONTACT=П&ремести контакт @@ -353,7 +336,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Контакт који сте одабран service.gui.MOVE_SUBCONTACT_QUESTION=Да ли сте сигурни да желите преместити {0} за {1}? service.gui.MOVE_TO_GROUP=&Премести у групу service.gui.MOVE_CONTACT=Премести контакт -service.gui.MOVE_CONTACT_ERROR=&Контакт не може бити премештен service.gui.MSG_DELIVERY_FAILURE=Порука изнад није могла бити испоручена service.gui.MSG_DELIVERY_NOT_SUPPORTED=Протокол који користите не подржава поруке ван мреже. Пробајте преко {0} другог протокола или чекајте док он/она постане доступан. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Догодила се интерна грешка. Ово је највероватније баг. Молим пријавите овде: https://jitsi.org/Development/BugsAndIssues. @@ -367,7 +349,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Потребно је да сте пов service.gui.MULTIPLE_LOGINS=Ви сте пријављени са више од једног налога. Следећи налог: Корисничко име: {0}, Име сервера: {1} је тренутно искључен. service.gui.MY_CHAT_ROOMS=Додај собу за ћаскање service.gui.MY_CHAT_ROOMS_TITLE=Додај собу за ћаскање -service.gui.MUTE=Утишај service.gui.NAME=Име service.gui.NETWORK=Мрежа service.gui.NETWORK_FAILURE=Пад мреже @@ -397,7 +378,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Нијеуконтактлисти service.gui.SD_QUALITY=Стандардан квалитет service.gui.OFFLINE=Ван мреже service.gui.OK=&У реду -service.gui.OLDER_CALLS=Старији позиви service.gui.ONLINE=На мрежи service.gui.OPEN=Отвори service.gui.OPEN_FILE_FROM_IMAGE=Двоклик за отварање фајла. @@ -409,7 +389,6 @@ service.gui.OPEN_ON_ACTIVITY=Отвори на активности service.gui.OPEN_ON_MESSAGE=Отвори само на поруке service.gui.OPEN_ON_IMPORTANT_MESSAGE=Отвори само на важне поруке service.gui.OR=или -service.gui.OR_ENTER_PHONE_NUMBER=Или унеси телефонски број овде... service.gui.ORGANIZATION=Организација service.gui.OTHER=Друго service.gui.OWNER=власник собе @@ -428,7 +407,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS=Притисни "Ентер" за су service.gui.PRESS_FOR_CALL_INFO=Притисни за податке позива service.gui.PRESS_TO_OPEN_CRM=Притисни за отварање ЦРМ апликације service.gui.PREVIOUS=Претходно -service.gui.PREVIOUS_TOOLTIP=Претражи старије конверзације service.gui.PRINT=&Штампај service.gui.PROACTIVE_NOTIFICATION=је писање поруке service.gui.PROBLEMS_ENCOUNTERED=Суочавајући проблеми @@ -444,7 +422,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Одјављивали и пријављ service.gui.RE_REQUEST_AUTHORIZATION=Поново захтевај ауторизацију service.gui.REFERRED_STATUS=Препоручено service.gui.REJECT=&Одбаци -service.gui.REMIND_ME_LATER=Подсети ме касније service.gui.REMEMBER_PASSWORD=Запамти лозинку service.gui.REMOVE=&Уклони service.gui.REMOVE_ACCOUNT=&Уклони налог @@ -470,29 +447,20 @@ service.gui.REVOKE_ADMIN=Опозови администратора service.gui.REVOKE_MODERATOR=Опозови модератора service.gui.REVOKE_MEMBERSHIP=Опозови чланство service.gui.REVOKE_VOICE=Укини глас -service.gui.ROOT_GROUP=Админ група service.gui.SAVE=&Сачувај -service.gui.SAVE_AS_DEFAULT=Сачувај као подразумевано service.gui.SEARCH=&Претражи service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Кликни на дугме испод за приказ свих соба за ћаскање на одабраном серверу. Онда одабери један коме желиш да приступиш и кликни на приступно дугме. service.gui.SEARCH_STRING_CONTACT_SOURCE=Тражени контакт service.gui.SECURITY=Безбедност -service.gui.SELECT_ACCOUNT=Одабери налог service.gui.SELECT_COLOR=Одабери боју service.gui.SELECT_GROUP=Одабери групу -service.gui.SELECT_GROUP_WIZARD_MSG=Листа испод садржи све групе у вашој контакт листи. Одабери једну где желиш да додаш нови контакт. service.gui.SELECT_NO_GROUP=Без групе -service.gui.SELECT_GROUP_WIZARD=Одреди групу service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Листа испод садржи све налоге које подржавају функцију вишеструког ћаскања. Одабери један који желиш за креирање своје собе за ћаскање. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Листа испод садржи све регистроване налоге. Одабери један који желиш за комуникацију са новим контактом. -service.gui.SELECT_PROVIDERS_WIZARD=Одабери налог service.gui.SELECT_VIDEO_CONFERENCE=Одавери видео конференцију service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Одабери собу за ћаскање са листе и притисни У реду за додавање. service.gui.SEND=&Пошаљи service.gui.SEND_FILE=Пошаљи &фајл -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Не постоје подаци за овај контакт. service.gui.SEND_MESSAGE=&Пошаљи поруку -service.gui.SEND_AS_SMS=Пошаљи као СМС service.gui.SEND_PRIVATE_MESSAGE=Пошаљи приватну поруку service.gui.SEND_SMS=П&ошаљи СМС service.gui.SEND_SMS_DETAILS=Запамти да је потребно унети број у интернационалном формату, нпр. почети са +44 за UK као пример, +447777000000 @@ -531,7 +499,6 @@ service.gui.STREET=Улица service.gui.SUBJECT=Субјект service.gui.SUMMARY=Сажетак service.gui.TELEPHONY=Телефонија -service.gui.TODAY=Данас service.gui.TOOLS=&Алати service.gui.TRANSFER=Прен&ос service.gui.TO=&За: @@ -541,7 +508,6 @@ service.gui.TRANSFER_CALL_TO=Пренос за: service.gui.TRANSPARENCY_NOT_ENABLED=Провидност није подржана за ваше тренутне поставке. service.gui.TYPE_YOUR_REQUEST=Укуцајте захтев овде service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Није могуће променити квалитет видеа за овај позив. -service.gui.UNMUTE=Укључи звук service.gui.USER_IDENTIFIER=Идентификатор корисника: service.gui.USER_EXISTS_ERROR=Корисник већ постоји на одабраној мрежи. Молим одаберите другог корисника или мрежу service.gui.USERNAME_NULL=Молим попуните ваше корисничко име и лозинку. @@ -554,7 +520,6 @@ service.gui.USE_PROVISIONING=Користи провизију преко мре service.gui.VALUE=Вредност service.gui.VIDEO_CALL=&Видео позив service.gui.VIA=преко -service.gui.VIA_SMS=преко СМС service.gui.VIEW=&Приказ service.gui.VIEW_HISTORY=Приказ &историје service.gui.VIEW_SMILEYS=Приказ &емотикона @@ -574,9 +539,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Подеси јачину звука service.gui.WAITING_AUTHORIZATION=Чекам за ауторизацију service.gui.WARNING=Упозорење service.gui.YES=Да -service.gui.YESTERDAY=Јуче -service.gui.EXISTING_ACCOUNT_ERROR=Налог који сте унели је већ инсталиран. -service.gui.NEW_MAIL=Имате нову е-пошту!
    Од: {0} {1}
    Субјект: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Примили сте нову поруку е-поште у сату {0} примљено:
    service.gui.NEW_GMAIL_MANY_HEADER=Примили сте {2} нову поруку е-поште у сату {0} примљено:
    service.gui.NEW_GMAIL_FOOTER=једна непрочитана порука у твом примљеном.
    @@ -600,7 +562,6 @@ service.gui.SECURITY_ERROR=Безбедоносна грешка service.gui.SPEED=Брзина: service.gui.SILENT_MEMBER=тихи члан service.gui.NON_SECURE_CONNECTION=Небезбедне конекције могу бити направљене за овај налог {0}. Ако желите повезивање са небезбедним сервером, молим проверите "Омогући небезбедне конекције" у вашим поставкама налога. -service.gui.UPDATE=Ажурирај service.gui.MOBILE_PHONE=Мобилни service.gui.VIDEO_PHONE=Видео service.gui.WORK_PHONE=Посао @@ -635,7 +596,6 @@ service.gui.callinfo.CALL_INFORMATION=Подаци позива service.gui.callinfo.CALL_IDENTITY=Идентитет service.gui.callinfo.PEER_COUNT=Број учесника service.gui.callinfo.IS_CONFERENCE_FOCUS=Фокус конференције -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Омогућено шифрофање service.gui.callinfo.CALL_TRANSPORT=Сигнализација у току позива service.gui.callinfo.CALL_DURATION=Трајање позива service.gui.callinfo.TLS_PROTOCOL=ТЛС протокол @@ -649,7 +609,6 @@ service.gui.callinfo.AUDIO_INFO=Звучни подаци service.gui.callinfo.VIDEO_INFO=Видео подаци service.gui.callinfo.LOCAL_IP=Локална ИП / Порт service.gui.callinfo.REMOTE_IP=Удаљена ИП / Порт -service.gui.callinfo.BANDWITH=Проток service.gui.callinfo.LOSS_RATE=Ниска стопа service.gui.callinfo.RTT=РТТ service.gui.callinfo.JITTER=Померање @@ -659,9 +618,12 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=СРТП service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Кључ размене протокола service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=ICE кандидат проширеног типа service.gui.callinfo.ICE_STATE=ICE обрада + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.RUNNING=Провера повезивања service.gui.callinfo.ICE_STATE.COMPLETED=Завршено service.gui.callinfo.ICE_STATE.FAILED=Неуспело + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Локални рачунар ИП / Порт service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Даљински пренета ИП / Порт service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=Локални ИП / Порт @@ -683,6 +645,8 @@ service.gui.CERT_DIALOG_TITLE=Преглед сертификата service.gui.CONTINUE_ANYWAY=Ипак настави service.gui.CERT_INFO_CHAIN=Ланац сертификата: service.gui.CERT_INFO_ISSUED_TO=Издато за + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Средње име: service.gui.CERT_INFO_O=Организација: service.gui.CERT_INFO_C=Назив државе: @@ -701,12 +665,10 @@ service.gui.CERT_INFO_SIGN_ALG=Алгоритам потписа: service.gui.CERT_INFO_PUB_KEY_INFO=Подаци о јавном кључу service.gui.CERT_INFO_ALG=Алгоритам: service.gui.CERT_INFO_PUB_KEY=Јавни кључ: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} бајтова: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} битова service.gui.CERT_INFO_EXP=Изложилац: service.gui.CERT_INFO_KEY_SIZE=Величина кључа: service.gui.CERT_INFO_SIGN=Потпис: -service.gui.CONTINUE=Настави service.gui.SHOW_CERT=Прикажи сертификат service.gui.HIDE_CERT=Сакриј сертификат @@ -728,12 +690,9 @@ service.gui.security.SECURE_AUDIO=Бесбедан звук service.gui.security.AUDIO_NOT_SECURED=Звук није безбедан service.gui.security.SECURE_VIDEO=Безбедан видео service.gui.security.VIDEO_NOT_SECURED=Видео није безбедан -service.gui.security.NO_VIDEO=Без видеа -service.gui.security.CIPHER=Шифра: {0} service.gui.security.CALL_SECURED_TOOLTIP=Позив је безбедан. За више података притисни овде. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Позив није безбедан. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Притисни овде да упоредити безбедоносну тајну са партнером. -service.gui.security.COMPARE_WITH_PARTNER=Упореди са партнером и кликни катанац за потврду. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Упореди са партнером: service.gui.security.SECURITY_ALERT=Покушавам да обезбедим позив. Искључење у @@ -749,19 +708,13 @@ service.gui.avatar.imagepicker.CLICK=Клик и емотикон service.gui.avatar.imagepicker.IMAGE_FILES=Фајлови слика service.gui.avatar.imagepicker.IMAGE_PICKER=Слика service.gui.avatar.imagepicker.IMAGE_SIZE=Величина слике -service.gui.avatar.imagepicker.INITIALIZING=Покрећем service.gui.avatar.imagepicker.RESET=Поврати service.gui.avatar.imagepicker.SET=Подеси service.gui.avatar.imagepicker.TAKE_PHOTO=Сними фотографију -service.gui.avatar.imagepicker.WEBCAM_ERROR=Грешка веб камере service.gui.security.encryption.required=Захтева се шифровање! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Грешка у СИП складишту контакт листи impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Ресурс се не чита {0}. За {1} @@ -791,9 +744,7 @@ impl.ldap.QUERY_CUSTOM=Прилагођени упит impl.ldap.QUERY_CUSTOM_HINT=Користи {0} као чиновника за термин претраге. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Аутоматски додај џокере за термин упита impl.ldap.QUERY_PHOTO_INLINE=Донеси слику са другим атрибутима -impl.ldap.NEW=Нова impl.ldap.EDIT=уреди -impl.ldap.REMOVE=Уклони impl.ldap.ENABLED=Омогућен impl.ldap.SERVER_NAME=Име сервера impl.ldap.SERVER_NAME_EXAMPLE=Мој ЛДАП сервер @@ -826,6 +777,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=кућнителефон impl.ldap.PHONE_PREFIX=Префикс телефона impl.ldap.PHONE_PREFIX_EXAMPLE=Ex.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Адресар plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Омогући претрагу за MacOSX адресар @@ -839,9 +794,7 @@ plugin.addrbook.MAKE_OUTLOOK_DEFAULT_MAIL_CLIENT=Направи Outlook подр # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Google контакти -impl.googlecontacts.NEW=Ново impl.googlecontacts.EDIT=уреди -impl.googlecontacts.REMOVE=Уклони impl.googlecontacts.ENABLED=Омогућен impl.googlecontacts.ACCOUNT_NAME=Име налога impl.googlecontacts.SAVE=Сачувај @@ -879,11 +832,8 @@ plugin.accountinfo.ORGANIZATION=Назив организације: plugin.accountinfo.JOB_TITLE=Назив посла: plugin.accountinfo.ABOUT_ME=О мени: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Корисничке слике plugin.accountinfo.GLOBAL_ICON=Користи општу икону plugin.accountinfo.LOCAL_ICON=Користи ову икону: -plugin.accountinfo.CHANGE=Промени -plugin.accountinfo.ONLY_MESSAGE=Само поруке # connection info plugin.connectioninfo.TITLE=Инфо повезивања @@ -903,49 +853,12 @@ plugin.aimaccregwizz.USERNAME=AIM надимак: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Надимак и лозинка plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Региструј нови налог plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=У случају да немате AIM налог, кликните на дугме за креирање новог. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Препиши подразумеване поставке сервера # branding plugin.branding.ABOUT_WINDOW_TITLE=О {0} plugin.branding.LOGO_MESSAGE=VoIP && инстант поруке отвореног кода -plugin.branding.LOADING=Учитавам plugin.branding.ABOUT_MENU_ENTRY=&О -plugin.branding.WELCOME_MESSAGE=
    Тренутно {1} је под активним развојем. Верзија коју сте поктенули је експериментална и МОЖДА НЕЋЕ радити као што очекујете. Молим погледајте {2} за више информација.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Copyright jitsi.org. Сва права задржана. Посетите https://jitsi.org.
    -plugin.branding.LICENSE=
    Jitsi је дистрибуиран под условима LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Речници -plugin.dictaccregwizz.ANY_DICTIONARY=Било који речник -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Било који речник од {0} -plugin.dictaccregwizz.FIRST_MATCH=Први погодак -plugin.dictaccregwizz.NO_MATCH=Без подударања -plugin.dictaccregwizz.MATCH_RESULT=Без дефиниције нађене за "{0}", можда сте мислили:\n -plugin.dictaccregwizz.INVALID_DATABASE=Тренутни речник "{0}" не постоји било где на серверу. -plugin.dictaccregwizz.INVALID_STRATEGY=Тренутна стратегија није доступна на серверу. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Протокол Dict сервиса -plugin.dictaccregwizz.HOST=Рачунар -plugin.dictaccregwizz.SERVER_INFO=Подаци сервера -plugin.dictaccregwizz.STRATEGY_SELECTION=Strategy селекција -plugin.dictaccregwizz.STRATEGY_LIST=Листа стратегија: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Претрага стратегија -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Стратегија се користи за тражење сличних речи, ако превод није пронађен, захваљујући различитим приступима. На пример, префикс стратегије ће потражити речи које почињу као реч коју би превели. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Dict подаци о налогу -plugin.dictaccregwizz.FIRST_ACCOUNT=Чаробњак ће креирати ваш први Dict налог за dict.org.\n\nМожете додати нови речник преко чаробњака за регистрацију. Попуните поље са речником који желите да додате. -plugin.dictaccregwizz.THREAD_CONNECT=Повезивање са сервером -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Неуспео покушај повезивања, то није dict сервер или је сервер ван мреже. -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Довлачим стратегије -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Стратегија није нађена на серверу -plugin.dictaccregwizz.POPULATE_LIST=Листа насељавања -plugin.dictaccregwizz.CLOSING_CONNECTION=Затварање повезивања - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Да би користили Facebook ћаскање потребно је креирати "Корисничко име"
    на вашем "Подешавању налога" на Facebook.


    Напомена: Кад креирате корисничко име морате се одјавити са веб стране
    и то може потрајати пре него што се пријавите са својим новим корисничким именом!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Протокол Facebook ћаскања -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Корисничко име: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Корисничко име и лозинка + # generalconfig plugin.generalconfig.AUTO_START=Аутоматски покрени {0} када се рачунар поново покреће @@ -956,9 +869,6 @@ plugin.generalconfig.SHOW_HISTORY=Прикажи plugin.generalconfig.HISTORY_SIZE=недавне поруке у новим ћаскањима plugin.generalconfig.SEND_MESSAGES_WITH=Пошаљи поруке са: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Постави напред прозор за ћаскање -plugin.generalconfig.ERROR_PERMISSION=Немате довољно овлашћења у уклоните аутостарт -plugin.generalconfig.TRANSPARENCY=Провидност -plugin.generalconfig.ENABLE_TRANSPARENCY=Омогући провидност plugin.generalconfig.DEFAULT_LANGUAGE=Језик сучеља plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Ваше промене ће бити примењене при следећем покретању. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% преведено @@ -1006,11 +916,9 @@ plugin.ircaccregwizz.IRC_SERVER=Сервер plugin.ircaccregwizz.USE_SECURE_CONNECTION=Користи безбедну везу # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=XMPP протокол plugin.jabberaccregwizz.USERNAME=XMPP надимак plugin.jabberaccregwizz.PASSWORD_CONFIRM=Потврди лозинку -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ИД или лозинка plugin.jabberaccregwizz.CSERVER=Сервер plugin.jabberaccregwizz.SERVER=Повезивање са сервером plugin.jabberaccregwizz.ENABLE_GMAIL_NOTIFICATIONS=Омогући Gmail обавештења за нове поруке @@ -1025,13 +933,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Напомена plugin.jabberaccregwizz.RESOURCE=Ресурс plugin.jabberaccregwizz.AUTORESOURCE=Аутоматски генериши ресурсе plugin.jabberaccregwizz.PRIORITY=Приоритет -plugin.jabberaccregwizz.XMPP_ERROR=XMPP грешка plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Непозната XMPP грешка ({0}). Провери да ли је име сервера исправно. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Ваше лозинке се не подударају. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Препиши подразумеване поставке сервера -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Напредне поставке plugin.jabberaccregwizz.USE_ICE=Користи ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Користи Google's Jingle/ICE (експериментално) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Аутоматска претрага STUN/TURN сервера plugin.jabberaccregwizz.SUPPORT_TURN=TURN подршка plugin.jabberaccregwizz.TURN_USERNAME=TURN корисничко име @@ -1055,11 +959,8 @@ plugin.jabberaccregwizz.ALLOW_NON_SECURE=Омогући небезбедна п plugin.jabberaccregwizz.DTMF_AUTO=Ауто: одаберите аутоматски између RTP и Inband plugin.jabberaccregwizz.SERVER_OPTIONS=Опције сервера plugin.jabberaccregwizz.CHANGE_PASSWORD=Промени лозинку налога -plugin.jabberaccregwizz.NEW_PASSWORD=Нова лозинка -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Потврди нову лозинку plugin.jabberaccregwizz.PORT_FIELD_INVALID=Молим попуните исправан број порта како би наставили. plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Ваш налог мога бити пријављен пре промене лозинке. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Лозинка је празна. plugin.jabberaccregwizz.TLS_REQUIRED=Веза не користи TLS, неће покушати промену лозинке. plugin.jabberaccregwizz.PASSWORD_CHANGED=Лозинка је успешно промењена plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Ваш XMPP сервер не подржава промену лозинке. @@ -1073,24 +974,9 @@ plugin.jabberaccregwizz.RESET=Поврати plugin.jabberaccregwizz.RESET_DESCRIPTION=Ресетуј општа подешавања plugin.jabberaccregwizz.DISABLE_JINGLE=Онемогући Jingle (звучни и видо позиви са XMPP). -# mailbox -plugin.mailbox.OUTGOING=Одлазна порука: -plugin.mailbox.INCOMING=Долазна порука: -plugin.mailbox.MAX_MESSAGE_TIME=Максимално трајање долазних порука -plugin.mailbox.CONFIRM=Потврди -plugin.mailbox.DEFAULTS=Подразумевано -plugin.mailbox.MAILBOX=Сандуче - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=МСН -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Протокол за повезивање и ћаскање на МСН сервису. -plugin.msnaccregwizz.USERNAME=Е-пошта: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ИД и лозинка - # plugin manager plugin.pluginmanager.INSTALL=Инсталирај plugin.pluginmanager.UNINSTALL=Деинсталирај -plugin.pluginmanager.UPDATE=Ажурирај plugin.pluginmanager.PLUGINS=Прикључци plugin.pluginmanager.URL=Адреса plugin.pluginmanager.CHOOSE_FILE=Одабери фајл @@ -1115,7 +1001,6 @@ plugin.sipaccregwizz.SERVER_PORT=Порт сервера plugin.sipaccregwizz.PROXY=Прокси plugin.sipaccregwizz.PROXY_PORT=Прокси порт plugin.sipaccregwizz.PREFERRED_TRANSPORT=Жељени превоз -plugin.sipaccregwizz.ADVANCED_OPTIONS=Напредне опције plugin.sipaccregwizz.PROXY_OPTIONS=Опције проксија plugin.sipaccregwizz.PROXY_AUTO=Подеси прокси аутоматски plugin.sipaccregwizz.ENABLE_PRESENCE=Омогући присуство (ЈЕДНОСТАВНО) @@ -1133,8 +1018,6 @@ plugin.sipaccregwizz.DTMF_METHOD=ДТМФ метод plugin.sipaccregwizz.DTMF_AUTO=Ауто: Одаберите аутоматски између RTP и Inband (без SIP инфа) plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP подаци -plugin.sipaccregwizz.REGISTER=РЕГИСТАР -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Препиши подразумеване опције сервера plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Омогући подршку за заштићене позиве plugin.sipaccregwizz.AUTH_NAME=Име за пријаву plugin.sipaccregwizz.DISPLAY_NAME=Приказно име @@ -1154,6 +1037,7 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=Повера URI говорном по plugin.sipaccregwizz.NOT_SAME_PASSWORD=Ваша лозинка се не подудара. plugin.sipaccregwizz.NO_CERTIFICATE=<ништа> (користи званичну идентификацију) plugin.sipaccregwizz.SAVP_OPTION=RTP/SAVP индикација +#used from SecurityPanel plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Изаберите омогућене протоколе шифровања и њихов приоритет (прво горњи протокол): plugin.sipaccregwizz.CIPHER_SUITES=Омогућено шифровање: plugin.sipaccregwizz.SHOW_ADVANCED=Напредна подешавања енкрипције @@ -1166,15 +1050,6 @@ plugin.skinmanager.DEFAULT_SKIN=Подразумевани мотив plugin.skinmanager.ADD_NEW_SKIN=Додај нови мотив... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Подразумевани мотив апликације. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=ССХ -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Протокол за повезивање удаљеног рачунара преко ССХ. -plugin.sshaccregwizz.USERNAME=ИД налога: -plugin.sshaccregwizz.IDENTITY_FILE=Идентификациони фајл: -plugin.sshaccregwizz.KNOWN_HOSTS=Позната имена рачунара: -plugin.sshaccregwizz.OPTIONAL=Опционо -plugin.sshaccregwizz.ACCOUNT_DETAILS=Детаљи налога - # status update plugin.autoaway.AUTO_STATUS=Аутоматска одсутност plugin.autoaway.ENABLE_CHANGE_STATUS=Промени статус у одсутности @@ -1220,22 +1095,6 @@ plugin.whiteboard.DESELECT=Поништи избор plugin.whiteboard.DELETE=Обриши plugin.whiteboard.PROPERTIES=Својства -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Протоко за повезивање и ћаскање на Yahoo! сервису. -plugin.yahooaccregwizz.USERNAME=Корисничко име: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ИД и лозинка - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Zeroconf (Bonjour) протокол сервиса. -plugin.zeroaccregwizz.FIRST_NAME=Име: -plugin.zeroaccregwizz.LAST_NAME=Презиме: -plugin.zeroaccregwizz.EMAIL=Е-пошта: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Запамти Bonjour контакти? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ИД и Лозинка -plugin.zeroaccregwizz.USERID=Корисников ИД - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Google Talk протокол @@ -1249,19 +1108,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, ИП телекомуни plugin.iptelaccregwizz.USERNAME=Корисничко име plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Претплата на iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.подаци -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP и ћаскање +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Корисничко име plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Потврда лозинке plugin.sip2sipaccregwizz.EMAIL=Адреса е-поште -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=За помоћ за овај сервис посетите
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Адреса е-поште се користи за слање гласовних порука,
    пропуштених позива и опоравак изгубљених лозинки -plugin.sip2sipaccregwizz.INFO_NOTE=За помоћ у вези овог сервиса посетите http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Постојећи sip2sip.info налог -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Креирај бесплатан sip2sip.info налог - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP && инстант поруке plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=За помоћ око овог сервиса посетите
    http://ippi.fr @@ -1270,6 +1121,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Постојећи ippi налог plugin.ippiaccregwizz.CREATE_ACCOUNT=Креирај бесплатан ippi налог # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Затвори прозор за ћаскање plugin.keybindings.CHAT_COPY=Умножи plugin.keybindings.CHAT_CUT=Исеци @@ -1292,10 +1144,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Име plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Примарна пречица plugin.keybindings.globalchooser.SHORTCUT_SECOND=Секундарна пречица plugin.keybindings.globalchooser.PRESS_BTN=Притисни за подешавање пречице -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=Чекање plugin.keybindings.globalchooser.PUSH_TO_TALK=Гурни за разговор plugin.keybindings.globalchooser.ENABLE_SPECIAL=Омогући детекцију специјалног кључа plugin.keybindings.PLUGIN_NAME=Пречице +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Ћаскање plugin.keybindings.MAIN=Главно plugin.keybindings.GLOBAL=Опште пречице @@ -1323,6 +1175,7 @@ plugin.notificationconfig.tableheader.SOUND=Пусти звук преко ур plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Пусти звук преко уређаја за емитовање plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Пусти збук преко ПЦ звучника plugin.notificationconfig.tableheader.DESCRIPTION=Опис догађаја +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Долазни позив plugin.notificationconfig.event.SecurityMessage=Безбедна порука plugin.notificationconfig.event.IncomingFile=Долазни фајл @@ -1419,6 +1272,7 @@ impl.neomedia.configform.VIDEO=Видео impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Периодично освежавање impl.neomedia.configform.H264.defaultProfile=Подразумевани профил за декодирање у: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Подножје impl.neomedia.configform.H264.defaultProfile.high=Високо impl.neomedia.configform.H264.defaultProfile.main=Главно @@ -1448,7 +1302,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Тренутна лози plugin.securityconfig.masterpassword.ENTER_PASSWORD=Унеси нову лозинку: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Поново унеси лозинку: plugin.securityconfig.masterpassword.MP_TITLE=Главна лозинка -plugin.securityconfig.masterpassword.MP_NOT_SET=(није подешено) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Нисте унели исправну главну лозинку. Молим пробајте поново. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Главна лозинка није исправна! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Неуспела промена лозинке @@ -1464,7 +1317,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Лозинка plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(непознато) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(не може да дешифрује) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Сачуване лозинке -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Уклони plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Уклони све plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Да ли сте сигурни да желите да уклоните све лозинке? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Уклони све лозинке @@ -1549,7 +1401,6 @@ plugin.globalproxy.PROXY_ADDRESS=Прокси сервер plugin.globalproxy.PROXY_PORT=Прокси порт plugin.globalproxy.PROXY_USERNAME=Прокси корисничко име plugin.globalproxy.PROXY_PASSWORD=Прокси лозинка -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Прокси ДНС plugin.globalproxy.FWD_DNS_ADDR=ДНС прокси адреса @@ -1585,7 +1436,6 @@ plugin.provisioning.RESTART_WARNING=Напомена да ће промене б plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Умноћи UUID у клипборд plugin.provisioning.CLIPBOARD_FAILED=Неуспело умножавање UUID у клипборд -plugin.provisioning.EXIT_ON_FAIL=Затвори апликацију ако не успе резервисање plugin.provisioning.CREDENTIALS=Последњи сачувани резервни акредитиви plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=Да ли сте сигурни да желите да уклоните резервну лозинку? plugin.provisioning.PROV_FAILED=Резервисање није успело @@ -1644,8 +1494,6 @@ net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult #plugin spellcheck plugin.spellcheck.TITLE=Провера писања и правописа plugin.spellcheck.MENU=Прикажи проверу писања и правописа -plugin.spellcheck.LANG=Језик -plugin.spellcheck.EDIT_PERSONAL_DICT=Уреди plugin.spellcheck.ENABLE_SPELL_CHECK=Омогући проверу правописа plugin.spellcheck.dialog.FIND=Пронађи следеће plugin.spellcheck.dialog.REPLACE=Замени -- cgit v1.1 From e05ea63ed6035166163e9f166241a5fc9011b205 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:59:51 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 711 of 1505 strings translated (130 fuzzy). --- resources/languages/resources_id.properties | 183 +++++++--------------------- 1 file changed, 41 insertions(+), 142 deletions(-) diff --git a/resources/languages/resources_id.properties b/resources/languages/resources_id.properties index e142468..9ad1416 100644 --- a/resources/languages/resources_id.properties +++ b/resources/languages/resources_id.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Saya service.gui.ACCOUNT_REGISTRATION_WIZARD=Pemandu Pendaftaran Akun service.gui.ACCOUNTS=Akun-akun service.gui.ADD=&Tambah -service.gui.ADD_ACCOUNT=Tambah akun service.gui.ADD_CONTACT=&Tambah kontak service.gui.ADD_AUTHORIZED_CONTACT=Tambah {0} ke daftar kontak anda service.gui.ADD_CONTACT_TO_CONTACTLIST=Tambahkan {0} ke daftar kontak anda @@ -42,20 +52,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Kegagalan menambah kontak service.gui.ADD_CONTACT_EXIST_ERROR=Kontak {0} sudah ada di daftar kontak anda. service.gui.ADD_CONTACT_NETWORK_ERROR=Server tidak merespon permintaan menambahkan kontak dengan id: {0} service.gui.ADD_CONTACT_NOT_SUPPORTED=Gagal menambahkan kontak dengan id: {0}. Operasi tidak didukung. -service.gui.ADD_CONTACT_IDENTIFIER=Pada isian dibawah masukan pengenal dari kontak yang ingin anda tambahkan. -service.gui.ADD_CONTACT_WIZARD=Pemandu penambahan kontak service.gui.ADD_CONTACT_NOT_CONNECTED=Anda harus terhubung agar dapat menambahkan kontak. Silahkan terhubung ke provider terpilih dan coba lagi. service.gui.ADD_GROUP_LOCAL_ERROR=Gagal menambah grup dengan nama: {0}. Permasalahan terjadi pada saat operasi Input/Output lokal service.gui.ADD_GROUP_EXIST_ERROR=Grup {0} sudah ada di daftar kontak anda. Silahkan gunakan nama yang lain. service.gui.ADD_GROUP_NET_ERROR=Gagal menambah grup dengan nama: {0}. Permasalah terjadi karena kesalahan jaringan. Silahkan periksa koneksi jaringan dan coba lagi. service.gui.ADD_GROUP_ERROR=Gagal menambah grup dengan nama: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Nama grup tidak boleh kosong. -service.gui.ADD_GROUP=Buat grup -service.gui.ADD_SUBCONTACT=&Tambah sub-kontak service.gui.ADDRESS=Alamat service.gui.ADMINISTRATOR=administratur service.gui.ADVANCED=&Mahir -service.gui.ALL=&Semua service.gui.ALL_CONTACTS=&Semua kontak service.gui.ALTERNATE_ADDRESS=Alamat alternatif service.gui.APPLY=&Terapkan @@ -65,7 +70,6 @@ service.gui.AT=di service.gui.AUTHORIZE=Otorisasikan service.gui.AUTHORIZATION_ACCEPTED={0} kontak telah menerima permintaan otorisasi anda. service.gui.AUTHENTICATION_FAILED=Autentikasi gagal untuk {0}. Kata sandi yang anda masukkan tidak benar. -service.gui.AUTHENTICATION_REQUESTED=Autentikasi diminta service.gui.AUTHENTICATION_REQUESTED_SERVER=Server {0} telah meminta autentikasi anda. service.gui.AUTHENTICATION_REJECTED={0} telah menolak permintaan autorisasi anda. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autentikasi @@ -107,7 +111,6 @@ service.gui.CHANGE_NICKNAME_LABEL=Pada isian dibawah, anda dapat menuliskan pang service.gui.CHANGE_NICKNAME_ERROR=Gagal merubah nama panggilan service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nama panggilan sudah ada service.gui.CHANGE_VIDEO_QUALITY=Ubah kualitas remote video -service.gui.CHAT_CONFERENCE_LABEL=Konferensi service.gui.CHAT_CONFERENCE_ITEM_LABEL=konferensi milik {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Sudah tergabung dengan ruang bincang {0}. service.gui.CHAT_ROOM_CONFIGURATION=konfigurasi ruang bincang {0} @@ -119,13 +122,11 @@ service.gui.CHAT_ROOM_USER_KICKED=telah diusir dari {0} service.gui.CHAT_ROOM_USER_QUIT=telah menghentikan {0} service.gui.CHAT_ROOM_NAME=Nama ruang bincang service.gui.ROOM_NAME=Ruang Bincang -service.gui.AUTOJOIN=Gabung Otomatis service.gui.CHANGE_PASSWORD=Ubah Kata Sandi service.gui.CHAT_ROOM_NAME_INFO=Pada isian dibawah tuliskan nama ruang bincang yaang ingin anda buat. service.gui.CHAT_ROOM_NOT_EXIST=Ruang {0} tidak ditemukan pada server {1}. Silahkan periksa apakah nama yang anda ketikkan sudah benar. service.gui.CHAT_ROOM_NOT_CONNECTED=Anda perlu login untuk ikut dalam ruang bincang {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Anda perlu login untuk meninggalkan sebuah ruang bincang. -service.gui.CHAT_ROOM_NOT_JOINED=Anda harus tergabung dalam ruang bincang untuk melakukan hal lebih lanjut. service.gui.CHAT_ROOM_OPTIONS=Pilihan ruang bincang service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Ruang bincang {0} membutuhkan pendaftaran untuk dapat bergabung. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Ruang bincang {0} meminta kata sandi. @@ -139,16 +140,13 @@ service.gui.CONNECTING=Menyambung... service.gui.CONNECTING_STATUS=Sambungan service.gui.CONNECTING_EARLY_MEDIA_STATUS=Menyambung... service.gui.CONNECTION=Sambungan -service.gui.CONNECTION_FAILED_MSG=Koneksi gagal untuk akun berikut: Nama Pengguna: {0}, Nama Server: {1}. Silaahkan periksa koneksi jaringan atau hubungi administratur jaringan anda untuk informasi lebih lanjut. service.gui.CONNECTION_EXPIRED_MSG=Anda saat ini terputus dari server {0}. service.gui.CONTACT_NAME=ID atau Nomer -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Kontak terpilih {0} tidak mendukung telephony. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Kontak terpilih {0} tidak mendukung konferensi perbincangan. service.gui.CONTACT_PAUSED_TYPING={0} berhenti mengetikkan pesan service.gui.CONTACT_TYPING={0} sedang mengetik pesan service.gui.CONTACT_TYPING_SEND_FAILED=wakwawww.. kami tidak dapat memberitahu {0} anda sedang menulis service.gui.CONTACT_INFO=&Informasi kontak -service.gui.CONTACTLIST=Daftar Kontak service.gui.CONTACTS=Kontak service.gui.COPY=Salin service.gui.COPY_LINK=Salin tautan @@ -158,15 +156,12 @@ service.gui.CREATE_CHAT_ROOM=&Buat ruang bincang.. service.gui.CREATE_CHAT_ROOM_ERROR=Gagal membuat ruang bincang {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Pemandu pembuatan ruang bincang service.gui.CREATE_CONFERENCE_CALL=&Buat sebuah panggilan konferensi... -service.gui.CREATE_CONFERENCE_CHAT=&Buat sebuah perbincangan konferensi... service.gui.CREATE_GROUP=&Buat grup service.gui.CREATE_GROUP_NAME=Pada isian dibawah ketikkan nama grup yang ingin anda buat. -service.gui.CREATE_FIRST_GROUP_WIZARD=Tidak ada grup dalam daftar kontak anda. Silahkan membuat sebuah grup dahulu. service.gui.CREATE_VIDEO_BRIDGE=Membuat jembatan &video... service.gui.CREATE_VIDEO_BRIDGE_MENU=Membuat jembatan &video service.gui.CONTACT_INFO_NOT_SUPPORTED=Kontak ini tidak mendukung informasi web service.gui.CUT=Potong -service.gui.DATE=Tanggal service.gui.DELETE=Hapus service.gui.DENY=Tolak service.gui.DESKTOP_SHARING_WARNING=Anda yakin ingin menmulai berbagi layar?
    Memilih OK akan mengijinkan orang dalam panggilan ini untuk melihat tampilan layar anda. @@ -176,7 +171,6 @@ service.gui.DISCONNECTED_STATUS=Terputus service.gui.DND_STATUS=Jangan diganggu service.gui.DO_NOT_ASK_AGAIN=Jangan tanya lagi service.gui.DO_NOT_SHOW_AGAIN=Jangan tampilkan pesan ini lagi -service.gui.DOWNLOAD_NOW=Unduh sekarang service.gui.DRAG_FOR_SHARING=Seret kesini apa saja yang ingin anda bagi... service.gui.DURATION=durasi service.gui.EDIT=&Edit @@ -193,7 +187,6 @@ service.gui.ERROR_WAS=Kesalahan yaitu: {0} service.gui.ESTIMATED_TIME=Perkiraan waktu: service.gui.EVENTS=Kejadian service.gui.EXIT=Keluar -service.gui.EXTENDED_CRITERIA=Kriteria tambahan service.gui.GENERAL=Umum service.gui.GENERAL_ERROR=Kesalahan umum service.gui.GROUP_NAME=Nama grup @@ -251,12 +244,12 @@ service.gui.HISTORY=Riwayat service.gui.HISTORY_CONTACT=Riwayat - {0} service.gui.HOME=Beranda service.gui.HOME_PAGE=Halaman Depan -service.gui.HOUR=Jam service.gui.ICE=ICE service.gui.IDENTIFIER=Pengenal service.gui.IGNORE=Abaikan service.gui.INSERT_SMILEY=Masukkan senyuman service.gui.INCOMING_CALL=Panggilan masuk diterima dari: {0} +service.gui.INCOMING_SCREEN_SHARE=Panggilan masuk diterima dari: {0} service.gui.INCOMING_CALL_STATUS=Panggilan masuk service.gui.INITIATING_CALL_STATUS=Memulai panggilan service.gui.INVITATION=Teks undangan @@ -269,11 +262,8 @@ service.gui.INVITE_CONTACT_TO_CALL=Undang kontak ke panggilan service.gui.INVITE_REASON=ALasan undangan service.gui.IS_CALLING=sedang memanggil... service.gui.IS_NOW={0} sekarang {1} -service.gui.JITSI_WARNING=SIP Communicator telah berganti nama menjadi Jitsi.
    Jika anda ingin versi milik anda tetap terkini, silahkan unduh Jitsi.

    Kami mohon maaf atass ketidaknyamanan ini

    Tim PengembangJitsi -service.gui.JITSI_WARNING_TITLE=SIP Communicator menjadi Jitsi service.gui.JOIN=Gabung service.gui.JOIN_AS=Gabung sebagai -service.gui.CLOSE_CHAT_ROOM_DIALOG=Tutup service.gui.JOB_TITLE=Pekerjaan service.gui.JOIN_CHAT_ROOM=Gabung ruang bincang... service.gui.JOIN_CHAT_ROOM_TITLE=Gabung ruang bincang @@ -284,7 +274,6 @@ service.gui.KICK_FAILED=Pengusiran gagal service.gui.KICK_FAILED_GENERAL_ERROR=Gagal mengusir {0}. Terjadi kesalahan umum server. service.gui.KICK_FAILED_NOT_ALLOWED=Gagal mengusir {0}. Pemilik dan administratur ruang tidak dapat diusir. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Gagal mengusir {0}. Anda tidak punya cukup hak untuk melakukannya. -service.gui.LAST=Teerakhir service.gui.LAST_NAME=Nama Belakang: service.gui.LEAVE=Pergi service.gui.LIMIT_REACHED_FOR_IP=Anda telah memiliki terlalu banyak pendaftaran dari alamat IP lokal dan server {0} tidak mengijinkan membuka lebih lanjut lagi. @@ -304,7 +293,6 @@ service.gui.MESSAGE=Pesan: service.gui.MISSED_CALLS_TOOL_TIP=Pesan tak terjawab dari: service.gui.MISSED_CALLS_MORE_TOOL_TIP= dan {0} lagi service.gui.MODERATOR=moderator -service.gui.MORE=Lihat lebih lanjut service.gui.MORE_LABEL=Pindah service.gui.MOVE=Pindah service.gui.MOVE_SUBCONTACT=Pindahkan Kontak @@ -313,7 +301,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Kontak yang anda pilih sama dengan sumber. Ha service.gui.MOVE_SUBCONTACT_QUESTION=Apa anda yakin ingin memindahkan {0} ke {1}? service.gui.MOVE_TO_GROUP=&Pindah ke grup service.gui.MOVE_CONTACT=Pindah Kontak -service.gui.MOVE_CONTACT_ERROR=Kontak tidak dapat dipindahkan service.gui.MSG_DELIVERY_FAILURE=Pesan diatas tidak dapat terkirim service.gui.MSG_DELIVERY_NOT_SUPPORTED=Protokol yang anda gunaakan tidak mendukung pesan offline. Anda dapat mencoba menghubungi kontak ini melalui protokol lain atau menunggu sampai dia online. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Sebuah kesalahan internal telah terjadi. Kemungkinan besar ini adalah cacat aplikasi. Harap laporkan ke: http://www.sip-communicator.org/index.php/Development/BugsAndIssues. Server mengembalikan error: {0} @@ -324,7 +311,6 @@ service.gui.MSG_NOT_POSSIBLE=Pengiriman pesan tidak dimungkinkan untuk kontak in service.gui.MSG_RECEIVED={0} menulis service.gui.MSG_SEND_CONNECTION_PROBLEM=Anda harus terhubung untuk dapat mengirim pesan. service.gui.MULTIPLE_LOGINS=Anda telah masuk lebih dari sekali dengan akun yang sama. Akun berikut: Nama Pengguna: {0}, Nama Server: {1} saat ini terputus. -service.gui.MUTE=Bisu service.gui.NAME=Nama service.gui.NETWORK=Jaringan service.gui.NETWORK_FAILURE=Kesalahan Jaringan @@ -334,6 +320,7 @@ service.gui.NEW_MESSAGE=Pesan baru service.gui.NEW_NAME=Nama baru service.gui.NEW_STATUS_MESSAGE=Status pesan baru service.gui.NEW_STATUS_MESSAGE_SAVE=Simpan sebagai pesan unik +service.gui.NICKNAME=Nama panggilan service.gui.NO=Tidak service.gui.NONE=Tidak ada service.gui.NO_CAMERA_AVAILABLE=Tidak ada kamera @@ -353,7 +340,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=TidakDiDaftarKontak service.gui.SD_QUALITY=Kualitas standard service.gui.OFFLINE=Offline service.gui.OK=OK -service.gui.OLDER_CALLS=Panggilan lama service.gui.ONLINE=Online service.gui.OPEN=Buka service.gui.OPEN_FILE_FROM_IMAGE=Klik ganda untuk membuka berkas. @@ -361,9 +347,12 @@ service.gui.OPEN_FOLDER=Buka folder service.gui.OPEN_IN_BROWSER=Buka di browser service.gui.OPTIONS=Pilihan service.gui.OR=atau -service.gui.OR_ENTER_PHONE_NUMBER=atau masukkan nomor telepon disini... service.gui.ORGANIZATION=Organization: service.gui.OTHER=Lainnya +service.gui.chat.role.ADMINISTRATOR=administratur +service.gui.chat.role.MODERATOR=moderator +service.gui.chat.role.MEMBER=anggota +service.gui.chat.role.SILENT_MEMBER=anggota diam service.gui.OWNER=pemilik ruang service.gui.PASSWORD=Kata Sandi service.gui.PASSWORD_CHANGE_FAILURE=Perubahan kata sandi gagal @@ -377,7 +366,6 @@ service.gui.PRESENCE=Kehadiran service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' untuk saran service.gui.PRESS_FOR_CALL_INFO=Tekan untuk informasi panggilan service.gui.PREVIOUS=Sebelumnya -service.gui.PREVIOUS_TOOLTIP=Jalajahi percakapan lama service.gui.PRINT=Cetak service.gui.PROACTIVE_NOTIFICATION=sedang mengetik pesan service.gui.PROTOCOL=Protokol @@ -389,7 +377,6 @@ service.gui.REASON=Alasan service.gui.RECONNECTION_LIMIT_EXCEEDED=Anda telah terputus dan menyambung kembali ke server terlalu cepat. Akun berikut: Nama Pengguna {0}, Nama Server: {1} sementara dicekal dan harus menunggu sementara sebelum mencoba untuk masuk lagi. service.gui.RE_REQUEST_AUTHORIZATION=Meminta otorisasi service.gui.REJECT=Tolak -service.gui.REMIND_ME_LATER=Ingatkan saya nanti service.gui.REMEMBER_PASSWORD=Ingat kata sandi service.gui.REMOVE=Hapus service.gui.REMOVE_ACCOUNT=Hapus akun @@ -413,27 +400,18 @@ service.gui.REVOKE_ADMIN=Batalkan administrasi service.gui.REVOKE_MODERATOR=Batalkan pengaturan service.gui.REVOKE_MEMBERSHIP=Batalkan keanggotaan service.gui.REVOKE_VOICE=Batalkan suara -service.gui.ROOT_GROUP=Grup utama service.gui.SAVE=Simpan -service.gui.SAVE_AS_DEFAULT=Simpan sebagai default service.gui.SEARCH=Cari service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Klik tombol dibawah untuk menampilkan semua ruang bincang yang terssedia di server terpilih. Lalu pilih satu yang anda ingin bergabung dan tekan tombol Gabung. service.gui.SEARCH_STRING_CONTACT_SOURCE=Kontak pencarian service.gui.SECURITY=Keamanan -service.gui.SELECT_ACCOUNT=Pilih akun service.gui.SELECT_COLOR=Pilih warna service.gui.SELECT_GROUP=Pilih grup -service.gui.SELECT_GROUP_WIZARD_MSG=daftar dibawah berisi seluruh grup dalam daftar kontak anda. Pilih satu yang anda ingin tambahkan kontak baru. service.gui.SELECT_NO_GROUP=Tidak ada grup -service.gui.SELECT_GROUP_WIZARD=Tentukan grup service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Daftar dibawah berisi seluruh akun yang mendukung fitur percakapan banyak pengguna. Pilih satu yang anda inginkan untuk membuat ruang bincang anda. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Daftar dibawah berisi seluruh akun yang terdaftar. Pilih satu yang anda inginkan untuk berkomunikasi dengan kontak baru. -service.gui.SELECT_PROVIDERS_WIZARD=Pilih aakun service.gui.SEND=Kirim service.gui.SEND_FILE=Kirim berkas -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Tidak ada informasi untuk kontak ini. service.gui.SEND_MESSAGE=Kirim sebuah pesan -service.gui.SEND_AS_SMS=Kirim sebagai SMS service.gui.SEND_SMS=Kirim SMS service.gui.SEND_SMS_DETAILS=Ingat bahwa abda perlu memasukkan angka dalam bentuk internasional, seperti dimulai dengan +62 untuk Indonesia dengan contoh +629998812345 service.gui.SEND_SMS_NOT_SUPPORTED=Protokol yang anda pilih tidak mendukung pesan SMS. @@ -468,7 +446,6 @@ service.gui.STREET=Jalan service.gui.SUBJECT=Subyek service.gui.SUMMARY=Ringkasan service.gui.TELEPHONY=Telephony -service.gui.TODAY=Hari ini service.gui.TOOLS=Perkakas service.gui.TRANSFER=Pengiriman service.gui.TO=Kepada: @@ -478,7 +455,6 @@ service.gui.TRANSFER_CALL_TO=Kirim Ke: service.gui.TRANSPARENCY_NOT_ENABLED=Transsparansi tidak didukung oleh konfigurasi anda saat ini. service.gui.TYPE_YOUR_REQUEST=Ketikkan permintaan anda disini service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Kami tidak dapat mengubah kualitas video untuk kontak ini. -service.gui.UNMUTE=Bersuara service.gui.USER_IDENTIFIER=Identitas pengguna: service.gui.USER_EXISTS_ERROR=Pengguna ini sudah ada di jaringan terpilih. Silahkan pilih pengguna atau jaringan lainnya. service.gui.USERNAME_NULL=Silahkan isi nama pengguna dan kata sandi anda. @@ -488,7 +464,6 @@ service.gui.UNKNOWN_STATUS=Keadaan tidak diketahui service.gui.UNREGISTERED_MESSAGE=Tidak dapat menghubungi akun berikut: Nama Pengguna: {0}, Nama Server: {1}. Anda saat ini offline. service.gui.VALUE=Nilai service.gui.VIDEO_CALL=Panggilan video -service.gui.VIA_SMS=Melalui SMS service.gui.VIEW=Tampilan service.gui.VIEW_HISTORY=Lihat riwayat service.gui.VIEW_SMILEYS=Lihat Senyuman @@ -508,9 +483,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Mengatur volume service.gui.WAITING_AUTHORIZATION=Menunggu otorisasi service.gui.WARNING=Peringatan service.gui.YES=Ya -service.gui.YESTERDAY=Kemarin -service.gui.EXISTING_ACCOUNT_ERROR=Akun yang anda ketikkan sudah terinstal. -service.gui.NEW_MAIL=Anda memiliki satu Surat baru!
    Dari: {0} {1}
    Subyek: {2}
    {3} service.gui.NEW_GMAIL_HEADER=Anda telah menerima sebuah surat baru dalam inbox {0} anda:
    service.gui.NEW_GMAIL_MANY_HEADER=Anda telah menerima {2} surat baru dalam inbox {0} anda:
    service.gui.NEW_GMAIL_FOOTER=satu atau lebih percakapan belum terbaca dalam inbox anda.
    @@ -563,7 +535,6 @@ service.gui.callinfo.CALL_INFORMATION=Informasi panggilan service.gui.callinfo.CALL_IDENTITY=Pengenal service.gui.callinfo.PEER_COUNT=jumlah peserta service.gui.callinfo.IS_CONFERENCE_FOCUS=fokus konferensi -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Penyandian aktif service.gui.callinfo.CALL_TRANSPORT=transport panggilan dihubungi service.gui.callinfo.CALL_DURATION=Durasi panggilan service.gui.callinfo.VIEW_CERTIFICATE=Tampilkan Sertifikat @@ -581,10 +552,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=protokol pertukaran kunci service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=tipe perluasan kandidat ICE service.gui.callinfo.ICE_STATE=Tahapan Pemrosesan ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=kumpulkan kandidat service.gui.callinfo.ICE_STATE.RUNNING=Memeriksa koneksi service.gui.callinfo.ICE_STATE.COMPLETED=Selesai service.gui.callinfo.ICE_STATE.FAILED=Gagal + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP / Port komputer lokal service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=IP / Port komputer remote service.gui.callinfo.DECODED_WITH_FEC=paket di-decode dengan FEC @@ -595,9 +569,10 @@ service.gui.ALWAYS_TRUST=Selalu percaya sertifikat ini service.gui.CERT_DIALOG_TITLE=Periksa Sertifikat service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} tidak dapat memeriksa indentitas server ketika menghubungi
    {1}:{2}.

    Sertifikat tidak terpercaya, yang berarti identitas server tidak dapat diperiksa secara otomatis. Apakah anda ingin meneruskan menyambung?

    Untuk informasi lebih lanjut, klik "Tampilkan Sertifikat". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} tidak dapat memeriksa indentitas server ketika menghubungi
    {1}:{2}.

    Sertifikat tidak terpercaya, yang berarti identitas server tidak dapat diperiksa secara otomatis. Apakah anda ingin meneruskan menyambung?

    Untuk informasi lebih lanjut, klik "Tampilkan Sertifikat". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} tidak dapat memeriksa indentitas server ketika menghubungi
    {1}:{2}.

    Sertifikat tidak terpercaya, yang berarti identitas server tidak dapat diperiksa secara otomatis. Apakah anda ingin meneruskan menyambung?

    Untuk informasi lebih lanjut, klik "Tampilkan Sertifikat". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} tidak dapat memeriksa indentitas server ketika menghubungi
    {1}:{2}.

    Sertifikat tidak terpercaya, yang berarti identitas server tidak dapat diperiksa secara otomatis. Apakah anda ingin meneruskan menyambung?

    Untuk informasi lebih lanjut, klik "Tampilkan Sertifikat". service.gui.CONTINUE_ANYWAY=Tetap lanjutkan + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Common Name: service.gui.CERT_INFO_O=Organization: service.gui.CERT_INFO_C=Country Name: @@ -611,12 +586,10 @@ service.gui.CERT_INFO_VER=Versi: service.gui.CERT_INFO_SIGN_ALG=Algoritma Tanda Tangan: service.gui.CERT_INFO_ALG=Algoritma service.gui.CERT_INFO_PUB_KEY=Kunci Publik: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Eksponen service.gui.CERT_INFO_KEY_SIZE=Panjang Kunci service.gui.CERT_INFO_SIGN=Tanda Tangan: -service.gui.CONTINUE=Lanjutkan service.gui.SHOW_CERT=Tampilkan Sertifikat service.gui.HIDE_CERT=Sembunyikan Sertifikat @@ -635,11 +608,9 @@ service.gui.security.SECURE_AUDIO=Audio diamankan service.gui.security.AUDIO_NOT_SECURED=Audio tidak diamankan service.gui.security.SECURE_VIDEO=Video diamankan service.gui.security.VIDEO_NOT_SECURED=Video tidak diamankan -service.gui.security.NO_VIDEO=Tidak ada video -service.gui.security.CIPHER=Penyandi: {0} +service.gui.security.CALL_SECURED_TOOLTIP=Panggilan diamankan. Untuk informasi lebih lanjut tekan disini. service.gui.security.CALL_NOT_SECURED_TOOLTIP=Panggilan tidak diamankan. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Tekan disini untuk membandingkan raasia keamanan dengan rekan anda. -service.gui.security.COMPARE_WITH_PARTNER=Bandingkan dengan rekan dan ketik gembok untuk konfirmasi. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Bandingkan dengan rekan: {0} service.gui.security.STRING_COMPARED=String terbandingkan! @@ -656,19 +627,13 @@ service.gui.avatar.imagepicker.CLICK=Tekan dan Senyum service.gui.avatar.imagepicker.IMAGE_FILES=Berkas gambar service.gui.avatar.imagepicker.IMAGE_PICKER=Gambar service.gui.avatar.imagepicker.IMAGE_SIZE=Ukuran gambar -service.gui.avatar.imagepicker.INITIALIZING=Memulai service.gui.avatar.imagepicker.RESET=Ulang service.gui.avatar.imagepicker.SET=Jadikan service.gui.avatar.imagepicker.TAKE_PHOTO=Mengambil foto -service.gui.avatar.imagepicker.WEBCAM_ERROR=kesalahan webcam service.gui.security.encryption.required=Enkripsi diperlukan -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Kesalahan di penyimpanan daftar kontak SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Resource tidak dapat membaca {0}. Untuk {1} @@ -691,9 +656,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=pilih jaringan # LDAP impl.ldap.CONFIG_FORM_TITLE=Konfigurasi LDAP impl.ldap.GENERAL=Umum -impl.ldap.NEW=Baru impl.ldap.EDIT=&Edit -impl.ldap.REMOVE=Hapus impl.ldap.ENABLED=Hidupkan impl.ldap.SERVER_NAME=Nama Server impl.ldap.SERVER_NAME_EXAMPLE=Server LDAP saya @@ -726,6 +689,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=telponRumah impl.ldap.PHONE_PREFIX=awalan Telpon impl.ldap.PHONE_PREFIX_EXAMPLE=Contoh: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Buku alamat plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Hidupkan pencarian buku alamat MacOSX @@ -735,9 +702,7 @@ plugin.addrbook.PREFIX_EXAMPLE=Contoh: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Kontak Google -impl.googlecontacts.NEW=Baru impl.googlecontacts.EDIT=&Edit -impl.googlecontacts.REMOVE=Hapus impl.googlecontacts.ENABLED=Hidupkan impl.googlecontacts.ACCOUNT_NAME=Nama Akun impl.googlecontacts.SAVE=Simpan @@ -764,9 +729,6 @@ plugin.accountinfo.EMAIL=Surel: plugin.accountinfo.PHONE=Telepon: plugin.accountinfo.MOBILE_PHONE=telponSeluler plugin.accountinfo.JOB_TITLE=Pekerjaan -plugin.accountinfo.USER_PICTURES=Gambar Pengguna -plugin.accountinfo.CHANGE=Ubah -plugin.accountinfo.ONLY_MESSAGE=Hanya pesan # connection info @@ -785,47 +747,12 @@ plugin.aimaccregwizz.USERNAME=Nama layar AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Nama layar dan kata sandi plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Daftarkan akun baru plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Jika anda tidak memiliki akun AIM, klik tombol ini untuk membuat yang baru. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Mengganti pilihan awal server # branding plugin.branding.ABOUT_WINDOW_TITLE=Tentang {0} plugin.branding.LOGO_MESSAGE=VoIP && Instant Messaging Open Source -plugin.branding.LOADING=Memuat plugin.branding.ABOUT_MENU_ENTRY=Tentang -plugin.branding.WELCOME_MESSAGE=
    {1} saat ini sedang aktif dikembangkan. Versi anda jalankan saat ini bersifat eksperimental dan MUNGKIN TIDAK bekerja sebagaimana mestinya. Silahkan merujuk ke {2} untuk informasi lebih lanjut.
    -plugin.branding.COPYRIGHT=
    (c)2003-2009 Hak Cipta sip-communicator.org. Semua hak terpelihara. Kunjungi http://sip-communicator.org.
    -plugin.branding.LICENSE=
    The SIP Communicator didistribusikan dalam lisensi LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Kamus -plugin.dictaccregwizz.ANY_DICTIONARY=Kamus Apa saja -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Kamus apa saja dari {0} -plugin.dictaccregwizz.FIRST_MATCH=Temuan Pertama -plugin.dictaccregwizz.NO_MATCH=Tidak ada yang cocok -plugin.dictaccregwizz.MATCH_RESULT=Tidak ada definisi ditemukan untuk "{0}", mungkin maksud anda:\n -plugin.dictaccregwizz.INVALID_DATABASE=Kamus "{0}" sudah tidak ada lagi di server. -plugin.dictaccregwizz.INVALID_STRATEGY=Strategi ini tidak tersedia di server. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Protokol layanan Dict -plugin.dictaccregwizz.HOST=Host -plugin.dictaccregwizz.SERVER_INFO=Informasi Server -plugin.dictaccregwizz.STRATEGY_SELECTION=Pilihan Strategi -plugin.dictaccregwizz.STRATEGY_LIST=Daftar Strategi: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Strategi pencarian -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategi digunakan untuk mencari kaa yang mirip jika sebuah terjemahan tidak ditemukan, berkat beragam pendekatan. Sebagai contoh, strategi Prefix akan mencari kata yang diawali mirip dengan kata yang ingin anda terjemahkan. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informasi Akun Dict -plugin.dictaccregwizz.THREAD_CONNECT=Mencoba menghubungi server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=hubungan gagal. ini bukan server dict atau server sedang offline -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Mengambil strategi -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Tidak ada strategi di server -plugin.dictaccregwizz.POPULATE_LIST=Mengumpulkan daftar -plugin.dictaccregwizz.CLOSING_CONNECTION=Menutup koneksi - -# facebookaccregwizz -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protokol Obrolan Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nama Pengguna -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nama layar dan kata sandi + # generalconfig plugin.generalconfig.AUTO_START=Menjalankan {0} otomatis saat komputer dinyalakan @@ -836,9 +763,6 @@ plugin.generalconfig.SHOW_HISTORY=Tampilkan plugin.generalconfig.HISTORY_SIZE=pesan terkini di obrolan baru plugin.generalconfig.SEND_MESSAGES_WITH=Kirim pesan dengan: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Bawa jendela obrolan ke depan -plugin.generalconfig.ERROR_PERMISSION=Jika anda tidak punya cukup hak untuk menghilangkan autostart -plugin.generalconfig.TRANSPARENCY=Tembus pandang -plugin.generalconfig.ENABLE_TRANSPARENCY=Hidupkan tembus pandang plugin.generalconfig.DEFAULT_LANGUAGE=Bahasa antar muka plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Perubahan anda akan berdampak setelah dinyalakan ulang berikutnya. plugin.generalconfig.SIP_CLIENT_PORT=PORT klien SIP @@ -880,18 +804,19 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Daftarkan akun baru plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=Protokol IRC plugin.ircaccregwizz.USERNAME_AND_PASSWORD=UIN dan kata sandi +plugin.ircaccregwizz.USERNAME=Nama panggilan plugin.ircaccregwizz.INFO_PASSWORD=Kebanyakan server IRC tidak membutuhkan password. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Otomatis mengganti panggilan jika sudah terpakai plugin.ircaccregwizz.USE_DEFAULT_PORT=Gunakan port awal plugin.ircaccregwizz.HOST=Hostname plugin.ircaccregwizz.IRC_SERVER=Server +plugin.ircaccregwizz.SASL_AUTHENTICATION_TITLE={0} autentikasi +plugin.ircaccregwizz.SASL_USERNAME=Nama Pengguna # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Protokol XMPP plugin.jabberaccregwizz.USERNAME=nama pengguna XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=konfirmasi kata sandi -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID dan kata sandi plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Hubungi Server plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Hidupkan keep alive @@ -907,13 +832,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Komentar plugin.jabberaccregwizz.RESOURCE=Resource plugin.jabberaccregwizz.AUTORESOURCE=Membuat resource otomatis plugin.jabberaccregwizz.PRIORITY=Prioritas -plugin.jabberaccregwizz.XMPP_ERROR=Kesalahan XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Kesalahan XMPP tidak diketahui. Periksa nama server telah benar. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Kata sandi tidak sama. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Mengganti pilihan awal server -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Pilihan lanjutan plugin.jabberaccregwizz.USE_ICE=Gunakan ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Gunakan Google Jingle/ICE (eksperimental) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Menemukan server STUN/TURN otomatis plugin.jabberaccregwizz.SUPPORT_TURN=Dukung TURN plugin.jabberaccregwizz.TURN_USERNAME=Nama pengguna TURN @@ -937,16 +858,9 @@ plugin.jabberaccregwizz.EXISTING_ACCOUNT=Akun XMPP telah ada plugin.jabberaccregwizz.DOMAIN_BYPASS_CAPS=Domain yang akan menggunakan panggilan GTalk plugin.jabberaccregwizz.TELEPHONY_DOMAIN=DOmain Telephony plugin.jabberaccregwizz.ALLOW_NON_SECURE=Izinkan koneksi tidak aman -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=konfirmasi kata sandi plugin.jabberaccregwizz.VIDEO=Video plugin.jabberaccregwizz.RESET=Ulang -# mailbox - -# msn accregwizz -plugin.msnaccregwizz.USERNAME=Surel: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID dan kata sandi - # plugin manager plugin.pluginmanager.NEW=Baru @@ -957,20 +871,15 @@ plugin.simpleaccregwizz.LOGIN_USERNAME=Nama Pengguna plugin.sipaccregwizz.PROTOCOL_NAME=SIP plugin.sipaccregwizz.PROTOCOL_DESCRIPTION=Protokol XMPP plugin.sipaccregwizz.USERNAME_AND_PASSWORD=Nama layar dan kata sandi -plugin.sipaccregwizz.ADVANCED_OPTIONS=Pilihan lanjutan -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Mengganti pilihan awal server plugin.sipaccregwizz.DISPLAY_NAME=Nama tampilan plugin.sipaccregwizz.EXISTING_ACCOUNT=Akun XMPP telah ada plugin.sipaccregwizz.CREATE_ACCOUNT=Membuat akun baru XMPP plugin.sipaccregwizz.XCAP_PASSWORD=Kata Sandi plugin.sipaccregwizz.NOT_SAME_PASSWORD=Kata sandi tidak sama. +#used from SecurityPanel # skin manager -# ssh accregwizz -plugin.sshaccregwizz.USERNAME=Info Akun -plugin.sshaccregwizz.OPTIONAL=Pilihan - # status update # updatechecker @@ -983,41 +892,31 @@ plugin.whiteboard.OPEN=Buka plugin.whiteboard.COLOR=Warna plugin.whiteboard.DELETE=Hapus -# yahoo accregwizz -plugin.yahooaccregwizz.USERNAME=Nama Pengguna -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID dan kata sandi - -# zero accregwizz -plugin.zeroaccregwizz.FIRST_NAME=Nama Depan: -plugin.zeroaccregwizz.LAST_NAME=Nama Belakang: -plugin.zeroaccregwizz.EMAIL=Surel: -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID dan kata sandi -plugin.zeroaccregwizz.USERID=ID Pengguna: - # gtalk accregwizz plugin.googletalkaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Jika anda tidak memiliki akun AIM, klik tombol ini untuk membuat yang baru. # iptel accregwizz plugin.iptelaccregwizz.USERNAME=Nama Pengguna -# sip2sip accregwizz -plugin.sip2sipaccregwizz.USERNAME=Nama Pengguna -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Membuat akun baru XMPP - # ippi accregwizz +plugin.sip2sipaccregwizz.USERNAME=Nama Pengguna plugin.ippiaccregwizz.EXISTING_ACCOUNT=Akun XMPP telah ada plugin.ippiaccregwizz.CREATE_ACCOUNT=Membuat akun baru XMPP # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=Salin plugin.keybindings.CHAT_CUT=Potong plugin.keybindings.CHAT_PASTE=Rekat plugin.keybindings.MAIN_RENAME=Ganti nama kontak plugin.keybindings.globalchooser.SHORTCUT_NAME=Nama +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Bincang # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=Hidupkan plugin.notificationconfig.RESTORE=Kembalikan awal +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Panggilan masuk plugin.notificationconfig.event.IncomingFile=Panggilan masuk plugin.notificationconfig.event.HangUp=Gantung @@ -1037,6 +936,7 @@ impl.media.configform.VIDEO_RESET=Kembalikan awal impl.neomedia.configform.VIDEO=Video +#in JNIEncoder impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTP # The callrecordingconfig plugin was never really committed into trunk and its @@ -1051,7 +951,6 @@ plugin.securityconfig.masterpassword.MP_CHANGE_SUCCESS_MSG=Kata sandi berhasil d plugin.securityconfig.masterpassword.MP_REMOVE_SUCCESS_MSG=Kata sandi berhasil diubah plugin.securityconfig.masterpassword.COL_NAME=Nama plugin.securityconfig.masterpassword.COL_PASSWORD=Kata Sandi -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Hapus # otr plugin plugin.otr.menu.CB_RESET=Ulang @@ -1072,6 +971,7 @@ plugin.reconnectplugin.CONNECTION_FAILED_MSG=Koneksi gagal untuk akun berikut: N #plugin chat config plugin.chatconfig.TITLE=Bincang +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Hidupkan #provisioning plugin @@ -1085,7 +985,6 @@ net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=Abaikan net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=Tolak #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=&Edit #Certificate configuration plugin -- cgit v1.1 From f32e12fd8310de3d86a2a3e0a26b4a220ffe9be3 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 18 Jan 2017 23:59:57 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 703 of 1505 strings translated (137 fuzzy). --- resources/languages/resources_si.properties | 189 +++++----------------------- 1 file changed, 29 insertions(+), 160 deletions(-) diff --git a/resources/languages/resources_si.properties b/resources/languages/resources_si.properties index 909a419..be6326f 100644 --- a/resources/languages/resources_si.properties +++ b/resources/languages/resources_si.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,24 +43,18 @@ service.gui.ACCOUNT_ME=මම service.gui.ACCOUNT_REGISTRATION_WIZARD=ගිණුම ලියාපදිංචි කිරීමේ සහකරු service.gui.ACCOUNTS=ගිණුම් service.gui.ADD=එකතු කරන්න (&A) -service.gui.ADD_ACCOUNT=ගිණුමක් එකතු කරන්න service.gui.ADD_CONTACT=සබැඳුමක් එකතු කරන්න (&A) service.gui.ADD_CONTACT_TO=සබැඳුමක් එකතු කරන්න (&A) - service.gui.ADD_CONTACT_ERROR={0} යන සබැඳුම එකතු කිරීම අසාර්ථක විය service.gui.ADD_CONTACT_ERROR_TITLE=සබැඳුම එකතු කිරීම අසාර්ථක විය service.gui.ADD_CONTACT_EXIST_ERROR={0} යන සබැඳුම දැනටමත් ඔබේ ලැයිස්තුවේ අන්තර්ගතයි. -service.gui.ADD_CONTACT_IDENTIFIER=පහත තීරුවේ ඔබ එකතු කිරීමට යන සබැඳුමේ හඳුන්වනය ඇතුලත් කරන්න. -service.gui.ADD_CONTACT_WIZARD=සබැඳුම් එකතු කිරීමේ සහකරු service.gui.ADD_GROUP_LOCAL_ERROR={0} යන නම සහිත සමූහය එකතු කිරීම අසාර්ථක විය. මෙම පද්ධතියේ IO operation එකක් අතරතුර දෝශයක් ඇතිවිය. service.gui.ADD_GROUP_EXIST_ERROR={0} යන සමූහය දැනටමත් ඔබේ ලැයිස්තුවේ අන්තර්ගතයි. කරුණාකර වෙනත් නමක් ඇතුලත් කරන්න. service.gui.ADD_GROUP_NET_ERROR=ජාල දෝශයක් හේතුවෙන් {0} යන නම සහිත සමූහය එකතු කිරීම අසාර්ථක විය. කරුණාකර ඔබගේ ජාල සම්බන්ධතාව පරීක්ෂාකර නැවත උත්සාහ කරන්න. service.gui.ADD_GROUP_ERROR={0} යන නම සහිත සමූහය එකතු කිරීම අසාර්ථක විය. service.gui.ADD_GROUP_EMPTY_NAME=සමූහ නාමය හිස් විය නොහැක. -service.gui.ADD_GROUP=සමූහයක් සාදන්න -service.gui.ADD_SUBCONTACT=උප-සබැඳුමක් එකතු කරන්න (&A) service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=වැඩිමනත් (&A) -service.gui.ALL=සියල්ල (&A) service.gui.ALL_CONTACTS=සියලු සබැඳුම් (&A) service.gui.APPLY=ක්‍රියාත්මක කරන්න (&A) service.gui.ARE_CALLING=අමතමින්... @@ -57,7 +62,6 @@ service.gui.ARE_NOW=ඔබ දැන් {0} service.gui.AT=වේලාව: service.gui.AUTHORIZATION_ACCEPTED=මෙම සබැඳුම ඔබේ ඉල්ලීම අනුමත කර ඇත. service.gui.AUTHENTICATION_FAILED=අවසර නොලැබේ. ඔබ ඇතුලත් කල රහස් පදය වැරදියි. -service.gui.AUTHENTICATION_REQUESTED=සත්‍යතා සහතික කිරීමක් ඉල්ලුම් කර ඇත. service.gui.AUTHENTICATION_REQUESTED_SERVER={0} server එක ඔබේ අනන්‍යතාව සහතික කිරීමට ඉල්ලුම් කර ඇත. service.gui.AUTHENTICATION_REJECTED=මෙම සබැඳුම ඔබේ ඉල්ලීම ප්‍රතික්ෂේප කර ඇත. service.gui.AUTHENTICATION_WINDOW_TITLE={0} සත්‍යතා සහතික කිරීම @@ -97,12 +101,10 @@ service.gui.CHAT_ROOM_USER_KICKED={0}න් එලවන ලදි service.gui.CHAT_ROOM_USER_QUIT={0} සමු ගත්තා service.gui.CHAT_ROOM_NAME=සංවාදයේ නම service.gui.ROOM_NAME=සංවාද මණ්ඩපය -service.gui.AUTOJOIN=ස්වයංක්‍රීය සම්බන්ධවීම service.gui.CHAT_ROOM_NAME_INFO=පහත තීරුවේ ඔබ සෑදීමට යන සංවාද මණ්ඩපය සඳහා නම ඇතුලත් කරන්න. service.gui.CHAT_ROOM_NOT_EXIST={0} කුටිය {1} server එකේ සොයාගත නොහැක. කරුණාකර ඔබ ඇතුලත් කළ නම නිවැරදිදැයි තහවුරු කරගන්න. service.gui.CHAT_ROOM_NOT_CONNECTED={0} සංවාදයට සම්බන්ධ වීම සඳහා ඔබ ප්‍රවේශවී (log-in) තිබිය යුතුය. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=සංවාදයකින් ඉවත්වීම සඳහා ඔබ ප්‍රවේශවී (log-in) තිබිය යුතුය. -service.gui.CHAT_ROOM_NOT_JOINED=වැඩිදුර ක්‍රියාකාරකම්වලට ප්‍රථමයෙන් සංවාදයට සම්බන්ධවී සිටිය යුතුය. service.gui.CHAT_ROOM_OPTIONS=සංවාද මණ්ඩප සැකසුම් service.gui.CHAT_ROOM_REGISTRATION_REQUIRED={0} සංවාදයට සම්බන්ධ වීම සඳහා ලියාපදිංචි පෝරමයක් අවශ්‍යවේ. service.gui.CHAT_ROOM_REQUIRES_PASSWORD={0} සංවාද මණ්ඩපය රහස්පදයක් ඉල්ලා සිටියි. @@ -112,14 +114,11 @@ service.gui.CHAT_ROOM_SUBJECT_CHANGED={0}හි මාතෘකාව {1} ලෙ service.gui.CLOSE=වහන්න (&o) service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=ඔබ‍ට අවසානවරට පණිවිඩය ලැබුණේ මෙයට තත්පර දෙකකටත් අඩු කාලයක් ඉහතදීය. ඔබට සැබවින්ම ඉවත්වීමට අවශ්‍යද? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=දැනටමත් ඔබේ ගොනු හුවමාරු වෙමින් පවතී. ඒවා අහෝසි කිරීම තහවුරු කරන්න. -service.gui.CONFIRM=තහවුරු කරන්න service.gui.CONNECTING=සම්බන්ධ වෙමින්... service.gui.CONNECTING_STATUS=සබැඳුම service.gui.CONNECTING_EARLY_MEDIA_STATUS=සම්බන්ධ වෙමින්... service.gui.CONNECTION=සබැඳුම -service.gui.CONNECTION_FAILED_MSG=පහත ගිණුම සමග සම්බන්ධවීම අසාර්ථක විය.පරිශීලක නාමය: {0}, Server නාමය: {1}. කරුණාකර ඔබගේ ජාල සබැඳුම පරීක්ෂා කරන්න. නැතහොත් වැඩි විස්තර ජාල administratorගෙන් ලබා ගන්න. service.gui.CONNECTION_EXPIRED_MSG={0} server එක සමග ඔබ දැන‍ට සම්බන්ධවී නොමැත. -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=තෝරන ලද {0} සබැඳුම දුරකථන සහාය නොදක්වයි. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=තෝරන ලද {0} සබැඳුම සම්මන්ත්‍රණ සඳහා සහාය නොදක්වයි. service.gui.CONTACT_PAUSED_TYPING={0} පණිවිඩය ඇතුලත් කිරීම නැවැත්වූවා service.gui.CONTACT_TYPING={0} පණිවිඩයක් ඇතුලත් කරමින් සිටියි @@ -132,13 +131,10 @@ service.gui.CREATE_CHAT_ROOM=සංවාද මණ්ඩපක් සාදන service.gui.CREATE_CHAT_ROOM_ERROR={0} සංවාද මණ්ඩපක් සෑදීම අසාර්ථක විය. service.gui.CREATE_CHAT_ROOM_WIZARD=සංවාද මණ්ඩප සෑදීමේ සහකරු service.gui.CREATE_CONFERENCE_CALL=සම්මන්ත්‍රණ ඇමතුමක් ගන්න... (&C) -service.gui.CREATE_CONFERENCE_CHAT=සම්මන්ත්‍රණයක් ආරම්භ කරන්න... (&C) service.gui.CREATE_GROUP=සමූහයක් සාදන්න... (&C) service.gui.CREATE_GROUP_NAME=පහත තීරුවේ ඔබ සෑදීමට යන සමූහය සඳහා නම ඇතුලත් කරන්න. -service.gui.CREATE_FIRST_GROUP_WIZARD=ඔබේ සබඳතා ලැයිස්තුවේ කිසිඳු සමූහයක් අඩංගු නොවේ. කරුණාකර ප්‍රථමයෙන් සමූයක් සාදන්න (ගොනු මෙනුවෙන්). service.gui.CONTACT_INFO_NOT_SUPPORTED=මෙම සබැඳුම ජාල සබඳතා තොරතුරු සඳහා සහාය නොදක්වයි service.gui.CUT=කපන්න (&U) -service.gui.DATE=දිනය service.gui.DELETE=මකන්න service.gui.DESKTOP_SHARING_WARNING=තිරය පෙන්වීට අවශ්‍යබව තහවුරු කරන්න
    'හරි' එබීමෙන් පසු ඔබගේ පරිගණක තිරය මෙම ඇමතුමට සම්බන්ධව ඇති අයට දිස්වනු ඇත. service.gui.DIALPAD=ඇමතුම් පැනලය @@ -159,7 +155,6 @@ service.gui.ERROR_WAS=දෝෂය: {0} service.gui.ESTIMATED_TIME=ඇස්තමේන්තුගත කාලය: service.gui.EVENTS=සිදුවීම් service.gui.EXIT=පිටවෙන්න (&X) -service.gui.EXTENDED_CRITERIA=වැඩිදුර නිර්ණායක service.gui.GENERAL=සාමාන්‍ය service.gui.GENERAL_ERROR=සාමාන්‍ය දෝෂයක් service.gui.GROUP_NAME=සමූහ නාමය @@ -213,7 +208,6 @@ service.gui.HIDE_OFFLINE_CONTACTS=ජාලයට සම්බන්ධනොව service.gui.HIDE_MAIN_WINDOW=
    කතිර ලකුණ එබීමෙන් මෙය ඉවත් නොවේ, කවුලුව සඟවයි. ඔබට ඉවත්වීමට අවශ්‍ය නම් ගොනු/පිටවෙන්න තෝරන්න
    service.gui.HISTORY=අතීතය (&H) service.gui.HISTORY_CONTACT=අතීතය - {0} -service.gui.HOUR=පැය service.gui.IDENTIFIER=හඳුන්වනය service.gui.IGNORE=නොසලකා හරින්න (&I) service.gui.INSERT_SMILEY=සිනා-මුහුණක් යොදන්න @@ -230,7 +224,6 @@ service.gui.IS_CALLING=අමතයි... service.gui.IS_NOW={0} දැන් {1} නම්වේ service.gui.JOIN=එකතුවෙන්න (&J) service.gui.JOIN_AS=...ලෙස එකතුවෙන්න (&O) -service.gui.CLOSE_CHAT_ROOM_DIALOG=වසන්න (&L) service.gui.JOIN_CHAT_ROOM=සංවාද මණ්ඩපයට එකතුවෙන්න... (&J) service.gui.JOIN_CHAT_ROOM_TITLE=සංවාද මණ්ඩපයට එකතුවෙන්න... service.gui.JOIN_CHAT_ROOM_NAME=කරුණාකර ඔබ සම්බන්ධවීමට කැමති සංවාද මණ්ඩපයේ නම ඇතුලත් කරන්න. @@ -240,7 +233,6 @@ service.gui.KICK_FAILED=ඉවත් කිරීම අසාර්ථක ව service.gui.KICK_FAILED_GENERAL_ERROR={0} ඉවත් කිරීම අසාර්ථක විය. පොදු server දෝශයක් ඇතිවිය. service.gui.KICK_FAILED_NOT_ALLOWED={0} ඉවත් කිරීම අසාර්ථක විය. මෙම කුටියේ අයිතිකරු ඉවත් කල නොහැකිවිය. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS={0} ඉවත් කිරීම අසාර්ථක විය. ඔබට ඒ සඳහා වරප්‍රසාද නොමැත. -service.gui.LAST=අවසාන service.gui.LAST_NAME=අවසාන නම: service.gui.LEAVE=පිටවෙන්න (&L) service.gui.LIMIT_REACHED_FOR_IP=ඔබට දැනටමත් මෙම IP ලිපිනයෙන් ලියාපදිංචිවීම් විශාල ප්‍රමාණයක් ඇත. server {0} තවත් ලියාපදිංචිවීම් සඳහා ඉඩ ලබා නොදෙයි. @@ -255,7 +247,6 @@ service.gui.MEMBER=සාමාජිකයා service.gui.MESSAGE=පණිවිඩය: service.gui.MISSED_CALLS_MORE_TOOL_TIP= සහ තවත් {0}ක් service.gui.MODERATOR=සභාපති -service.gui.MORE=වැඩිමනත් විස්තර service.gui.MORE_LABEL=තැන්මාරු කරන්න service.gui.MOVE=තැන්මාරු කරන්න service.gui.MOVE_SUBCONTACT=සබැඳුම මාරු කරන්න (&O) @@ -264,7 +255,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=ඔබ තේරූ සබැඳුම මු service.gui.MOVE_SUBCONTACT_QUESTION=ඔබට {0}, {1}‍ වෙත මාරුකිරීමට අවශ්‍යබව තහවුරු කරන්න. service.gui.MOVE_TO_GROUP=සමූහයට මාරු කරන්න. (&M) service.gui.MOVE_CONTACT=සබැඳුම මාරු කරන්න -service.gui.MOVE_CONTACT_ERROR=සබැඳුම මාරු කිරීමට නොහැක (&C) service.gui.MSG_DELIVERY_FAILURE=ඉහත පණිවිඩය බාරදීමට නොහැකිවිය service.gui.MSG_DELIVERY_NOT_SUPPORTED=ඔබ පාවිච්චි කරන ප්‍රොටෝකෝලය ජාලයට සම්බන්ධනොවී පණිවිඩ යැවීමට සහාය නොදක්වයි. මෙම සබැඳුම සමග වෙනත් ප්‍රොටෝකෝලයකින් සම්බන්ධවීමට උත්සාහ කරන්න. නැතහොත් ඔහු/ඇය ජාලයට සම්බන්ධවනතුරු රැඳී සිටින්න. service.gui.MSG_DELIVERY_INTERNAL_ERROR=අභ්‍යන්තර දෝශයක් ඇතිවිය. බොහෝදුරට මෘදුකාංගයේ දොශයක් වියහැක. කරුණාකර මෙතැනට වාර්තා කරන්න: http://www.sip-communicator.org/index.php/Development/BugsAndIssues. @@ -275,7 +265,6 @@ service.gui.MSG_NOT_POSSIBLE=මෙම සබැඳුමට පණිවිඩ service.gui.MSG_RECEIVED={0} ගෙන් service.gui.MSG_SEND_CONNECTION_PROBLEM=පණිවිඩ යැවීමට ඔබ ජාලයට සම්බන්ධවී සිටිය යුතුය. service.gui.MULTIPLE_LOGINS=ඔබ එකම ගිණුමෙන් එක් වරකට වඩා ප්‍රවේශවී ඇත. {0} පරිශීලක නාමය සහ {1} server නාමය සහිත ගිණුම දැනට විසන්ධිවී ඇත. -service.gui.MUTE=නිශ්ශබ්ද service.gui.NAME=නම service.gui.NETWORK=ජාලය service.gui.NETWORK_FAILURE=ජාල දෝශයක් @@ -294,7 +283,6 @@ service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=ඔබ නොයැවූ පණිව service.gui.NON_EXISTING_USER_ID={0} server එක මෙම පරිශීලක නාමය හඳුනා නොගනී. service.gui.OFFLINE=විසන්ධිව service.gui.OK=හරි (&O) -service.gui.OLDER_CALLS=පසුගිය ඇමතුම් service.gui.ONLINE=සම්බන්ධව service.gui.OPEN=විවෘත කරන්න service.gui.OPEN_FILE_FROM_IMAGE=ගොනුව විවෘත කිරීම සඳහා double click කරන්න. @@ -302,7 +290,6 @@ service.gui.OPEN_FOLDER=බහාලුම විවෘත කරන්න service.gui.OPEN_IN_BROWSER=අන්තර්ජාල ගවේශකයේ විවෘත කරන්න (&B) service.gui.OPTIONS=තේරීම් service.gui.OR=හෝ -service.gui.OR_ENTER_PHONE_NUMBER=හෝ මෙතැන දුකතන අංකය ඇතුලත් කරන්න... service.gui.ORGANIZATION=සංවිධානය: service.gui.OWNER=කුටියේ අයිතිකරු service.gui.PASSWORD=රහස්පදය @@ -313,7 +300,6 @@ service.gui.PORT=තොටුපළ service.gui.PRESENCE=පැවැත්ම service.gui.PRESS_ENTER_FOR_SUGGESTIONS=යෝජනා සඳහා: 'Enter' service.gui.PREVIOUS=පසුගිය -service.gui.PREVIOUS_TOOLTIP=පසුගිය සංවාද පිරික්සන්න service.gui.PRINT=මුද්‍රණය (&P) service.gui.PROACTIVE_NOTIFICATION=පණිවිඩයක් සටහන් කරමින්... service.gui.PROTOCOL=ප්‍රොටෝකෝලය @@ -346,25 +332,17 @@ service.gui.REVOKE_ADMIN=admin අවලංගුකරන්න service.gui.REVOKE_MODERATOR=moderator අවලංගුකරන්න service.gui.REVOKE_MEMBERSHIP=සාමාජිකත්වය අවලංගුකරන්න service.gui.REVOKE_VOICE=කටහඬ අහෝසිකරන්න -service.gui.ROOT_GROUP=ප්‍රධාන සමූහය service.gui.SAVE=සුරකින්න (&S) service.gui.SEARCH=සොයන්න (&S) service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=තෝරාගත් server එකෙහි ඇති සියලු සංවාද මණ්ඩප පෙන්වීමට පහත බොත්තම ඔබා ඔබ සම්බන්ධවීමට කැමති මණ්ඩපට තෝරන්න. service.gui.SECURITY=ආරක්ෂාව -service.gui.SELECT_ACCOUNT=ගිණුම තෝරන්න service.gui.SELECT_COLOR=පාට තෝරන්න service.gui.SELECT_GROUP=සමූහය තෝරන්න -service.gui.SELECT_GROUP_WIZARD_MSG=පහත ලැයිස්තුවේ ඔබේ සබඳතා ලැයිස්තුවේ ඇති සියලු සමූහයන් අන්තර්ගතවේ. නව සබැඳුම එකතුවිය යුතු සමූහය තෝරන්න. service.gui.SELECT_NO_GROUP=සමූහයක් නොමැත -service.gui.SELECT_GROUP_WIZARD=සමූහය සඳහන් කරන්න service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=පහත ලැයිස්තුවේ බහු පරිශීලක සංවාද සඳහා සහය දක්වන සියලු ගිණම් අන්තර්ගතවේ. ඔබේ සංවාද මණ්ඩපය සෑදීම සඳහා යොදාගැනීමට අවශ්‍ය ගිණුම තෝරන්න. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=පහත ලැයිස්තුවේ ඔබ ලියාපදිංචිවූ සියලු ගිණම් අන්තර්ගතවේ. නව සබැඳුම සමග අදහස් හුවමාරු කිරීමට අවශ්‍ය ගිණුම තෝරන්න. -service.gui.SELECT_PROVIDERS_WIZARD=ගිණුම තෝරන්න. service.gui.SEND=යවන්න (&S) service.gui.SEND_FILE=ගොනුව යවන්න (&F) -service.gui.SELECT_CONTACT_SUPPORTING_INFO=මෙම සබැඳුම සඳහා තොරතුරු කිසිවක් නොමැත. service.gui.SEND_MESSAGE=පණිවිඩයක් යවන්න (&S) -service.gui.SEND_AS_SMS=කෙටි පණිවිඩයක් ලෙස යවන්න service.gui.SEND_SMS=කෙටි පණිවිඩය යවන්න (&E) service.gui.SEND_SMS_DETAILS=මෙය ජාත්‍යන්තර අංකයක් ලෙස ඇතුලත්කළ යුතු බව මතක තබාගන්න.උදා- ශ්‍රී ලංකාවේ අංකයක් +94 ලෙස ආරම්භ කරන්න, +941110000000 service.gui.SEND_SMS_NOT_SUPPORTED=ඔබ තෝරන ලද ගිණුම කෙටි පණිවිඩ සඳහා සහාය නොදක්වයි. @@ -391,7 +369,6 @@ service.gui.STATUS_CHANGE_NETWORK_FAILURE=ජාල දෝශයක් හේත service.gui.STATUS_MESSAGE_INFO=ඔබට පහත තීරුවේ නව පණිවිඩය ඇතුලත් කළ හැක. service.gui.SUBJECT=මාතෘකාව service.gui.SUMMARY=සාරාංශය -service.gui.TODAY=අද service.gui.TOOLS=මෙවලම් service.gui.TRANSFER=පවරන්න (&F) service.gui.TO=වෙත: (&T) @@ -400,7 +377,6 @@ service.gui.TRANSFER_CALL_TITLE=ඇමතුම පවරන්න service.gui.TRANSFER_CALL_TO=වෙත පවරන්න: service.gui.TRANSPARENCY_NOT_ENABLED=ඔබේ වර්තමාන සැකසුම් පාරදෘශ්‍යතාව සඳහා සහාය නොදක්වයි. service.gui.TYPE_YOUR_REQUEST=මෙතැන ඔබේ ඉල්ලීම ඇතුලත් කරන්න. -service.gui.UNMUTE=නිශ්ශබ්දතාව අහෝසි කරන්න service.gui.USER_IDENTIFIER=පරිශීලක හඳුන්වනය: service.gui.USER_EXISTS_ERROR=තේරූ ජාලයේ දැනටමත් මෙම පරිශිලකයා පවතී. කරුණාකර වෙනත් පරිශිලකයෙක් හෝ ජාලයක් තෝරන්න. service.gui.ACCOUNT_CREATION_FAILED=මෙම දෝශය හේතුවෙන් ඔබේ ගිණුම සෑදීම අසාර්ථක විය: {0} @@ -414,9 +390,6 @@ service.gui.VIEW_TOOLBAR=මෙවලම් තීරුව පෙන්වන service.gui.VOICEMAIL_NO_MESSAGES=පණිවිඩයක් නොමැත service.gui.WARNING=අවවාදයයි service.gui.YES=ඔව් -service.gui.YESTERDAY=ඊයේ -service.gui.EXISTING_ACCOUNT_ERROR=ඔබ ඇතුලත්කළ ගිණුම දැනටමත් ස්ථාපනය කර ඇත. -service.gui.NEW_MAIL=ඔබට නව ලිපියක් තිබේ!
    එවන්නා: {0} {1}
    මාතෘකා‍ව: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=ඔබේ {0} inbox එකට නව ලිපියක් ලැබී ඇත:
    service.gui.NEW_GMAIL_MANY_HEADER=ඔබේ {0} inbox එකට නව ලිපි {2}ක් ලැබී ඇත:
    service.gui.NEW_GMAIL_FOOTER=ඔබේ inbox එකේ නොකියවූ තවත් එක් සංවාදයක් තිබේ.
    @@ -436,7 +409,6 @@ service.gui.SECURITY_WARNING=ආරක්ෂක අවවාදය service.gui.SECURITY_ERROR=ආරක්ෂණ දෝශය service.gui.SPEED=වේගය: service.gui.SILENT_MEMBER=සාමාජිකයා නිශ්ශබ්ද කරන්න -service.gui.UPDATE=යාවත්කාලීන service.gui.VIDEO_PHONE=දෘශ්‍ය service.gui.PHONE=දුරකතනය: service.gui.PHONES=දුරකතනය: @@ -459,12 +431,16 @@ service.gui.callinfo.VIEW_CERTIFICATE=සහතිකය පෙන්වන් service.gui.callinfo.MEDIA_STREAM_RTP=ZRTP service.gui.callinfo.MEDIA_STREAM_SRTP=ZRTP +#enum values from IceProcessingState + + service.gui.ALWAYS_TRUST=මෙම සහතිකය සෑමවිටම විශ්වාස කරන්න service.gui.CERT_DIALOG_TITLE=සහතිකය තහවුරු කරන්න service.gui.CERT_DIALOG_DESCRIPTION_TXT={1}:{2} වෙත සම්බන්ධවීමේදී server එකෙහි අනන්‍යතාව {0}ට තහවුරු කරගත නොහැක.

    සහතිකය විශ්වාස කළ නොහැකි බැවින් server එකෙහි අනන්‍යතාව ස්වයංක්‍රීයව තහවුරු කරගත නොහැක. ඔබට මෙම සම්බන්ධවීම පවත්වාගෙන යාමට අවශ්‍යද?

    වැඩිදුර තොරතුරු සඳහා "සහතිකය පෙන්වන්න" යන්න ඔබන්න. service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={1}:{2} වෙත සම්බන්ධවීමේදී server එකෙහි අනන්‍යතාව {0}ට තහවුරු කරගත නොහැක.

    සහතිකය විශ්වාස කළ නොහැකි බැවින් server එකෙහි අනන්‍යතාව ස්වයංක්‍රීයව තහවුරු කරගත නොහැක. ඔබට මෙම සම්බන්ධවීම පවත්වාගෙන යාමට අවශ්‍යද?

    වැඩිදුර තොරතුරු සඳහා "සහතිකය පෙන්වන්න" යන්න ඔබන්න. -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={1}:{2} වෙත සම්බන්ධවීමේදී server එකෙහි අනන්‍යතාව {0}ට තහවුරු කරගත නොහැක.

    සහතිකය විශ්වාස කළ නොහැකි බැවින් server එකෙහි අනන්‍යතාව ස්වයංක්‍රීයව තහවුරු කරගත නොහැක. ඔබට මෙම සම්බන්ධවීම පවත්වාගෙන යාමට අවශ්‍යද?

    වැඩිදුර තොරතුරු සඳහා "සහතිකය පෙන්වන්න" යන්න ඔබන්න. service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={1}:{2} වෙත සම්බන්ධවීමේදී server එකෙහි අනන්‍යතාව {0}ට තහවුරු කරගත නොහැක.

    සහතිකය විශ්වාස කළ නොහැකි බැවින් server එකෙහි අනන්‍යතාව ස්වයංක්‍රීයව තහවුරු කරගත නොහැක. ඔබට මෙම සම්බන්ධවීම පවත්වාගෙන යාමට අවශ්‍යද?

    වැඩිදුර තොරතුරු සඳහා "සහතිකය පෙන්වන්න" යන්න ඔබන්න. + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=පොදු නාමය: service.gui.CERT_INFO_O=සංවිධානය: service.gui.CERT_INFO_C=රට: @@ -478,18 +454,15 @@ service.gui.CERT_INFO_VER=සංස්කරණය: service.gui.CERT_INFO_SIGN_ALG=මුද්‍රා ඇල්ගොරිතමය: service.gui.CERT_INFO_ALG=ඇල්ගොරිතමය: service.gui.CERT_INFO_PUB_KEY=පොදු යතුර: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} බයිට්: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} බිට් service.gui.CERT_INFO_EXP=ප්‍රකාශකයා: service.gui.CERT_INFO_KEY_SIZE=යතුරේ ප්‍රමාණය: service.gui.CERT_INFO_SIGN=මුද්‍රාව: -service.gui.CONTINUE=පවත්වාගන්න service.gui.SHOW_CERT=සහතිකය පෙන්වන්න service.gui.HIDE_CERT=සහතිකය සඟවන්න service.gui.AUTO_ANSWER_VIDEO=දෘශ්‍ය -service.gui.security.COMPARE_WITH_PARTNER=සහකරු සමග සසඳාබලා තහවුරුකිරීම සඳහා ඉබියතුර ඔබන්න. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT={0} සහකරු සමග සසඳන්න @@ -503,18 +476,12 @@ service.gui.avatar.imagepicker.CLICK=ඔබා සිනාසෙන්න service.gui.avatar.imagepicker.IMAGE_FILES=පිළිබිඹු ගොනු service.gui.avatar.imagepicker.IMAGE_PICKER=රූපය service.gui.avatar.imagepicker.IMAGE_SIZE=පිළිබිඹුවේ ප්‍රමාණය -service.gui.avatar.imagepicker.INITIALIZING=අරඹමින් service.gui.avatar.imagepicker.RESET=නැවත පිහිටුවන්න service.gui.avatar.imagepicker.SET=තෝරන්න service.gui.avatar.imagepicker.TAKE_PHOTO=ඡායාරූපයක් ගන්න -service.gui.avatar.imagepicker.WEBCAM_ERROR=වෙබ්කැමරාවේ දෝශයක් -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ # systray @@ -533,9 +500,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=ජාලය තෝරන්න # LDAP impl.ldap.GENERAL=සාමාන්‍ය -impl.ldap.NEW=නව impl.ldap.EDIT=සැකසුම් (E) -impl.ldap.REMOVE=ඉවත්කරන්න impl.ldap.ENABLED=සක්‍රීය කරන්න impl.ldap.SERVER_HOSTNAME=සත්කාරක නම: impl.ldap.SAVE=සුරකින්න (&S) @@ -544,12 +509,14 @@ impl.ldap.SERVER_PORT=තොටුපළ impl.ldap.PASSWORD=රහස්පදය impl.ldap.MAIL_FIELD_EXAMPLE=විද්‍යුත් තැපැල් ලිපිනය: +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts -impl.googlecontacts.NEW=නව impl.googlecontacts.EDIT=සැකසුම් (E) -impl.googlecontacts.REMOVE=ඉවත්කරන්න impl.googlecontacts.ENABLED=සක්‍රීය කරන්න impl.googlecontacts.SAVE=සුරකින්න (&S) impl.googlecontacts.CANCEL=එපා (&C) @@ -569,9 +536,6 @@ plugin.accountinfo.BDAY=උපන් දිනය: plugin.accountinfo.GENDER=‍ස්ත්‍රී/පුරුෂ භාවය: plugin.accountinfo.EMAIL=විද්‍යුත් තැපෑල: plugin.accountinfo.PHONE=දුරකතනය: -plugin.accountinfo.USER_PICTURES=පරිශීලක රූප -plugin.accountinfo.CHANGE=වෙනස් කරන්න -plugin.accountinfo.ONLY_MESSAGE=පණිවිඩ පමණක් # connection info @@ -589,49 +553,12 @@ plugin.aimaccregwizz.USERNAME=AIM තිරනාමය: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=තිරනාමය සහ රහස්පදය plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=නව ගිණුමක් ලියාපදිංචි කරන්න plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=ඔබට AIM ගිණුමක් නොමැතිනම්, අලුතෙන් ආරම්භ කිරීමට මෙම බොත්තම ඔබන්න. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=server එකෙහි සම්මත සැකසුම් වෙනස් කරන්න # branding plugin.branding.ABOUT_WINDOW_TITLE={0} ගැන plugin.branding.LOGO_MESSAGE=විවෘත කේත VoIP සහ ක්ෂණික පණිවිඩ -plugin.branding.LOADING=ප්‍රවේශ වෙම්න් plugin.branding.ABOUT_MENU_ENTRY=පිළිබඳව (&A) -plugin.branding.WELCOME_MESSAGE=
    The {1},දැනට සක්‍රීය ගොඩනැගුම් අදියරේ ඇත. ඔබ පාවිච්චි කරන සංස්කරණය පරීක්ෂණ මට්ටමේ ඇති බැවින් බලාපොරොත්තුවන ආකාරයට ක්‍රියා නොකිරීමට පිළිවන. කරුණාකර වැඩිවිස්තර සඳහා {2} බලන්න.
    -plugin.branding.COPYRIGHT=
    (c)2003-2009 ප්‍රකාශන හිමිකම sip-communicator.org. සියලු හිමිකම් ඇවිරිණි. http://sip-communicator.org වෙත යන්න.
    -plugin.branding.LICENSE=
    SIP Communicator, LGPLහි අඩංගු වගන්ති යටතේ බෙදාහැරේ.(http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=ශබ්දකෝෂ -plugin.dictaccregwizz.ANY_DICTIONARY=ඕනෑම ශබ්දකෝෂයක් -plugin.dictaccregwizz.ANY_DICTIONARY_FORM={0} සිට ඕනෑම ශබ්දකෝෂයක් -plugin.dictaccregwizz.FIRST_MATCH=ප්‍රථම ගැළපුම -plugin.dictaccregwizz.NO_MATCH=ගැළපීම් නොමැත -plugin.dictaccregwizz.MATCH_RESULT="{0}" සඳහා අර්ථ දැක්වීම් කිසිවක් සොයාගත නොහැක. සමහරවිට ඔබ අදහස් කරන්නේ මෙය විය හැක:\n -plugin.dictaccregwizz.INVALID_DATABASE=මෙම "{0}" ශබ්දකෝෂය තවදුරටත් server එකෙහි නොපවතී. -plugin.dictaccregwizz.INVALID_STRATEGY=මෙම මූලෝපාය server එකෙහි අඩංගු නොවේ. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION='Dict' සේවා ප්‍රොටෝකෝලය -plugin.dictaccregwizz.HOST=ධාරකයා -plugin.dictaccregwizz.SERVER_INFO=server තොරතුරු -plugin.dictaccregwizz.STRATEGY_SELECTION=මූලෝපා තේරීම -plugin.dictaccregwizz.STRATEGY_LIST=මූලෝපායන් ලැයිස්තුව -plugin.dictaccregwizz.SEARCH_STRATEGIES=මූලෝපායන් සොයන්න -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=මූලෝපාය වන්නේ, පරිවර්තනයක් සොයා නොගතහොත් සමාන වචන සෙවීමයි. උදාහරණයක් ලෙස, උපසර්ග මූලෝපායයෙන් ඔබ පරිවර්තනය කිරීමට යන වචනයෙන් පටන්ගන්නා වචන සොයාදෙයි. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE='Dict' ගිණුම් තොරතුරු -plugin.dictaccregwizz.FIRST_ACCOUNT=මෙමගින්, dict.org හි ඔබේ ප්‍රථම Dict ගිණුම සෑදීමට සහායවනු ඇත.\n\nනව ගිණුමක් එකතු කිරීමට "ගිණුම් ලියාපදිංචිකිරීමේ සහකරු" වෙත ගොස් "සත්කාරකයා" තීරුවෙහි ඔබේ ශබ්දකෝෂය ඇතුලත් කරන්න. -plugin.dictaccregwizz.THREAD_CONNECT=server එකට සම්බන්ධවීමට උත්සාහ කරමින්... -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=සම්බන්ධවීමට නොහැකිවිය. මෙය dic server එකක් නොවේ, එසේ නොමැතිනම් server එක ක්‍රියාකාරීව නොපවතී -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=ලබාගන්නා මූලෝපායයන් -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=මෙම server එකෙහි මූලෝපායක් හමු නොවුණි -plugin.dictaccregwizz.POPULATE_LIST=ලැයිස්තුව සකසමින් -plugin.dictaccregwizz.CLOSING_CONNECTION=සම්බන්ධතාවය වසමින් - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    ෆේස්බුක් කතාබහ සඳහා ඔබ පරිශීලක නාමයක් සෑදිය යුතුවේ:
    ෆේස්බුක් හි "Account Settings" පිටුවෙන්.


    සටහන: පරිශීලක නාමය සෑදූ පසු වෙබ් අඩවියෙන් ඉවත්වන්න
    නව පරිශීලක නාමයෙන් ඇතුලුවීම සඳහා ටික වේලාවක් ගතවිය හැකිය!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=ෆේස්බුක් කතාබහ ප්‍රොටෝකෝලය -plugin.facebookaccregwizz.PROTOCOL_NAME=ෆේස්බුක් (facebook) -plugin.facebookaccregwizz.USERNAME=පරිශීලක නාමය: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=පරිශීලක නාමය සහ රහස්පදය + # generalconfig plugin.generalconfig.AUTO_START=පරිගණකය නැවත ක්‍රියාත්මක කරනවිට {0} ස්වයංක්‍රීයව ආරම්භ කරන්න @@ -641,9 +568,6 @@ plugin.generalconfig.SHOW_HISTORY=පෙන්වන්න plugin.generalconfig.HISTORY_SIZE=නව කතාබහකදී මෑතකදී හුවමාරුවූ පණිවිඩ plugin.generalconfig.SEND_MESSAGES_WITH=මෙමගින් යවන්න: plugin.generalconfig.BRING_WINDOW_TO_FRONT=කතාබහ කවුලුව ඉදිරියට ගෙනෙන්න -plugin.generalconfig.ERROR_PERMISSION=ස්වංක්‍රීය ආරම්භකිරීම ඉවත්කිරීම සඳහා ඔබට ප්‍රමාණවත් අයිතීන් නොමැත -plugin.generalconfig.TRANSPARENCY=පාරදෘශ්‍යතාවය -plugin.generalconfig.ENABLE_TRANSPARENCY=පාරදෘශ්‍යතාවය සක්‍රීය කරන්න plugin.generalconfig.DEFAULT_LANGUAGE=අතුරුමුහුණත් භාෂාව plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=ඔබ සිදුකල වෙනස්කම් ඊළඟ ප්‍රතිපිහිටුමේදී ක්‍රියාවට නැංවෙනු ඇත plugin.generalconfig.SIP_CLIENT_PORT=SIP සේවාග්‍රාහක දොරටුව @@ -681,7 +605,6 @@ plugin.ircaccregwizz.IRC_SERVER=Server # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=SIP ප්‍රොටෝකෝලය plugin.jabberaccregwizz.PASSWORD_CONFIRM=රහස්පදය තහවුරු කරන්න -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=අනන්‍යතාව සහ රහස්පදය plugin.jabberaccregwizz.CSERVER=Server plugin.jabberaccregwizz.SERVER=Server එකට සම්බන්ධවන්න plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=ක්‍රියාත්මකව තබාගැනීම සක්‍රීය කරන්න @@ -695,10 +618,7 @@ plugin.jabberaccregwizz.SERVER_COLUMN=Server plugin.jabberaccregwizz.COMMENT_COLUMN=සටහන plugin.jabberaccregwizz.RESOURCE=සම්පත plugin.jabberaccregwizz.PRIORITY=ප්‍රමුඛතාව -plugin.jabberaccregwizz.XMPP_ERROR=XMPP දෝශයක් plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=හඳුනානොගත් XMPP දෝශයක්. server නාමය නිවැරදිදැයි පරීක්ෂා කරන්න. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=server එකෙහි සම්මත සැකසුම් අභිබවා යන්න -plugin.jabberaccregwizz.ADVANCED_OPTIONS=වැඩිදුර සැකසුම් plugin.jabberaccregwizz.USE_ICE=ICE පාවිච්චි කරන්න plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=STUN/TURN servers ස්වයංක්‍රීයව හඳුනාගන්න plugin.jabberaccregwizz.SUPPORT_TURN=TURN සහාය @@ -711,31 +631,14 @@ plugin.jabberaccregwizz.NO_STUN_USERNAME=ඉදිරියට යෑම සඳ plugin.jabberaccregwizz.STUN_ALREADY_EXIST=ඔබ සඳහන් කළ STUN server එක දැනටමත් පවතී. plugin.jabberaccregwizz.JID_ADDRESS=IP ලිපිනය plugin.jabberaccregwizz.EXISTING_ACCOUNT=දැනටමත් පවතින SIP ගිණුමක් -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=රහස්පදය තහවුරු කරන්න plugin.jabberaccregwizz.ENCODINGS=කේතකයන් (&E): plugin.jabberaccregwizz.AUDIO=ශ්‍රව්‍ය plugin.jabberaccregwizz.VIDEO=දෘශ්‍ය plugin.jabberaccregwizz.RESET=නැවත පිහිටුවන්න -# mailbox -plugin.mailbox.OUTGOING=යැවෙන පණිවිඩය: -plugin.mailbox.INCOMING=ලැබෙන පණිවිඩ: -plugin.mailbox.WAIT_TIME=ඇමතුම voicemail වෙත යැවීමට රැඳී සිටිය යුතු කාලය -plugin.mailbox.MAX_MESSAGE_TIME=උපරිම පණිවිඩ කාලය -plugin.mailbox.CONFIRM=තහවුරු කරන්න -plugin.mailbox.DEFAULTS=සම්මත සැකසුම් -plugin.mailbox.MAILBOX=තැපැල් පෙට්ටිය - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=එම්.එස්.එන්. (MSN) -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=MSN සේවා සඳහා සම්බන්ධවීමට සහ එමගින් කතාබහ කිරීමට අදාල ප්‍රොටෝකෝලය. -plugin.msnaccregwizz.USERNAME=විද්‍යුත් තැපැල් ලිපිනය: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=පරිශීලක නාමය සහ රහස්පදය - # plugin manager plugin.pluginmanager.INSTALL=ස්ථාපනය කරන්න plugin.pluginmanager.UNINSTALL=අස්ථාපනය කරන්න -plugin.pluginmanager.UPDATE=යාවත්කාලීන plugin.pluginmanager.PLUGINS=ප්ලග්-ඉන් plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=ගොනුව තෝරන්න @@ -759,7 +662,6 @@ plugin.sipaccregwizz.SERVER_PORT=Server දොරටුව plugin.sipaccregwizz.PROXY=ප්‍රොක්සි plugin.sipaccregwizz.PROXY_PORT=ප්‍රොක්සි දොරටුව plugin.sipaccregwizz.PREFERRED_TRANSPORT=ප්‍රවාහන ආකාරය -plugin.sipaccregwizz.ADVANCED_OPTIONS=වැඩිදුර සැකසුම් plugin.sipaccregwizz.PROXY_OPTIONS=ප්‍රොක්සි සැකසුම් plugin.sipaccregwizz.PROXY_AUTO=ප්‍රොක්සි ස්වයංක්‍රීයව සකසන්න plugin.sipaccregwizz.ENABLE_PRESENCE=පැවැත්ම සක්‍රීය කරන්න (සරල) @@ -771,8 +673,6 @@ plugin.sipaccregwizz.KEEP_ALIVE=සජීවීව තබාගැනීම plugin.sipaccregwizz.KEEP_ALIVE_METHOD=සජීවීව තබාගැනීමේ ක්‍රමය plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=සජීවී පරාසය plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=තත්පර 1 සහ 3600 අතර -plugin.sipaccregwizz.REGISTER=ලියාපදිංචිය -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=server එකෙහි සම්මත සැකසුම් අබිභවා යන්න plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=ඇමතුම් කේතනය කිරීමේ සහාය plugin.sipaccregwizz.AUTH_NAME=බලයලත් නාමය plugin.sipaccregwizz.DISPLAY_NAME=පෙන්වන නම @@ -783,6 +683,7 @@ plugin.sipaccregwizz.CLIST_TYPE=ගිණුම් වර්ගය plugin.sipaccregwizz.XCAP_USE_SIP_CREDENTIALS=SIP ගිණුම් දත්ත යොදාගන්න plugin.sipaccregwizz.XCAP_USER=පරිශීලක plugin.sipaccregwizz.XCAP_PASSWORD=රහස්පදය +#used from SecurityPanel # skin manager plugin.skinmanager.SKINS=තේමාව @@ -790,15 +691,6 @@ plugin.skinmanager.DEFAULT_SKIN=සම්මත තේමාව plugin.skinmanager.ADD_NEW_SKIN=නව තේමාවක් එකතු කරන්න... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=යෙදුමේ සම්මත තේමාව. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=SSH හරහා දුරස්ථ පරිගණය සම්බන්ධ කිරීම සඳහාවූ ප්‍රොටෝකෝලයකි. -plugin.sshaccregwizz.USERNAME=ගිණුම් අනන්‍යතාව: -plugin.sshaccregwizz.IDENTITY_FILE=අනන්‍යතා ගොනුව: -plugin.sshaccregwizz.KNOWN_HOSTS=දන්නා සත්කාරකයන්: -plugin.sshaccregwizz.OPTIONAL=අතිරේක -plugin.sshaccregwizz.ACCOUNT_DETAILS=ගිණුම් විස්තර - # status update plugin.autoaway.AUTO_STATUS=ස්වයංක්‍රීය බැහැරවීම plugin.autoaway.ENABLE_CHANGE_STATUS=බැහැරව සිටිනවිට තත්වය වෙනස්කරන්න @@ -843,21 +735,6 @@ plugin.whiteboard.DESELECT=නොතෝරන්න plugin.whiteboard.DELETE=මකන්න plugin.whiteboard.PROPERTIES=තොරතුරු -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=යාහූ සේවාවන් අතර සම්බන්ධ වීමට සහ කතාබහ කිරීමට අදාළ ප්‍රොටෝකෝලය. -plugin.yahooaccregwizz.USERNAME=පරිශීලක නාමය: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=අනන්‍යතාව සහ රහස්පදය - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=සීරෝ-කන්ෆ් (Zeroconf) -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=සීරෝ-කන්ෆ් (Zeroconf-Bonjour) සේවා ප්‍රොටෝකෝලය. -plugin.zeroaccregwizz.FIRST_NAME=මුල් නම: -plugin.zeroaccregwizz.LAST_NAME=අවසාන නම: -plugin.zeroaccregwizz.EMAIL=විද්‍යුත් තැපෑල: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Bonjour සබඳතා මතක තබා ගන්න -plugin.zeroaccregwizz.USERID_AND_PASSWORD=අනන්‍යතාව සහ රහස්පදය -plugin.zeroaccregwizz.USERID=පරිශීලක නාමය - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=ගූගල් කතා ප්‍රොටෝකෝලය plugin.googletalkaccregwizz.USERNAME=පරිශීලක නාමය @@ -870,25 +747,18 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org සන්නිවේද plugin.iptelaccregwizz.USERNAME=පරිශීලක නාමය plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=iptel.org හි ලියාපදිංචි වන්න -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=සිප්2සිප් (sip2sip.info) -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=අන්තර්ජාල ඇමතුම් සහ කතාබහ +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=පරිශීලක නාමය plugin.sip2sipaccregwizz.RETYPE_PASSWORD=රහස්පදය නැවත ඇතුලත් කරන්න plugin.sip2sipaccregwizz.EMAIL=විද්‍යුත් තැපෑල -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=සේවා සහාය සඳහා
    http://wiki.sip2sip.info වෙත යන්න plugin.sip2sipaccregwizz.EMAIL_NOTE=මගහැරුණු ඇමතුම්, පටිගතකළ පණිවිඩ යැවීමට සහ අස්ථාන ගතවූ රහස්පදය
    ආපසු ලබාගැනීමට විද්‍යුත් තැපැල් ලිපිනය යොදාගැනේ -plugin.sip2sipaccregwizz.INFO_NOTE=සේවා සහාය සඳහා http://wiki.sip2sip.info වෙත යන්න -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=දැනට පවතින සිප්2සිප් ගිණුමක් -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=නව සිප්2සිප් ගිණුමක් සාදන්න - -# ippi accregwizz plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=සේවා සහාය සඳහා
    http://wiki.sip2sip.info වෙත යන්න plugin.ippiaccregwizz.INFO_NOTE=සේවා සහාය සඳහා http://wiki.sip2sip.info වෙත යන්න plugin.ippiaccregwizz.EXISTING_ACCOUNT=දැනටමත් පවතින SIP ගිණුමක් plugin.ippiaccregwizz.CREATE_ACCOUNT=SIP ගිණුමක් සාදන්න # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=කතාබහ කවුලුව වැසීම plugin.keybindings.CHAT_COPY=පිටපත් කිරීම plugin.keybindings.CHAT_CUT=කැපීම @@ -904,6 +774,7 @@ plugin.keybindings.OPEN_HISTORY=අතීතය විවෘත කිරීම plugin.keybindings.OPEN_SMILIES=සිනා-මුහුණු plugin.keybindings.globalchooser.SHORTCUT_NAME=නම plugin.keybindings.PLUGIN_NAME=යතුරුපුවරු කෙටි මං +#Enum KeybindingSet.Category plugin.keybindings.CHAT=කතාබහ # Notification Configuration Form @@ -918,6 +789,7 @@ plugin.notificationconfig.EXEC_PROG=වැඩසටහන ක්‍රියා plugin.notificationconfig.DISPLAY_POPUP=මතුවන කවුලුවක පණිවිඩය පෙන්වන්න plugin.notificationconfig.POPUP_NOTIF_HANDLER=නිවේදන වර්ගය: plugin.notificationconfig.tableheader.EXECUTE=වැඩසටහන ක්‍රියාත්මක කරන්න: +#NotificationsTable constants plugin.notificationconfig.event.IncomingMessage=ලැබෙන පණිවිඩ: plugin.notificationconfig.event.HangUp=විසන්ධි කරන්න @@ -968,6 +840,7 @@ impl.media.configform.VIDEO_RESET=සම්මත සැකසුම් ප් impl.neomedia.configform.AUDIO=ශ්‍රව්‍ය impl.neomedia.configform.VIDEO=දෘශ්‍ය +#in JNIEncoder impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=ZRTP # The callrecordingconfig plugin was never really committed into trunk and its @@ -991,7 +864,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=පවත්නා රහ plugin.securityconfig.masterpassword.ENTER_PASSWORD=නව රහස්පදය : plugin.securityconfig.masterpassword.REENTER_PASSWORD=නැවත ඇතුලත් කරන්න: plugin.securityconfig.masterpassword.MP_TITLE=ප්‍රධාන රහස්පදය -plugin.securityconfig.masterpassword.MP_NOT_SET=(සකසා නොමැත) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=පවතින රහස්පදය ඔබ ඇතුලත් කර නොමැත. නැවත උත්සාහ කරන්න. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=ප්‍රධාන රහස්පදය වැරදියි! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=රහස්පදය වෙනස්කිරීම අසාර්ථක විය @@ -1006,7 +878,6 @@ plugin.securityconfig.masterpassword.COL_NAME=නම plugin.securityconfig.masterpassword.COL_PASSWORD=රහස්පදය plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(නොදනී) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(විකේතනය කළ නොහැක) -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=ඉවත්කරන්න plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=සියල්ල ඉවත්කරන්න plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=සියලු රහස්පද ඉවත්කිරීමට අවශ්‍යබව තහවුරු කරන්න plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=සියලු රහස්පද ඉවත්කිරීම @@ -1065,7 +936,6 @@ plugin.globalproxy.PROXY_PORT=ප්‍රොක්සි දොරටුව plugin.globalproxy.PROXY_USERNAME=ප්‍රොක්සි පරිශීලක නාමය plugin.globalproxy.PROXY_PASSWORD=ප්‍රොක්සි රහස්පදය plugin.globalproxy.DESCRIPTION=මෙතැන් පටන් ඔබ ඕනෑම ජාලයකට සම්බන්ධවීමේදී මෙම ප්‍රොක්සි සැකසුම් භාවිතා කෙ‍රෙනු ඇත. \nප්‍රොක්සි සහාය දැනට පරීක්ෂණ මට්ටමේ පවතින අතර එය ක්‍රියාත්මක වන්නේ සමහර ප්‍රොටෝකෝල සමග පමණි. වැඩි විස්තර සඳහා පහත වගුව බලන්න. -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    යාහූ!++--
    එම්.එස්.එන්.++--
    ජැබ'++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1100,7 +970,6 @@ plugin.dnsconfig.lblBackupPort.text=තොටුපළ net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=නොසලකා හරින්න (&I) #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=සැකසුම් (E) plugin.spellcheck.UNINSTALL_DICTIONARY=අස්ථාපනය කරන්න -- cgit v1.1 From 85426c94002cac40d8e85524d7b438fe6f60eefd Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:03 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1416 of 1505 strings translated (13 fuzzy). --- resources/languages/resources_gd.properties | 213 ++++------------------------ 1 file changed, 29 insertions(+), 184 deletions(-) diff --git a/resources/languages/resources_gd.properties b/resources/languages/resources_gd.properties index a578b7b..3e8aa90 100644 --- a/resources/languages/resources_gd.properties +++ b/resources/languages/resources_gd.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Mise service.gui.ACCOUNT_REGISTRATION_WIZARD=Draoidh clàradh nan cunntasan service.gui.ACCOUNTS=Cunntasan service.gui.ADD=&Cuir ris -service.gui.ADD_ACCOUNT=Cuir cunntas ris service.gui.ADD_CONTACT=C&uir neach-aithne ris service.gui.ADD_AUTHORIZED_CONTACT=Cuir {0} ri liosta an luchd-aithne agad service.gui.ADD_CONTACT_TO=Cuir an &neach-aithne ri @@ -41,20 +51,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Mearachd a' cur ris neach-aithne service.gui.ADD_CONTACT_EXIST_ERROR=Tha an neach-aithne {0} air liosta an luchd-aithne agad mu thràth. service.gui.ADD_CONTACT_NETWORK_ERROR=Cha do fhreagair am frithealaiche nuair a dh''iarr sinn an neach-aithne aig a bheil an ID {0} a chur ris. service.gui.ADD_CONTACT_NOT_SUPPORTED=Cha b'' urrainn dhuinn an neach-aithne aig a bheil an ID {0} a chur ris. Chan eil taic ris a leithid seo a ghnìomh. -service.gui.ADD_CONTACT_IDENTIFIER=Cuir aithnichear an neach-aithne a tha thu airson cur ris san raon gu h-ìosal. -service.gui.ADD_CONTACT_WIZARD=Draoidh cur ris an luchd-aithne service.gui.ADD_CONTACT_NOT_CONNECTED=Feumaidh ceangal a bhith agad mus urrainn dhut neach-aithne a chur ris. Clàraich a-steach aig an t-solaraiche a thagh thu ''s feuch ris a-rithist. service.gui.ADD_GROUP_LOCAL_ERROR=Cha b'' urrainn dhuinn am buidheann air a bheil {0} a chur ris. Dh''èirich an duilgheadas seo ri linn gnìomh IO ionadail. service.gui.ADD_GROUP_EXIST_ERROR=Tha am buidheann {0} air liosta an luchd-aithne agad mu thràth. Nach tagh thu ainm eile? service.gui.ADD_GROUP_NET_ERROR=Cha b'' urrainn dhuinn am buidheann air a bheil {0} a chur ris. Dh''èirich an duilgheadas seo ri linn fàilligeadh an lìonraidh. Dèan cinnteach gu bheil ceangal agad ris an lìonra ''s feuch ris a-rithist. service.gui.ADD_GROUP_ERROR=Cha b'' urrainn dhuinn am buidheann air a bheil {0} a chur ris. service.gui.ADD_GROUP_EMPTY_NAME=Chan fhaod ainm a'' bhuidhinn a bhith falamh. -service.gui.ADD_GROUP=Cruthaich buidheann -service.gui.ADD_SUBCONTACT=C&uir fo-neach-aithne ris service.gui.ADDRESS=Seòladh service.gui.ADMINISTRATOR=rianaire service.gui.ADVANCED=&Adhartach -service.gui.ALL=A &h-uile service.gui.ALL_CONTACTS=&A h-uile neach-aithne service.gui.APPLY=&Cuir an sàs service.gui.ARE_CALLING=Tha {0} a'' cur fòn... @@ -63,7 +68,6 @@ service.gui.AT=aig service.gui.AUTHORIZE=&Thoir ùghdarras service.gui.AUTHORIZATION_ACCEPTED=Ghabh {0} ris d'' iarrtas ùghdarrachaidh. service.gui.AUTHENTICATION_FAILED=Dh''fhàillig dearbhadh {0}. Chuir thu a-steach facal-faire nach eil dligheach. -service.gui.AUTHENTICATION_REQUESTED=Dearbhadh ''ga iarraidh service.gui.AUTHENTICATION_REQUESTED_SERVER=Dh''iarr frithealaiche {0} dearbhadh ort. service.gui.AUTHENTICATION_REJECTED=Dhiùlt {0} d'' iarrtas ùghdarrachaidh. service.gui.AUTHENTICATION_WINDOW_TITLE=Dearbhadh {0} @@ -103,7 +107,6 @@ service.gui.CHANGE_NICKNAME_LABEL=''S urrainn dhut am far-ainm ùr agad a chur a service.gui.CHANGE_NICKNAME_ERROR=Mearachd le atharrachadh an fhar-ainm service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Tha am far-ainm seo ann mu thràth service.gui.CHANGE_VIDEO_QUALITY=Atharraich càileachd a'' video chèin -service.gui.CHAT_CONFERENCE_LABEL=Co-labhairtean service.gui.CHAT_CONFERENCE_ITEM_LABEL=A'' cho-labhairt aig {0} service.gui.CHAT_ROOM_ALREADY_JOINED=Chaidh an seòmar cabadaich {0} a cheangal ris mu thràth. service.gui.CHAT_ROOM_CONFIGURATION=Rèiteachadh an t-seòmair chabadaich {0} @@ -114,18 +117,14 @@ service.gui.CHAT_ROOM_USER_JOINED=- chaidh iad a-steach dha {0} service.gui.CHAT_ROOM_USER_LEFT=- dh''fhàg iad {0} service.gui.CHAT_ROOM_USER_KICKED=- air breab fhaighinn às an t-seòmar {0} service.gui.CHAT_ROOM_USER_QUIT=- dh''fhàg iad {0} -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Sàbhailidh seo an seòmar cabadaich air eagal ''s gum bi feum agad uaireigin eile -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Bheir seo air falbh an seòmar a thagh thu o liosta nan seòmraichean a chaidh a shàbhaladh service.gui.CHAT_ROOM_NAME=Ainm an t-seòmair chabadaich service.gui.CLEAR_CUSTOM_MESSAGES=Falamhaich na teachdaireachdan gnàthaichte service.gui.ROOM_NAME=Seòmar cabadaich -service.gui.AUTOJOIN=Gabh pàirt gu fèin-obrachail service.gui.CHANGE_PASSWORD=Atharraich am facal-faire service.gui.CHAT_ROOM_NAME_INFO=Cuir ainm an t-seòmair chabadaich a tha thu airson cruthachadh san raon gu h-ìosal. service.gui.CHAT_ROOM_NOT_EXIST=Cha b'' urrainn dhuinn an seòmar {0} a lorg air an fhrithealaiche {1}. Dèan cinnteach gu bheil an t-ainm a chuir thu a-steach ceart. service.gui.CHAT_ROOM_NOT_CONNECTED=Feumaidh tu clàradh a-steach mus urrainn dhut a dhol a-steach dhan t-seòmar chabadaich {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Feumaidh tu clàradh a-steach mus urrainn dhut seòmar cabadaich fhàgail. -service.gui.CHAT_ROOM_NOT_JOINED=Feumaidh tu a bhith ceangailte ris an t-seòmar chabadaich mus urrainn dhut rudan a dhèanamh ann. service.gui.CHAT_ROOM_OPTIONS=Roghainnean an t-seòmair chabadaich service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Feumaidh tu clàradh mus urrainn dhut ceangal ris an t-seòmar chabadaich {0}. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Dh''iarr an seòmar cabadaich {0} facal-faire. @@ -142,22 +141,18 @@ service.gui.CLEAR=Falamhaich service.gui.CLOSE=Dùi&n service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Fhuair thu teachdaireachd ùr diog no dhà air ais. A bheil thu cinnteach gu bheil thu airson a'' chabadaich seo a dhùnadh? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Tha faidhlichean ''gan tar-aiseag agad fhathast. A bheil thu cinnteach gu bheil thu airson sgur dheth? -service.gui.CONFIRM=Dearbhaich service.gui.CONNECTED_STATUS=Ceangailte ris service.gui.CONNECTING=A'' dèanamh ceangal... service.gui.CONNECTING_STATUS=A'' dèanamh ceangal service.gui.CONNECTING_EARLY_MEDIA_STATUS=A'' dèanamh ceangal* service.gui.CONNECTION=Ceangal -service.gui.CONNECTION_FAILED_MSG=Dh''fhàillig an ceangal aig a'' chunntas a leanas: Ainm-cleachdaiche: {0}, ainm an fhrithealaiche: {1}. Dèan cinnteach gu bheil ceangal agad ris an lìonra no cuir fios gu rianaire an lìonraidh agad airson barrachd fiosrachaidh. service.gui.CONNECTION_EXPIRED_MSG=Chan eil ceangal agad ris an fhrithealaiche {0} aig an àm seo. service.gui.CONTACT_NAME=ID no àireamh -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Chan eil an neach-aithne a thagh thu, {0}, comasach air fònadh. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Chan eil an neach-aithne a thagh thu, {0}, comasach air co-labhairtean cabadaich. service.gui.CONTACT_PAUSED_TYPING=Sguir {0} de sgrìobhadh na teachdaireachd service.gui.CONTACT_TYPING=Tha {0} a'' sgrìobhadh teachdaireachd service.gui.CONTACT_TYPING_SEND_FAILED=ìoc... cha b'' urrainn dhuinn innse dha {0} gun robh thu a'' sgrìobhadh rud service.gui.CONTACT_INFO=&Fiosrachadh conaltraidh -service.gui.CONTACTLIST=Liosta an luchd-aithne service.gui.CONTACTS=Luchd-aithne service.gui.COPY=Dèan lethbhrea&c service.gui.COPY_LINK=Dèan &lethbhreac dhen cheangal @@ -167,17 +162,14 @@ service.gui.CREATE_CHAT_ROOM=&Cruthaich seòmar cabadaich... service.gui.CREATE_CHAT_ROOM_ERROR=Dh''fhàillig cruthachadh an t-seòmair chabadaich {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Draoidh cruthachadh nan seòmraichean cabadaich service.gui.CREATE_CONFERENCE_CALL=&Cruthaich gairm co-labhairt... -service.gui.CREATE_CONFERENCE_CHAT=&Cruthaich cabadaich co-labhairt... service.gui.CREATE_GROUP=&Cruthaich buidheann... service.gui.CREATE_GROUP_NAME=Cuir ainm a'' bhuidhinn a tha thu airson cruthachadh san raon gu h-ìosal. -service.gui.CREATE_FIRST_GROUP_WIZARD=Chan eil buidheann sam bith air liosta an luchd-aithne agad. Nach cruthaich thu buidheann an toiseach (Faidhle » Cruthaich buidheann). service.gui.CREATE_VIDEO_BRIDGE=Cruthaich drochaid &video... service.gui.CREATE_VIDEO_BRIDGE_MENU=Cruthaich drochaid &video service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Cruthaich / Gabh pàirt ann an co-labhairt video service.gui.CREATE_VIDEO_CONFERENCE=Cruthaich co-labhairt video ùr dhan t-seòmar chabadaich seo service.gui.CONTACT_INFO_NOT_SUPPORTED=Chan eil an neach-aithne seo comasach air fiosrachadh conaltraidh-lìn a làimhseachadh service.gui.CUT=&Gearr às -service.gui.DATE=Ceann-là service.gui.DELETE=Sguab às service.gui.DENY=&Diùlt service.gui.DESKTOP_SHARING_WARNING=A bheil thu cinnteach gu bheil thu airson tòiseachadh air co-roinneadh na sgrìn agad?
    Ma bhriogas tu air "Ceart ma-thà", chì càch sa chòmhradh seo an sgrìn agad. @@ -187,7 +179,6 @@ service.gui.DISCONNECTED_STATUS=Air a dhì-cheangal service.gui.DND_STATUS=Na bris a-steach orm service.gui.DO_NOT_ASK_AGAIN=Na faighnich dhìom a-rithist service.gui.DO_NOT_SHOW_AGAIN=Na seall an teachdaireachd seo a-rithist -service.gui.DOWNLOAD_NOW=L&uchdaich a-nuas an-dràsta service.gui.DRAG_FOR_SHARING=Slaod dad an-seo a bu toigh leat co-roinneadh... service.gui.DURATION=faid service.gui.EDIT=D&easaich @@ -206,7 +197,6 @@ service.gui.ERROR_RECEIVED_FROM=Fhuaras mearachd o {0} service.gui.ESTIMATED_TIME=Tuairmeas ama: service.gui.EVENTS=Tachartasan service.gui.EXIT=&Fàg an-seo -service.gui.EXTENDED_CRITERIA=Cuspair-deuchainnean adhartach service.gui.GENERAL=Coitcheann service.gui.GENERAL_ERROR=Mearachd choitcheann service.gui.GROUP_NAME=Ainm a'' bhuidhinn @@ -248,7 +238,6 @@ service.gui.FONT_ITALIC=Eadailteach service.gui.FONT_SIZE=Meud service.gui.FONT_STYLE=Stoidhle service.gui.FONT_UNDERLINE=Loidhne fodha -service.gui.FROM={0} o {1} service.gui.GRANT_OWNERSHIP=Thoir seachad seilbheachd... service.gui.GRANT_ADMIN=Thoir seachad inbhe rianaire... service.gui.GRANT_MODERATOR=Thoir seachad inbhe modaratair @@ -274,7 +263,6 @@ service.gui.HISTORY_REMOVE_ALL_WARNING=A bheil thu cinnteach gu bheil thu airson service.gui.HISTORY_REMOVE_ERROR=Mearachd a'' toirt air falbh nan teachdaireachdan a tha ''gan stòradh gu h-ionadail. service.gui.HOME=Dhachaigh service.gui.HOME_PAGE=Duilleag-dhachaigh -service.gui.HOUR=Uair a thìde service.gui.ICE=ICE service.gui.IDENTIFIER=Aithnichear service.gui.IGNORE=&Leig seachad @@ -295,13 +283,10 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Thoir cuireadh dhan luchd-aithne gu d service.gui.INVITE_REASON=Adhbhar a'' chuiridh service.gui.IS_CALLING=Tha {0} a'' cur fòn... service.gui.IS_NOW=Tha {0} {1} an-dràsta -service.gui.JITSI_WARNING=''S e Jitsi an t-ainm ùr air SIP Communicator.
    Ma tha thu airson ''s gum fan am prògram cho ùr ''s a ghabhas, nach luchdaich thu a-nuas Jitsi an-dràsta?

    Tha sinn duilich ma chuir sin fo mhì-ghoireas sam bith thu.

    Sgioba leasachadh Jitsi -service.gui.JITSI_WARNING_TITLE=''S e Jitsi an t-ainm ùr air an SIP Communicator service.gui.JOIN=&Rach ann service.gui.JOIN_AS=Rach &ann mar service.gui.JOIN_EXISTING_VIDEO_CONFERENCE=Gabh pàirt ann an co-labhairt video a tha ann mu thràth service.gui.JOIN_VIDEO=Gabh pàirt sa video -service.gui.CLOSE_CHAT_ROOM_DIALOG=Dùi&n service.gui.JOB_TITLE=Ainm an dreuchd service.gui.JOIN_CHAT_ROOM=Rach &dhan t-seòmar chabadaich... service.gui.JOIN_CHAT_ROOM_TITLE=Rach dhan t-seòmar chabadaich @@ -314,7 +299,6 @@ service.gui.KICK_FAILED=Dh''fhàillig a b(h)reabadh service.gui.KICK_FAILED_GENERAL_ERROR=Dh''fhàillig breabadh {0}. Thachair mearachd air an fhrithealaiche. service.gui.KICK_FAILED_NOT_ALLOWED=Dh''fhàillig breabadh {0}. Cha b'' urrainn dhuinn sealbhadair is rianaire an t-seòmair a bhreabadh. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Dh''fhàillig breabadh {0}. Chan eil cead gu leòr agad sin a dhèanamh. -service.gui.LAST=Sloinneadh service.gui.LAST_NAME=Sloinneadh service.gui.LEAVE=&Fàg service.gui.LIMIT_REACHED_FOR_IP=Rinn cus dhaoine clàradh on t-seòladh IP ionadail agad agus chan eil am frithealaiche {0} a'' dol a cheadachadh barrachd dhiubh. @@ -334,7 +318,6 @@ service.gui.MESSAGE=Teachdaireachd service.gui.MISSED_CALLS_TOOL_TIP=Chaill thu gairmean o: service.gui.MISSED_CALLS_MORE_TOOL_TIP= agus {0} a bharrachd service.gui.MODERATOR=modaratair -service.gui.MORE=Fac an corr service.gui.MORE_LABEL=Barrachd service.gui.MOVE=Gluais service.gui.MOVE_SUBCONTACT=G&luais an neach-aithne @@ -343,7 +326,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Tha an neach-aithne a thagh thu co-ionnann ri service.gui.MOVE_SUBCONTACT_QUESTION=A bheil thu cinnteach gu bheil thu airson {1} a ghluasad dha {0}? service.gui.MOVE_TO_GROUP=&Gluais dhan bhuidheann service.gui.MOVE_CONTACT=Gluais an neach-aithne -service.gui.MOVE_CONTACT_ERROR=&Cha ghabh an neach-aithne a ghluasad service.gui.MSG_DELIVERY_FAILURE=Cha b'' urrainn dhuinn an teachdaireachd gu h-àrd a libhrigeadh service.gui.MSG_DELIVERY_NOT_SUPPORTED=Chan eil am pròtacal a thagh thu a'' cur taic ri teachdaireachdan far loidhne. ''S urrainn dhut feuchainn ri {0} a ruigsinn slighe pròtacail eile no fuireach gus am bi e/i air loidhne. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Thachair mearachd inntearnail. Tha coltas gur e buga a dh''adhbharaich seo, nach dèan thu aithris air an-seo: https://jitsi.org/Development/BugsAndIssues. @@ -356,7 +338,6 @@ service.gui.MSG_SEND_CONNECTION_PROBLEM=Bu chòir dhut ceangal a dhèanamh ma th service.gui.MULTIPLE_LOGINS=Rinn thu clàradh a-steach barrachd air aon turas leis an aon chunntas. Tha an cunntas (ainm-cleachdaiche: {0}, ainm an fhrithealaiche: {1}) gun cheangal an-dràsta fhèin. service.gui.MY_CHAT_ROOMS=Cuir seòmar cabadaich ris service.gui.MY_CHAT_ROOMS_TITLE=Cuir seòmar cabadaich ris -service.gui.MUTE=Mùch service.gui.MUTUALLY_ON_HOLD_STATUS=An dà chuid ''ga chumail service.gui.NAME=Ainm service.gui.NETWORK=Lìonra @@ -387,7 +368,6 @@ service.gui.NOT_IN_CONTACT_LIST_GROUP_NAME=Chan-eil-e-air-liosta-an-luchd-aithne service.gui.SD_QUALITY=Càileachd stannardach service.gui.OFFLINE=Far loidhne service.gui.OK=&Ceart ma-thà -service.gui.OLDER_CALLS=Gairmean nas sine service.gui.ONLINE=Air loidhne service.gui.OPEN=Fosgail service.gui.OPEN_FILE_FROM_IMAGE=Dèan briogadh dùbailte gus am faidhle fhosgladh. @@ -399,7 +379,6 @@ service.gui.OPEN_ON_ACTIVITY=ma bhios gnìomhachd ann service.gui.OPEN_ON_MESSAGE=ma bhios teachdaireachd ann a-mhàin service.gui.OPEN_ON_IMPORTANT_MESSAGE=ma bhios teachdaireachd chudromach ann a-mhàin service.gui.OR=no -service.gui.OR_ENTER_PHONE_NUMBER=No cuir a-steach àireamh fòn an-seo... service.gui.ORGANIZATION=Buidheann service.gui.OTHER=Eile service.gui.OWNER=seilbheadair an t-seòmair @@ -418,7 +397,6 @@ service.gui.PRESS_ENTER_FOR_SUGGESTIONS="Enter" airson molaidhean service.gui.PRESS_FOR_CALL_INFO=Dèan brùthadh airson fiosrachadh mun ghairm service.gui.PRESS_TO_OPEN_CRM=Brùth gus an aplacaid CRM fhosgladh service.gui.PREVIOUS=Air ais -service.gui.PREVIOUS_TOOLTIP=Brabhsaich còmhraidhean nas sine service.gui.PRINT=Clò-&bhuail service.gui.PROACTIVE_NOTIFICATION=- a'' sgrìobhadh teachdaireachd service.gui.PROBLEMS_ENCOUNTERED=Thachair sinn ri duilgheadas @@ -433,7 +411,6 @@ service.gui.RECONNECTION_LIMIT_EXCEEDED=Rinn thu ''s bhris thu an ceangal ris an service.gui.RE_REQUEST_AUTHORIZATION=Iarr ùghdarachadh a-rithist service.gui.REFERRED_STATUS=Air ath-threòrachadh service.gui.REJECT=&Diùlt -service.gui.REMIND_ME_LATER=Cuir ''nam chuimhne às a dhèidh seo service.gui.REMEMBER_PASSWORD=Cuimhnich am facal-faire service.gui.REMOVE=&Thoir air falbh service.gui.REMOVE_ACCOUNT=Thoi&r air falbh an cunntas @@ -459,29 +436,20 @@ service.gui.REVOKE_ADMIN=Thoir air falbh inbhe rianaire service.gui.REVOKE_MODERATOR=Thoir air falbh inbhe modaratair service.gui.REVOKE_MEMBERSHIP=Thoir air falbh a'' bhallrachd service.gui.REVOKE_VOICE=Thoir air falbh an guth -service.gui.ROOT_GROUP=Buidheann root service.gui.SAVE=&Sàbhail -service.gui.SAVE_AS_DEFAULT=Sàbhail mar roghainn bhunaiteach service.gui.SEARCH=&Lorg service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Briog air a'' phutan gu h-ìosal airson liosta shlàn nan seòmraichean cabadaich a tha air an fhrithealaiche a thagh thu. Tagh am fear a tha thu ag iarraidh a dhol ann is briog air a'' phutan "Rach ann" an uairsin. service.gui.SEARCH_STRING_CONTACT_SOURCE=Neach-aithne a chaidh a lorg service.gui.SECURITY=Tèarainteachd -service.gui.SELECT_ACCOUNT=Tagh cunntas service.gui.SELECT_COLOR=Tagh dath service.gui.SELECT_GROUP=Tagh buidheann -service.gui.SELECT_GROUP_WIZARD_MSG=Tha gach buidheann a tha air liosta an luchd-aithne agad air an liosta gu h-ìosal. Tagh am fear a chuireas sinn an neach-aithne ùr ris. service.gui.SELECT_NO_GROUP=Gun bhuidheann -service.gui.SELECT_GROUP_WIZARD=Sònraich buidheann service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Tha gach cunntas a chuireas taic ri cabadaich iomadh cleachdaiche air an liosta gu h-ìosal. Tagh am fear a bu mhath leat cleachdadh gus an seòmar cabadaich agad a chruthachadh. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Tha gach cunntas clàraichte air an liosta gu h-ìosal. Tagh am fear a bu chaomh leat cleachdadh gus conaltradh a dhèanamh ris an neach-aithne ùr. -service.gui.SELECT_PROVIDERS_WIZARD=Tagh cunntas service.gui.SELECT_VIDEO_CONFERENCE=Tagh co-labhairt video service.gui.SERVER_CHAT_ROOMS_DIALOG_TEXT=Tagh seòmar cabadaich on liosta is briog air "Ceart ma-thà" gus a chur ris. service.gui.SEND=C&uir service.gui.SEND_FILE=Cuir am &faidhle -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Chan eil fiosrachadh ann mun neach-aithne seo. service.gui.SEND_MESSAGE=C&uir teachdaireachd -service.gui.SEND_AS_SMS=Cuir mar SMS service.gui.SEND_PRIVATE_MESSAGE=Cuir teachdaireachd phrìobhaideach service.gui.SEND_SMS=Cu&ir SMS service.gui.SEND_SMS_DETAILS=Cuimhnich gum bi agad an àireamh a chur a-steach sa chruth eadar-nàiseanta, m.e. a'' tòiseachadh le +44 airson na Rìoghachd Aonaichte , mar eisimpleir +447777000000 @@ -520,7 +488,6 @@ service.gui.STREET=Sràid service.gui.SUBJECT=Cuspair service.gui.SUMMARY=Gearr-chunntas service.gui.TELEPHONY=Fònadh -service.gui.TODAY=An-diugh service.gui.TOOLS=&Innealan service.gui.TRANSFER=&Sìn air adhart service.gui.TO=&Gu: @@ -530,7 +497,6 @@ service.gui.TRANSFER_CALL_TO=Sìn air adhart gu: service.gui.TRANSPARENCY_NOT_ENABLED=Chan eil an rèiteachadh làithreach agad a'' cur taic ri trìd-shoilleireachd. service.gui.TYPE_YOUR_REQUEST=Sgrìobh d'' iarrtas an-seo service.gui.UNABLE_TO_CHANGE_VIDEO_QUALITY=Cha b'' urrainn dhuinn càileachd a'' video atharrachadh airson a'' ghairm seo. -service.gui.UNMUTE=Till an fhuaim service.gui.USER_IDENTIFIER=Aithnichear a'' chleachdaiche: service.gui.USER_EXISTS_ERROR=Tha an cleachdaiche seo air an lìonra a thagh thu mu thràth. Feuch is tagh cleachdaiche no lìonra eile. service.gui.USERNAME_NULL=Cuir a-steach an t-ainm-cleachdaiche ''s am facal-faire agad. @@ -543,7 +509,6 @@ service.gui.USE_PROVISIONING=Cleachd solar air loidhne service.gui.VALUE=Luach service.gui.VIDEO_CALL=Gairm &video service.gui.VIA=slighe -service.gui.VIA_SMS=Slighe SMS service.gui.VIEW=&Sealladh service.gui.VIEW_HISTORY=Seall an eachdraid&h service.gui.VIEW_SMILEYS=Seall na &samhlaidhean-gnùise @@ -563,9 +528,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=Atharraich àirde na fuaime service.gui.WAITING_AUTHORIZATION=A'' feitheamh ri ùghdarachadh service.gui.WARNING=Rabhadh service.gui.YES=Tha -service.gui.YESTERDAY=An-dè -service.gui.EXISTING_ACCOUNT_ERROR=Chaidh an cunntas a chuir thu a-steach a stàladh mu thràth. -service.gui.NEW_MAIL=Tha aon teachdaireachd ùr agad!
    O: {0} {1}
    Cuspair: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Fhuair thu teachdaireachd puist ùr sa bhogsa a-steach {0} agad:
    service.gui.NEW_GMAIL_MANY_HEADER=Fhuair thu {2} teachdaireachd(an) puist ùr(a) sa bhogsa a-steach {0} agad:
    service.gui.NEW_GMAIL_FOOTER=aon chòmhradh eile gun leughadh sa bhogsa a-steach agad.
    @@ -589,7 +551,6 @@ service.gui.SECURITY_ERROR=Mearachd tèarainteachd service.gui.SPEED=Astar: service.gui.SILENT_MEMBER=ball sàmhach service.gui.NON_SECURE_CONNECTION=Chan urrainn dhuinn ceangal tèarainte a dhèanamh airson a'' chunntais {0}. Ma tha thu airson ceangal ri frithealaiche nach eil tèarainte, cuir cromag ri "Ceadaich ceanglaichean nach eil tèarainte" ann an rèiteachadh a'' chunntais agad. -service.gui.UPDATE=Ùraich service.gui.MOBILE_PHONE=Fòn-làimhe service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Obair @@ -624,7 +585,6 @@ service.gui.callinfo.CALL_INFORMATION=Fiosrachadh mun ghairm service.gui.callinfo.CALL_IDENTITY=Dearbh-aithne service.gui.callinfo.PEER_COUNT=Àireamh nan com-pàirtichean service.gui.callinfo.IS_CONFERENCE_FOCUS=Fòcas na co-labhairt -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=Tha an crioptachadh an comas service.gui.callinfo.CALL_TRANSPORT=A'' siognaileadh giùlanair na gairm service.gui.callinfo.CALL_DURATION=Faid na gairm service.gui.callinfo.VIEW_CERTIFICATE=Seall an teisteanas @@ -635,7 +595,6 @@ service.gui.callinfo.AUDIO_INFO=Fiosrachadh mun fhuaim service.gui.callinfo.VIDEO_INFO=Fiosrachadh mun video service.gui.callinfo.LOCAL_IP=IP/Port ionadail service.gui.callinfo.REMOTE_IP=IP/Port cèin -service.gui.callinfo.BANDWITH=Tar-chur dàta service.gui.callinfo.LOSS_RATE=Reat a'' challa service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Jitter @@ -645,10 +604,13 @@ service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP service.gui.callinfo.KEY_EXCHANGE_PROTOCOL=Pròtacal malairt na h-iuchrach service.gui.callinfo.ICE_CANDIDATE_EXTENDED_TYPE=Seòrsa de thagraiche ICE leudaichte service.gui.callinfo.ICE_STATE=Staid pròiseasadh ICE + +#enum values from IceProcessingState service.gui.callinfo.ICE_STATE.WAITING=Cruinnich na tagraichean service.gui.callinfo.ICE_STATE.RUNNING=Sgrùdaidhean a'' chomais-cheangail service.gui.callinfo.ICE_STATE.COMPLETED=Air a choileanadh service.gui.callinfo.ICE_STATE.FAILED=Dh''fhàillig e + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP/Port an òstair ionadail service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=IP/Port faileasach ionadail service.gui.callinfo.ICE_LOCAL_RELAYED_ADDRESS=IP/Port ath-sheachadaichte ionadail @@ -669,9 +631,10 @@ service.gui.ALWAYS_TRUST=Cuir earbsa san teisteanas seo an-còmhnaidh service.gui.CERT_DIALOG_TITLE=Dearbh an teisteanas service.gui.CERT_DIALOG_DESCRIPTION_TXT=Chan urrainn dha {0} dearbh-àithne an fhrithealaiche a dhearbhadh nuair a cheanglas e ri
    {1}.

    Chan eil earbsa san teisteanas agus is ciall dha sin nach urrainn dhuinn dearbh-àithne an fhrithealaiche a dhearbhadh gu fèin-obrachail.

    A bheil thu airson ceangal co-dhiù?
    Airson barrachd fiosrachaidh, briog air "Seall an teisteanas". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST=Chan urrainn dha {0} dearbh-àithne an fhrithealaiche a dhearbhadh.

    Chan eil earbsa san teisteanas agus is ciall dha sin nach urrainn dhuinn
    dearbh-àithne an fhrithealaiche a dhearbhadh gu fèin-obrachail. A bheil thu airson ceangal co-dhiù?

    Airson barrachd fiosrachaidh, briog air "Seall an teisteanas". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT=Chan urrainn dha {0} dearbh-àithne a'' chliaint a tha a'' ceangal a dhearbhadh.

    Chan eil earbsa san teisteanas agus is ciall dha sin nach urrainn dhuinn
    dearbh-àithne a'' chliaint a dhearbhadh gu fèin-obrachail. A bheil thu airson gabhail ris a'' cheangal co-dhiù?

    Airson barrachd fiosrachaidh, briog air "Seall an teisteanas". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT=Chan urrainn dha {0} dearbh-àithne an t-seise {1} a dhearbhadh.

    Chan eil earbsa san teisteanas agus is ciall dha sin nach urrainn dhuinn
    dearbh-àithne an t-seise a dhearbhadh gu fèin-obrachail. A bheil thu airson ceangal co-dhiù?

    Airson barrachd fiosrachaidh, briog air "Seall an teisteanas". service.gui.CONTINUE_ANYWAY=Lean air adhart co-dhiù + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Ainm cumanta: service.gui.CERT_INFO_O=Buidheann: service.gui.CERT_INFO_C=Ainm na dùthcha: @@ -685,12 +648,10 @@ service.gui.CERT_INFO_VER=Tionndadh: service.gui.CERT_INFO_SIGN_ALG=Algairim an t-soidhnidh: service.gui.CERT_INFO_ALG=Algairim: service.gui.CERT_INFO_PUB_KEY=Iuchair phoblach: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} bytes: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} bits service.gui.CERT_INFO_EXP=Easponant: service.gui.CERT_INFO_KEY_SIZE=Meud na h-iuchrach: service.gui.CERT_INFO_SIGN=Soidhneadh: -service.gui.CONTINUE=Lean air adhart service.gui.SHOW_CERT=Seall an teisteanas service.gui.HIDE_CERT=Falaich an teisteanas @@ -713,11 +674,8 @@ service.gui.security.SECURE_AUDIO=Fuaim thèarainte service.gui.security.AUDIO_NOT_SECURED=Chan eil an fhuaim tèarainte service.gui.security.SECURE_VIDEO=Video tèarainte service.gui.security.VIDEO_NOT_SECURED=Chan eil a'' video tèarainte -service.gui.security.NO_VIDEO=Chan eil video ann -service.gui.security.CIPHER=Sifir: {0} service.gui.security.CALL_NOT_SECURED_TOOLTIP=Chan eil a'' ghairm tèarainte. service.gui.security.CALL_SECURED_COMPARE_TOOLTIP=Briog an-seo gus coimeas a dhèanamh eadar an rùn tèarainteachd agadsa agus aig a'' chèile agad. -service.gui.security.COMPARE_WITH_PARTNER=Dèan coimeas leis a'' chèile agus briog air a'' ghlas gus a dhearbhadh. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Dèan coimeas leis a'' chèile: service.gui.security.STRING_COMPARED=Chaidh coimeas a dhèanamh eadar an dà shreang! @@ -735,19 +693,13 @@ service.gui.avatar.imagepicker.CLICK=Dèan briogadh is fiamh-ghàire service.gui.avatar.imagepicker.IMAGE_FILES=Faidhlichean deilbh service.gui.avatar.imagepicker.IMAGE_PICKER=Dealbh service.gui.avatar.imagepicker.IMAGE_SIZE=Meud an deilbh -service.gui.avatar.imagepicker.INITIALIZING=''Ga thòiseachadh service.gui.avatar.imagepicker.RESET=Ath-shuidhich service.gui.avatar.imagepicker.SET=Suidhich service.gui.avatar.imagepicker.TAKE_PHOTO=Tog dealbh -service.gui.avatar.imagepicker.WEBCAM_ERROR=Mearachd leis a'' chamara-lìn service.gui.security.encryption.required=Tha feum air crioptachadh! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ impl.protocol.sip.XCAP_ERROR_TITLE=Mearachd ann an stòras liosta an luchd-aithne SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Cha ghabh an goireas {0} a leughadh. Airson {1} @@ -777,9 +729,7 @@ impl.ldap.QUERY_CUSTOM=Ceist ghnàthaichte impl.ldap.QUERY_CUSTOM_HINT=Cleachd {0} mar glèidheadair-àite airson an fhacail-luirg seo. impl.ldap.QUERY_CUSTOM_AUTO_WILDCARD=Cuir saoragan ri teirm na ceiste gu fèin-obrachail impl.ldap.QUERY_PHOTO_INLINE=Faigh an dealbh an cois nam buadhan eile -impl.ldap.NEW=Ùr impl.ldap.EDIT=deasaich -impl.ldap.REMOVE=Thoir air falbh impl.ldap.ENABLED=An comas impl.ldap.SERVER_NAME=Ainm an fhrithealaiche impl.ldap.SERVER_NAME_EXAMPLE=Am frithealaiche LDAP agam @@ -812,6 +762,10 @@ impl.ldap.HOMEPHONE_FIELD_EXAMPLE=fòn dachaidh impl.ldap.PHONE_PREFIX=Ro-leasachan fòn impl.ldap.PHONE_PREFIX_EXAMPLE=M.e.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Leabhar nan seòladh plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Cuir an comas lorg ann an leabhar sheòlaidhean MacOSX @@ -822,9 +776,7 @@ plugin.addrbook.PREFIX_EXAMPLE=M.e.: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Luchd-aithne Google -impl.googlecontacts.NEW=Ùr impl.googlecontacts.EDIT=deasaich -impl.googlecontacts.REMOVE=Thoir air falbh impl.googlecontacts.ENABLED=An comas impl.googlecontacts.ACCOUNT_NAME=Ainm a'' chunntais impl.googlecontacts.SAVE=Sàbhail @@ -863,11 +815,8 @@ plugin.accountinfo.ORGANIZATION=Ainm a' bhuidhinn: plugin.accountinfo.JOB_TITLE=Ainm an dreuchd: plugin.accountinfo.ABOUT_ME=Mu mo dhèidhinn: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 -plugin.accountinfo.USER_PICTURES=Dealbhan a'' chleachdaiche plugin.accountinfo.GLOBAL_ICON=Cleachd ìomhaigheag uile-choitcheann plugin.accountinfo.LOCAL_ICON=Cleachd an ìomhaigheag seo: -plugin.accountinfo.CHANGE=Atharraich -plugin.accountinfo.ONLY_MESSAGE=Teachdaireachdan a-mhàin # connection info @@ -886,49 +835,12 @@ plugin.aimaccregwizz.USERNAME=Ainm-sgrìn AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Ainm-sgrìn ''s facal-faire plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Clàraich cunntas ùr plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=Mur eil cunntas AIM agad, briog air a'' phutan seo gus fear ùr a chruthachadh. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Tar-àithn bun-roghainnean an fhrithealaiche # branding plugin.branding.ABOUT_WINDOW_TITLE=Mu dhèidhinn {0} plugin.branding.LOGO_MESSAGE=VoIP ⁊ grad-theachdaireachdan le còd fosgailte -plugin.branding.LOADING=''Ga luchdadh plugin.branding.ABOUT_MENU_ENTRY=&Mu dheidhinn -plugin.branding.WELCOME_MESSAGE=
    Tha {1} ''ga leasachadh an-dràsta fhèin. ''S e tionndadh deuchainneil a tha agad agus DH''FHAOIDTE nach obraich e mar a tha dùil. Thoir sùil air {2} airson barrachd fiosrachaidh.
    -plugin.branding.COPYRIGHT=
    (c)2003-2013 Còir-lethbhreac jitsi.org. Gach còir glèidhte. Tadhail air https://jitsi.org.
    -plugin.branding.LICENSE=
    Tha Jitsi ''ga sgaoileadh fo theirmichean an LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Faclairean -plugin.dictaccregwizz.ANY_DICTIONARY=Faclair sam bith -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Faclair sam bith o {0} -plugin.dictaccregwizz.FIRST_MATCH=A'' chiad mhaids -plugin.dictaccregwizz.NO_MATCH=Gun mhaids -plugin.dictaccregwizz.MATCH_RESULT=Cha deach deifinisean a lorg airson "{0}", an robh na leanas fa-near dhut:\n -plugin.dictaccregwizz.INVALID_DATABASE=Chan eil am faclair làithreach "{0}" air an fhrithealaiche tuilleadh. -plugin.dictaccregwizz.INVALID_STRATEGY=Chan eil an ro-innleachd làithreach ri fhaighinn air an fhrithealaiche. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal seirbheis Dict -plugin.dictaccregwizz.HOST=Òstair -plugin.dictaccregwizz.SERVER_INFO=Fiosrachadh mun fhrithealaiche -plugin.dictaccregwizz.STRATEGY_SELECTION=Taghadh na ro-innleachd -plugin.dictaccregwizz.STRATEGY_LIST=Liosta nan ro-innleachdan: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Ro-innleachdan luirg -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Thèid an ro-innleachd a chleachdadh gus faclan a tha coltach ri chèile a lorg mur an deach eadar-theangachadh a lorg, stèidhichte air diofar dòighean-obrach. Ma eisimpleir, lorgaidh ro-innleachdan nan ro-leasachan faclan a tha a'' tòiseachadh mar a tha am facal air an dèanadh tu eadar-theangachadh. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Fiosrachadh a'' chunntais Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Cruthaichidh an draoidh seo a' chiad chunntas Dict dhut air dict.org.\n\n'S urrainn dhut faclair ùr a chruthachadh ma thèid thu gu draoidh clàradh nan cunntasan. Cuir am faclair a bu toigh leat a chur ris ann an lìon an òstair. -plugin.dictaccregwizz.THREAD_CONNECT=A'' feuchainn ri ceangal a dhèanamh ris an fhrithealaiche -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Dh''fhàillig an ceangal, chan e frithealaiche Dict a tha seo no tha am frithealaiche far loidhne -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=A'' faighinn nan ro-innleachdan -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Cha deach ro-innleachd a lorg air an fhrithealaiche -plugin.dictaccregwizz.POPULATE_LIST=A'' lìonadh na liosta -plugin.dictaccregwizz.CLOSING_CONNECTION=A'' dùnadh a'' cheangail - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Mus urrainn dhut Facebook Chat a chleachdadh, feumaidh tu ainm-cleachdaiche
    a chruthachadh air duilleag nan "Account Settings" air Facebook.


    An aire: Nuair a chruthaicheas tu ainm-cleachdaiche,
    feumaidh tu clàradh às an duilleag-lìn is faodaidh gum bi greis mus urrainn dhut clàradh a-steach leis an ainm ùr!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal Facebook Chat -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Ainm-cleachdaiche: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Ainm-cleachdaiche ''s facal-faire + # generalconfig plugin.generalconfig.AUTO_START=Tòisich {0} gu fèin-obrachail nuair a thòisicheas an coimpiutair agad @@ -939,9 +851,6 @@ plugin.generalconfig.SHOW_HISTORY=Seall plugin.generalconfig.HISTORY_SIZE=teachdaireachdan a sgrìobhadh o chionn goirid ann an cabadaich ùr plugin.generalconfig.SEND_MESSAGES_WITH=Cuir teachdaireachdan le: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Gluais uinneag na cabadaich gun bheulaibh -plugin.generalconfig.ERROR_PERMISSION=Chan eil pribhleidean gu leòr agad gus casg a chur air an fhèin-tòiseachadh -plugin.generalconfig.TRANSPARENCY=Trìd-shoilleireachd -plugin.generalconfig.ENABLE_TRANSPARENCY=Cuir an comas trìd-shoilleireachd plugin.generalconfig.DEFAULT_LANGUAGE=Cànan na h-eadar-aghaidh plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Bidh na h-atharraichean agad an sàs ann an ath-thuras a thòisicheas tu. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% air eadar-theangachadh @@ -995,11 +904,9 @@ plugin.ircaccregwizz.HOST=Ainm an òstair: plugin.ircaccregwizz.IRC_SERVER=Frithealaiche # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal XMPP plugin.jabberaccregwizz.USERNAME=Ainm-cleachdaiche XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Dearbhaich am facal-faire -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID is am facal-faire plugin.jabberaccregwizz.CSERVER=Frithealaiche plugin.jabberaccregwizz.SERVER=Ceangail am frithealaiche plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Cuir an comas an ceangal buan @@ -1015,13 +922,9 @@ plugin.jabberaccregwizz.COMMENT_COLUMN=Beachd plugin.jabberaccregwizz.RESOURCE=Goireas plugin.jabberaccregwizz.AUTORESOURCE=Gin an goireas gu fèin-obrachail plugin.jabberaccregwizz.PRIORITY=Prìomhachas -plugin.jabberaccregwizz.XMPP_ERROR=Mearachd XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Mearachd XMPP nach aithne dhuinn ({0}). Dèan cinnteach gu bheil ainm an fhrithealaiche ceart. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Chan eil an dà fhacal-faire co-ionnann. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Tar-àithn bun-roghainnean an fhrithealaiche -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Roghainnean adhartach plugin.jabberaccregwizz.USE_ICE=Cleachd ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=Cleachd Jingle Google/ICE (deuchainneil) plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Mothaich do dh''fhrithealaichean STUN/TURN gu fèin-obrachail plugin.jabberaccregwizz.SUPPORT_TURN=Cuir taic ri TURN plugin.jabberaccregwizz.TURN_USERNAME=Ainm-cleachdaiche TURN @@ -1049,11 +952,8 @@ plugin.jabberaccregwizz.DISABLE_CARBON=Cuir carboin nan teachdaireachdan à coma plugin.jabberaccregwizz.DTMF_AUTO=Gu fèin-obrachail: Dèan taghadh eadar RTP is Inband gu fèin-obrachail plugin.jabberaccregwizz.SERVER_OPTIONS=Roghainnean an fhrithealaiche plugin.jabberaccregwizz.CHANGE_PASSWORD=Atharraich facal-faire a'' chunntais -plugin.jabberaccregwizz.NEW_PASSWORD=Facal-faire ùr -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Dearbh am facal-faire ùr plugin.jabberaccregwizz.PORT_FIELD_INVALID=Nach cuir thu a-steach àireamh puirt dhligheach mus lean thu air adhart? plugin.jabberaccregwizz.HAS_TO_BE_LOGGED_IN=Feumaidh tu clàradh a-steach mus gabh am facal-faire atharrachadh. -plugin.jabberaccregwizz.PASSWORD_EMPTY=Tha am facal-faire bàn. plugin.jabberaccregwizz.TLS_REQUIRED=Chan eil an ceangal seo a'' cleachdadh TLS, chan fheuch sinn ris am facal-faire atharrachadh. plugin.jabberaccregwizz.PASSWORD_CHANGED=Chaidh am facal-faire atharrachadh plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=Chan eil am frithealaiche XMPP agad a'' ceadachadh atharrachadh fhaclan-faire. @@ -1067,25 +967,9 @@ plugin.jabberaccregwizz.RESET=Ath-shuidhich plugin.jabberaccregwizz.RESET_DESCRIPTION=Ath-shuidhich na roghainnean uile-choitcheann plugin.jabberaccregwizz.DISABLE_JINGLE=Cuir às comas Jingle (gairmean gutha is video le XMPP). -# mailbox -plugin.mailbox.OUTGOING=Teachdaireachdan a thèid a-mach: -plugin.mailbox.INCOMING=Teachdaireachdan a thig a-steach: -plugin.mailbox.WAIT_TIME=Cuir dàil air gus an deach a'' ghairm a chur gun phost-ghutha -plugin.mailbox.MAX_MESSAGE_TIME=Faid as motha de theachdaireachdan a thig a-steach -plugin.mailbox.CONFIRM=Dearbhaich -plugin.mailbox.DEFAULTS=Bun-roghainnean -plugin.mailbox.MAILBOX=Bogsa-puist - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal leis an urrainn dhut ceangal ri seirbheis MSN agus cabadaich air. -plugin.msnaccregwizz.USERNAME=Post-d: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=ID is am facal-faire - # plugin manager plugin.pluginmanager.INSTALL=Stàlaich plugin.pluginmanager.UNINSTALL=Dì-stàlaich -plugin.pluginmanager.UPDATE=Ùraich plugin.pluginmanager.PLUGINS=Plugain plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Tagh faidhle @@ -1110,7 +994,6 @@ plugin.sipaccregwizz.SERVER_PORT=Port an fhrithealaiche plugin.sipaccregwizz.PROXY=Progsaidh plugin.sipaccregwizz.PROXY_PORT=Port a'' phrogsaidh plugin.sipaccregwizz.PREFERRED_TRANSPORT=Giùlanair as fhearr leat -plugin.sipaccregwizz.ADVANCED_OPTIONS=Roghainnean adhartach plugin.sipaccregwizz.PROXY_OPTIONS=Roghainnean a'' phrogsaidh plugin.sipaccregwizz.PROXY_AUTO=Rèitich am progsaidh gu fèin-obrachail plugin.sipaccregwizz.ENABLE_PRESENCE=Cuir làthaireachd an comas (SIMPLE) @@ -1130,8 +1013,6 @@ plugin.sipaccregwizz.DTMF_AUTO=Gu fèin-obrachail: Dèan taghadh eadar RTP is In plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=SIP INFO plugin.sipaccregwizz.DTMF_INBAND=Inband -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Tar-àithn bun-roghainnean an fhrithealaiche plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Cuir an comas taic ri gairmean crioptaichte plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Nochd gu bheil taic ri ZRTP sa phròtacal siognailidh plugin.sipaccregwizz.AUTH_NAME=Ainm an ùghdarachaidh @@ -1152,10 +1033,10 @@ plugin.sipaccregwizz.VOICEMAIL_CHECK_URI=URI sgrùdadh puist-ghutha plugin.sipaccregwizz.NOT_SAME_PASSWORD=Chan eil an dà fhacal-faire co-ionnann. plugin.sipaccregwizz.NO_CERTIFICATE= (cleachd dearbhadh àbhaisteach) plugin.sipaccregwizz.SAVP_OPTION=Taisbeanadh RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=Dheth (taisbean RTP/AVP a-mhàin) plugin.sipaccregwizz.SAVP_OPTION_1=Èigneachail (na tairg is na gabh ach ri RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=Roghainneil (tairg RTP/SAVP an toiseach is RTP/AVP an uairsin) -plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE=Cuir an comas S-Descriptor (air a bheil SDES no SRTP cuideachd) plugin.sipaccregwizz.ENCRYPTION_PROTOCOL_PREFERENCES=Tagh pròtacalan crioptachaidh a tha an comas agus na prìomhachasan aca (am pròtacal aig a'' bharr an toiseach): plugin.sipaccregwizz.CIPHER_SUITES=Cipher suites a tha an comas: plugin.sipaccregwizz.SECURITY_WARNING=
    Feuchaidh {0} gu fèin-obrachail ris na gairmean uile agad a dhèanamh tèarainte le ZRTP agus cluinnidh an dithis agaibh brath turas a chaidh ceangal tèarainte a stèidheachadh. Cha bu chòir dhut na roghainnean adhartach gu h-ìosal atharrachadh ach ma tha thu gu math eòlach air a leithid a rud.
    @@ -1169,15 +1050,6 @@ plugin.skinmanager.DEFAULT_SKIN=An craiceann bunaiteach plugin.skinmanager.ADD_NEW_SKIN=Cuir craiceann ùr ris... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Craiceann bunaiteach na h-aplacaid. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal leis an urrainn dhut ceangal a dhèanamh ri innealan cèin slighe SSH. -plugin.sshaccregwizz.USERNAME=ID a'' chunntais: -plugin.sshaccregwizz.IDENTITY_FILE=Faidhle na dearbh-aithne: -plugin.sshaccregwizz.KNOWN_HOSTS=Òstairean as aithne dhuinn: -plugin.sshaccregwizz.OPTIONAL=Roghainneil -plugin.sshaccregwizz.ACCOUNT_DETAILS=Fiosrachadh a'' chunntais - # status update plugin.autoaway.AUTO_STATUS=Suidhich "Air falbh" gu fèin-obrachail plugin.autoaway.ENABLE_CHANGE_STATUS=Atharraich mo làthaireachd nuair a bhios mi air falbh @@ -1224,22 +1096,6 @@ plugin.whiteboard.DESELECT=Dì-thagh plugin.whiteboard.DELETE=Sguab às plugin.whiteboard.PROPERTIES=Roghainnean -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal leis an urrainn dhut ceangal ri seirbheis Yahoo! agus cabadaich air. -plugin.yahooaccregwizz.USERNAME=Ainm-cleachdaiche: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=ID is am facal-faire - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal na seirbheise Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Ainm: -plugin.zeroaccregwizz.LAST_NAME=Sloinneadh -plugin.zeroaccregwizz.EMAIL=Post-d: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=A bheil thu airson luchd-aithne Bonjour a chumail an cuimhne? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=ID is facal-faire -plugin.zeroaccregwizz.USERID=ID a'' chleachdaiche - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Pròtacal Google Talk @@ -1253,19 +1109,11 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, am portal cian-chonaltrad plugin.iptelaccregwizz.USERNAME=Ainm-cleachdaiche plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Fo-sgrìobh gu iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP agus cabadaich +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Ainm-cleachdaiche plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Cuir am facal-faire a-steach a-rithist plugin.sip2sipaccregwizz.EMAIL=Seòladh puist-d -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Airson cobhar leis an t-seirbheis seo, tadhail air
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Thèid an seòladh puist-d a chleachdadh gus post-gutha agus brathan mu,
    ghairmean a chaill thu a chur agus faclan-faire a dhìochuimhnich thu aiseag -plugin.sip2sipaccregwizz.INFO_NOTE=Airson cobhair leis an t-seirbheis seo, tadhail air http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Cunntas sip2sip.info a tha ann mu thràth -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Cruthaich cunntas sip2sip.info saor an-asgaidh - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.PROTOCOL_DESCRIPTION=VoIP ⁊ grad-theachdaireachdan plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Airson cobhar leis an t-seirbheis seo, tadhail air
    http://ippi.fr @@ -1274,6 +1122,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Cunntas ippi a tha ann mu thràth plugin.ippiaccregwizz.CREATE_ACCOUNT=Cruthaich cunntas ippi ùr # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Dùin uinneag na cabadaich plugin.keybindings.CHAT_COPY=Dèan lethbhreac plugin.keybindings.CHAT_CUT=Gearr às @@ -1296,10 +1145,10 @@ plugin.keybindings.globalchooser.SHORTCUT_NAME=Ainm plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=Prìomh ath-ghoirid plugin.keybindings.globalchooser.SHORTCUT_SECOND=Dàrna ath-ghoirid plugin.keybindings.globalchooser.PRESS_BTN=Dèan brùthadh gus an ath-ghoirid a shuidheachadh -plugin.keybindings.globalchooser.PRESS_BTN_DOWN=A'' feitheamh plugin.keybindings.globalchooser.PUSH_TO_TALK=Brùth airson bruidhinn plugin.keybindings.globalchooser.ENABLE_SPECIAL=Cuir an comas mothachadh do dh''iuchraichean sònraichte plugin.keybindings.PLUGIN_NAME=Ceanglaichean iuchrach +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Cabadaich plugin.keybindings.MAIN=Prìomh-cheangal iuchrach plugin.keybindings.GLOBAL=Ath-ghoiridean uile-choitcheann @@ -1326,6 +1175,7 @@ plugin.notificationconfig.tableheader.SOUND=Cluich fuaim tro uidheam bhrathan plugin.notificationconfig.tableheader.PLAYBACK_SOUND=Cluich fuaim tro uidheam cluiche plugin.notificationconfig.tableheader.PCSPEAKER_SOUND=Cluich fuaim tro glaodhaire a'' PC plugin.notificationconfig.tableheader.DESCRIPTION=Tuairisgeul tachartais +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Gairm a'' tighinn a-steach plugin.notificationconfig.event.SecurityMessage=Teachdaireachd tèarainteachd plugin.notificationconfig.event.IncomingFile=Faidhle a'' tighinn a-steach @@ -1427,6 +1277,7 @@ impl.neomedia.configform.VIDEO=Video impl.neomedia.configform.H264=H.264 impl.neomedia.configform.H264.defaultIntraRefresh=Ath-nuadhachadh Intra cunbhalach impl.neomedia.configform.H264.defaultProfile=A'' phròifil bhunaiteach dhan a nithear còdachadh: +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.baseline=Bun-loidhne impl.neomedia.configform.H264.defaultProfile.high=Àrd impl.neomedia.configform.H264.defaultProfile.main=Prìomh-phròifil @@ -1457,7 +1308,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Am facal-faire làithreach plugin.securityconfig.masterpassword.ENTER_PASSWORD=Cuir a-steach am facal-faire ùr: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Cuir a-steach am facal-faire a-rithist: plugin.securityconfig.masterpassword.MP_TITLE=Prìomh-fhacal-faire -plugin.securityconfig.masterpassword.MP_NOT_SET=(cha deach a shuidheachadh) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Cha do chuir thu a-steach am prìomh fhacal-faire làithreach ceart. Feuch ris a-rithist. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Tha am prìomh fhacal-faire cearr! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Dh''fhàillig atharrachadh an fhacail-fhaire @@ -1473,7 +1323,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Facal-faire plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(neo aithnichte) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(cha ghabh a dhì-chrioptachadh) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Faclan-faire a tha ''gan stòradh -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Thoir air falbh plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Thoir air falbh a h-uile plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=A bheil thu airson gach facal-faire a thoirt air falbh? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Thoir air falbh a h-uile facal-faire @@ -1569,7 +1418,6 @@ plugin.globalproxy.PROXY_PORT=Port a'' phrogsaidh plugin.globalproxy.PROXY_USERNAME=Ainm-cleachdaiche a'' phrogsaidh plugin.globalproxy.PROXY_PASSWORD=Facal-faire a'' phrogsaidh plugin.globalproxy.DESCRIPTION=Cleachdaidh {0} na roghainnean progsaidh gu h-àrd airson a h-uile lìonra a cheanglas tu ris no a dh'ath-cheanglas tu ris. \nTha an taic ri progsaidhean caran deuchainneil an-dràsta agus chan obraich e ach le cuid a phròtacalan. Thoir sùil air a' chlàr gu h-ìosal airson barrachd fiosrachaidh: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=DNS progsaidh cuideachd plugin.globalproxy.FWD_DNS_NOTE=Feumail le Tor. ''S urrainn dhut aoideanan DNS a sheachnadh leis is e a'' sìneadh air adhart an trafaig DNS air fad gun phrogsaidh Tor. Bidh agad ri ath-thòiseachadh. @@ -1602,7 +1450,6 @@ plugin.provisioning.RESTART_WARNING=Thoir an aire nach dèid na h-atharraichean plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=Cuir lethbhreac dhen UUID air an stòr-bhòrd plugin.provisioning.CLIPBOARD_FAILED=Cha b'' urrainn dhuinn lethbhreac dhen UUID a chur air an stòr-bhòrd -plugin.provisioning.EXIT_ON_FAIL=Fàg an aplacaid ma dh''fhàilligeas am provisioning plugin.provisioning.CREDENTIALS=Na teisteasan provisioning mu dheireadh a chaidh a stòradh plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=A bheil thu airson facal-faire a'' provisioning a thoirt air falbh? plugin.provisioning.PROV_FAILED=Dh''fhàillig am provisioning @@ -1669,8 +1516,6 @@ util.dns.DNSSEC_WARNING=
    Dh''fheuch {0} ri ceangal a dhèa #plugin spellcheck plugin.spellcheck.TITLE=Litreachadh is gràmar plugin.spellcheck.MENU=Seall dearbhadh an litreachaidh is a'' ghràmair -plugin.spellcheck.LANG=Cànan -plugin.spellcheck.EDIT_PERSONAL_DICT=Deasaich plugin.spellcheck.ENABLE_SPELL_CHECK=Cuir an comas an dearbhair-litreachaidh plugin.spellcheck.dialog.FIND=Lorg an ath-fhear plugin.spellcheck.dialog.REPLACE=Cuir ''na àite -- cgit v1.1 From 3542ee60589a68d1804594f5a5fa6db2ecf896cd Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:10 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 768 of 1505 strings translated (139 fuzzy). --- resources/languages/resources_ro.properties | 206 ++++++---------------------- 1 file changed, 40 insertions(+), 166 deletions(-) diff --git a/resources/languages/resources_ro.properties b/resources/languages/resources_ro.properties index 872eb64..3b7168e 100644 --- a/resources/languages/resources_ro.properties +++ b/resources/languages/resources_ro.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,26 +43,20 @@ service.gui.ACCOUNT_ME=Eu service.gui.ACCOUNT_REGISTRATION_WIZARD=Asistent de înregistrare a contului service.gui.ACCOUNTS=Conturi service.gui.ADD=&Adaugă -service.gui.ADD_ACCOUNT=Adaugă cont service.gui.ADD_CONTACT=&Adaugă contact service.gui.ADD_AUTHORIZED_CONTACT=Adaugă {0} în lista ta de contacte service.gui.ADD_CONTACT_TO=&Adaugă contact la service.gui.ADD_CONTACT_ERROR=Nu s-a putut adăuga contactul cu identificatorul: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Eroare la adăugarea contactului service.gui.ADD_CONTACT_EXIST_ERROR=Contactul {0} deja există în lista dvs de contacte. -service.gui.ADD_CONTACT_IDENTIFIER=În câmpul de mai jos introduceți identificatorul contactului pe care doriți să-l adăugați. -service.gui.ADD_CONTACT_WIZARD=Asistent de adăugare a contactului service.gui.ADD_GROUP_LOCAL_ERROR=A eșuat adăugarea grupului cu numele: {0}. Problema a intervenit în timpul unei operații locale IO. service.gui.ADD_GROUP_EXIST_ERROR=Grupul {0} deja există în lista dvs de contacte. Vă rugăm să alegeți un alt nume. service.gui.ADD_GROUP_NET_ERROR=A eșuat adăugarea grupului cu numele: {0}. Problema se datorează unei erori de rețea. Verificați conexiunea la rețea și reîncercați. service.gui.ADD_GROUP_ERROR=Nu s-a putut adăuga grupul cu numele: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Numele grupului trebuie să nu fie gol. -service.gui.ADD_GROUP=Creează grup -service.gui.ADD_SUBCONTACT=&Adaugă subcontact service.gui.ADDRESS=Adresă service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Avansat -service.gui.ALL=&Toate service.gui.ALL_CONTACTS=&Toate contactele service.gui.APPLY=&Aplică service.gui.ARE_CALLING=sună... @@ -60,7 +65,6 @@ service.gui.AT=la service.gui.AUTHORIZE=&Autorizează service.gui.AUTHORIZATION_ACCEPTED=contactul a acceptat cererea dvs de autorizare. service.gui.AUTHENTICATION_FAILED=Autentificarea a eșuat pentru {0}. Parola introdusă nu este validă. -service.gui.AUTHENTICATION_REQUESTED=Este necesară autentificare service.gui.AUTHENTICATION_REQUESTED_SERVER=Serverul {0} solicită autentificarea dvs. service.gui.AUTHENTICATION_REJECTED=contactul a refuzat cererea dvs de autorizare. service.gui.AUTHENTICATION_WINDOW_TITLE=autentificarea {0} @@ -103,13 +107,11 @@ service.gui.CHAT_ROOM_USER_KICKED=a fost exclus(ă) din {0} service.gui.CHAT_ROOM_USER_QUIT=a părăsit {0} service.gui.CHAT_ROOM_NAME=Numele conferinței service.gui.ROOM_NAME=Conferință -service.gui.AUTOJOIN=Intră automatic service.gui.CHANGE_PASSWORD=Schimbă parola service.gui.CHAT_ROOM_NAME_INFO=În câmpul de mai jos introduceți numele conferinței pe care doriți să o creați. service.gui.CHAT_ROOM_NOT_EXIST=Conferința {0} nu a fost găsită pe serverul {1}. Verificați corectitudinea numelui introdus. service.gui.CHAT_ROOM_NOT_CONNECTED=Este necesar să fiți conectat(ă) pentru a vă putea înscrie la conferință {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Trebuie să fiți conectat(ă) pentru a vă putea deconecta de la o conferință. -service.gui.CHAT_ROOM_NOT_JOINED=Trebuie să fiți înscris(ă) la conferință pentru a avea posibilitatea de a efectua diverse operații în cadrul acesteia. service.gui.CHAT_ROOM_OPTIONS=Setările conferinței service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Conferința {0} necesită să fiți înregistrat(ă) pentru a vă înscrie la ea. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Conferința {0} necesită parolă. @@ -123,21 +125,17 @@ service.gui.CLEAR=Șterge service.gui.CLOSE=În&chide service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Ați primit un mesaj acum 2 secunde. Sunteți sigur(ă) ca vreți să terminați conversația dată? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Are loc transfer de fișiere. Sunteți sigur(ă) că doriți să-l amânați? -service.gui.CONFIRM=Confirmă service.gui.CONNECTED_STATUS=Conectat service.gui.CONNECTING=Se conectează... service.gui.CONNECTING_STATUS=Conexiunea service.gui.CONNECTING_EARLY_MEDIA_STATUS=Se conectează... service.gui.CONNECTION=Conexiunea -service.gui.CONNECTION_FAILED_MSG=Eroare de conexiune pentru următorul cont: Nume utilizator: {0}, Nume server: {1}. Vă rugăm să verificați conexiunea la rețea sau să contactați administratorul rețelei dvs pentru mai multă informație. service.gui.CONNECTION_EXPIRED_MSG=La momentan sunteți deconectat(ă) de la serverul {0}. service.gui.CONTACT_NAME=ID sau număr -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Contactul {0} nu suportă telefonie. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Contactul {0} nu suportă discuții în grup. service.gui.CONTACT_PAUSED_TYPING={0} s-a oprit din scrierea mesajului service.gui.CONTACT_TYPING={0} scrie un mesaj service.gui.CONTACT_INFO=&Informația de contact -service.gui.CONTACTLIST=Listă de contacte service.gui.CONTACTS=Contacte service.gui.COPY=&Copiază service.gui.COPY_LINK=Copiază &legătura @@ -147,13 +145,10 @@ service.gui.CREATE_CHAT_ROOM=&Creează conferință... service.gui.CREATE_CHAT_ROOM_ERROR=Nu s-a putut crea conferința cu numele {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Asistent de creare a conferinței service.gui.CREATE_CONFERENCE_CALL=&Creează un apel în grup... -service.gui.CREATE_CONFERENCE_CHAT=&Creează o discuție în grup... service.gui.CREATE_GROUP=&Creează grup... service.gui.CREATE_GROUP_NAME=În câmpul de mai jos introduceți numele grupului pe care doriți să-l creați. -service.gui.CREATE_FIRST_GROUP_WIZARD=Lista dvs de contacte nu conține nici un grup. Pentru început creați un grup (Fișier/Creează grup). service.gui.CONTACT_INFO_NOT_SUPPORTED=Acest contact nu suportă informații de contact pe web service.gui.CUT=T&aie -service.gui.DATE=Data service.gui.DELETE=Șterge service.gui.DENY=&Refuză service.gui.DESKTOP_SHARING_WARNING=Sunteți sigur că doriți să distribuiți public ecranul?
    Apăsând OK veți lăsa alți oameni să vă vadă ecranul. @@ -163,7 +158,6 @@ service.gui.DISCONNECTED_STATUS=Deconectat service.gui.DND_STATUS=A nu deranja service.gui.DO_NOT_ASK_AGAIN=A nu întreba din nou service.gui.DO_NOT_SHOW_AGAIN=A nu afișa mesajul din nou -service.gui.DOWNLOAD_NOW=&Descarcă acum service.gui.DURATION=durata service.gui.EDIT=&Editare service.gui.EDITED_AT=editat la {0} @@ -179,7 +173,6 @@ service.gui.ERROR_RECEIVED_FROM=S-a recepționat o eroare de la service.gui.ESTIMATED_TIME=Timpul aproximativ: service.gui.EVENTS=Evenimente service.gui.EXIT=Term&ină -service.gui.EXTENDED_CRITERIA=Criteriu extins service.gui.GENERAL=General service.gui.GENERAL_ERROR=Eroare generală service.gui.GROUP_NAME=Numele grupului @@ -237,12 +230,12 @@ service.gui.HISTORY=&Istoria service.gui.HISTORY_CONTACT=Istoria - {0} service.gui.HOME=Acasă service.gui.HOME_PAGE=Pagina de pornire -service.gui.HOUR=Ora service.gui.ICE=ICE service.gui.IDENTIFIER=Identificatorul service.gui.IGNORE=&Ignoră service.gui.INSERT_SMILEY=Inserează smile service.gui.INCOMING_CALL=Apelul de intrare recepționat de la: {0} +service.gui.INCOMING_SCREEN_SHARE=Apelul de intrare recepționat de la: {0} service.gui.INCOMING_CALL_STATUS=Apel primit service.gui.INSTANT_MESSAGINGS=MI service.gui.INITIATING_CALL_STATUS=Se inițiază apelul @@ -258,7 +251,6 @@ service.gui.IS_CALLING=sună... service.gui.IS_NOW={0} acuma e {1} service.gui.JOIN=&Înscriere service.gui.JOIN_AS=Î&nscriere ca -service.gui.CLOSE_CHAT_ROOM_DIALOG=Î&nchide service.gui.JOB_TITLE=Funcție service.gui.JOIN_CHAT_ROOM=&Înscriere la conferință... service.gui.JOIN_CHAT_ROOM_TITLE=Înscriere la conferință @@ -269,7 +261,6 @@ service.gui.KICK_FAILED=Excluderea a eșuat service.gui.KICK_FAILED_GENERAL_ERROR=A eșuat excluderea {0}. A intervenit o eroare generală la server. service.gui.KICK_FAILED_NOT_ALLOWED=A eșuat excluderea {0}. Proprietarul sau administratorul conferinței nu poate fi exclus. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=A eșuat excluderea {0}. Nu dispuneți de suficiente privilegii pentru această operație. -service.gui.LAST=Ultimul service.gui.LAST_NAME=Prenume: service.gui.LEAVE=&Părăsește service.gui.LIMIT_REACHED_FOR_IP=Dvs aveți prea multe registrări curente de pe adresa IP locală și serverul {0} nu mai permite alte înregistrări. @@ -288,7 +279,6 @@ service.gui.MESSAGE=Mesaj: service.gui.MISSED_CALLS_TOOL_TIP=Apeluri pierdute de la: service.gui.MISSED_CALLS_MORE_TOOL_TIP= și {0} mai mult(e) service.gui.MODERATOR=moderator -service.gui.MORE=Vizualizați mai mult service.gui.MORE_LABEL=Mută service.gui.MOVE=Mută service.gui.MOVE_SUBCONTACT=M&ută subcontactul @@ -297,7 +287,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Contactul selectat este același ca și \n co service.gui.MOVE_SUBCONTACT_QUESTION=Sunteți sigur(ă) că doriți să mutați {0} în {1}? service.gui.MOVE_TO_GROUP=&Mută în grup service.gui.MOVE_CONTACT=Mută contactul -service.gui.MOVE_CONTACT_ERROR=&Contactul nu poate fi mutat service.gui.MSG_DELIVERY_FAILURE=Mesajul de mai sus nu a putut fi trimis service.gui.MSG_DELIVERY_NOT_SUPPORTED=Protocolul pe care îl utilizaţi nu permite trimiterea mesajelor în mod deconectat. Puteţi încerca să accesaţi acest contact prin intermediul altui protocol sau aşteptaţi până când el/ea se va conecta. service.gui.MSG_DELIVERY_INTERNAL_ERROR=A intervenit o eroare internă. Cel mai posibil că aceasta este o dificultate neprevăzută. Vă rugăm să o raportaţi aici: http://www.sip-communicator.org/index.php/Development/BugsAndIssues. @@ -308,7 +297,6 @@ service.gui.MSG_NOT_POSSIBLE=Discuții cu acest contact nu sunt posibile (nu est service.gui.MSG_RECEIVED={0} a scris service.gui.MSG_SEND_CONNECTION_PROBLEM=Trebuie să fiți conectat(ă) pentru a putea trimite mesaje. service.gui.MULTIPLE_LOGINS=Sunteți autentificat(ă) de mai multe ori cu același cont. Următorul cont: Nume utilizator: {0}, Nume server: {1} este la moment deconectat. -service.gui.MUTE=Mut service.gui.NAME=Nume service.gui.NETWORK=Rețea service.gui.NETWORK_FAILURE=Eroare de rețea @@ -317,6 +305,7 @@ service.gui.NEW_ACCOUNT=Adaugă un &cont nou service.gui.NEW_MESSAGE=Mesaj nou service.gui.NEW_NAME=Nume nou service.gui.NEW_STATUS_MESSAGE=Mesaj nou de statut +service.gui.NICKNAME=Porecla: service.gui.NO=Nu service.gui.NONE=Nimic service.gui.NO_CAMERA_AVAILABLE=Nicio cameră video disponibilă @@ -331,7 +320,6 @@ service.gui.NON_EXISTING_USER_ID=Serverul {0} nu recunoaște identificatorul uti service.gui.SD_QUALITY=Calitate standard service.gui.OFFLINE=Deconectat(ă) service.gui.OK=&OK -service.gui.OLDER_CALLS=Apeluri anterioare service.gui.ONLINE=Conectat(ă) service.gui.OPEN=Deschide service.gui.OPEN_FILE_FROM_IMAGE=Apăsați dublu-click pentru a deschide fișierul. @@ -339,8 +327,11 @@ service.gui.OPEN_FOLDER=Deschide mapa service.gui.OPEN_IN_BROWSER=Deschide în &navigator service.gui.OPTIONS=Setări service.gui.OR=sau -service.gui.OR_ENTER_PHONE_NUMBER=Sau introduceți număr de telefon aici... service.gui.ORGANIZATION=Organizaţia: +service.gui.chat.role.ADMINISTRATOR=administrator +service.gui.chat.role.MODERATOR=moderator +service.gui.chat.role.MEMBER=membru +service.gui.chat.role.SILENT_MEMBER=membru tăcut service.gui.OWNER=proprietarul conferinței service.gui.PASSWORD=Parola service.gui.PASSWORD_CHANGE_FAILURE=Schimbarea parolei a eşuat @@ -355,7 +346,6 @@ service.gui.PRESENCE=Prezența service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' pentru sugestii service.gui.PRESS_FOR_CALL_INFO=Apasă pentru infoormații despre apel service.gui.PREVIOUS=Anterior -service.gui.PREVIOUS_TOOLTIP=Răsfoiește conversațiile anterioare service.gui.PRINT=&Imprimă service.gui.PROACTIVE_NOTIFICATION=scrie un mesaj service.gui.PROBLEMS_ENCOUNTERED=Probleme întâmpinate @@ -368,7 +358,6 @@ service.gui.REASON=Motiv service.gui.RECONNECTION_LIMIT_EXCEEDED=Ați fost deconectat(ă) și reconectat(ă) la server prea rapid. Următorul cont : Nume utilizator: {0}, Nume server: {1} este blocat la moment și este nevoie să așteptați un pic înainte de a încerca să vă reconectați. service.gui.RE_REQUEST_AUTHORIZATION=&Cerere de autorizare service.gui.REJECT=&Respinge -service.gui.REMIND_ME_LATER=Amintește-mi mai târziu service.gui.REMEMBER_PASSWORD=Reține parola service.gui.REMOVE=&Șterge service.gui.REMOVE_ACCOUNT=&Șterge contul @@ -391,26 +380,17 @@ service.gui.REVOKE_ADMIN=Recheamă statutul de administrator service.gui.REVOKE_MODERATOR=Recheamă statutul de moderator service.gui.REVOKE_MEMBERSHIP=Recheamă statutul de membru service.gui.REVOKE_VOICE=Recheamă dreptul la voce -service.gui.ROOT_GROUP=Grupul de bază service.gui.SAVE=&Salvează -service.gui.SAVE_AS_DEFAULT=Salvează ca implicit service.gui.SEARCH=&Caută service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Apăsați butonul de mai jos pentru afișarea tuturor conferințelor existente pe serverul selectat. Alegeți apoi una la care doriți să vă înscrieți și apăsați butonul de înscriere. service.gui.SECURITY=Securitatea -service.gui.SELECT_ACCOUNT=Selectați contul service.gui.SELECT_COLOR=Selectați culoarea service.gui.SELECT_GROUP=Selectați grupul -service.gui.SELECT_GROUP_WIZARD_MSG=Lista de mai jos conține toate grupurile din lista de contacte. Selectați-l pe acela în care doriți să adăugați noul contact. service.gui.SELECT_NO_GROUP=Nici un grup -service.gui.SELECT_GROUP_WIZARD=Specificați grupul service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Lista de mai jos conține toate conturile ce permit participarea la conferințe. Selectați-l pe acela pe care doriți să-l utilizați la crearea propriei conferințe. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Lista de mai jos conține toate conturile înregistrate. Selectați-l pe acela pe care doriți să-l utilizați în conversațiile cu noul contact. -service.gui.SELECT_PROVIDERS_WIZARD=Selectați contul service.gui.SEND=&Trimite service.gui.SEND_FILE=Trimite &fișier -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Nu există informații despre acest contact. service.gui.SEND_MESSAGE=&Trimite un mesaj -service.gui.SEND_AS_SMS=Trimite ca SMS service.gui.SEND_SMS=T&rimite SMS service.gui.SEND_SMS_DETAILS=Nu uitați că dvs trebuie să introduceți numărul în formatul internațional, de ex. începând cu +44 pentru Marea Britanie, +447777000000 service.gui.SEND_SMS_NOT_SUPPORTED=Protocolul selectat nu suportă trimiterea de mesaje SMS. @@ -439,7 +419,6 @@ service.gui.STATUS_MESSAGE_INFO=În câmpul de mai jos puteți specifica noul me service.gui.STREET=Stradă service.gui.SUBJECT=Subiectul service.gui.SUMMARY=Sumarul -service.gui.TODAY=Astăzi service.gui.TOOLS=&Unelte service.gui.TRANSFER=Trans&feră service.gui.TO=&Spre: @@ -448,7 +427,6 @@ service.gui.TRANSFER_CALL_TITLE=Transferați apelul service.gui.TRANSFER_CALL_TO=Transferați la: service.gui.TRANSPARENCY_NOT_ENABLED=Transparența nu este suportată de configurația dvs curentă. service.gui.TYPE_YOUR_REQUEST=Introduceți aici cererea dvs -service.gui.UNMUTE=Activează service.gui.USER_IDENTIFIER=Identificatorul utilizatorului: service.gui.USER_EXISTS_ERROR=Acest utilizator deja există în rețeaua selectată. Vă rugăm să alegeți alt(ă) utilizator sau rețea. service.gui.ACCOUNT_CREATION_FAILED=Noi am eșuat să creăm contul dvs din cauza următoarei erori: {0} @@ -457,7 +435,6 @@ service.gui.UNKNOWN_STATUS=Stare necunoscută service.gui.UNREGISTERED_MESSAGE=A eșuat conexiunea la următorul cont: Nume utilizator: {0}, Nume Server: {1}. La momentan sunteți deconectat(ă). service.gui.VIDEO_CALL=&Apel video service.gui.VIA=via -service.gui.VIA_SMS=Via SMS service.gui.VIEW=&Vizualizare service.gui.VIEW_HISTORY=Vizualizează &istoria service.gui.VIEW_SMILEYS=Vizualizează &smilе-urile @@ -471,9 +448,6 @@ service.gui.VOICEMAIL_TOOLTIP=Mesaje vocale pentru: service.gui.VOLUME_CONTROL_TOOL_TIP=Ajustează volum service.gui.WARNING=Avertisment service.gui.YES=Da -service.gui.YESTERDAY=Ieri -service.gui.EXISTING_ACCOUNT_ERROR=Contul introdus de dvs este deja instalat. -service.gui.NEW_MAIL=Dvs aveți un mesaj electronic nou!
    De la: {0} {1}
    Subiect: {2}
    {3}; service.gui.NEW_GMAIL_HEADER=Dvs ați recepționat un nou mesaj electronic în cutia dvs {0}:
    service.gui.NEW_GMAIL_MANY_HEADER=Dvs ați recepționat {2} mesaje electronice noi în cutia dvs {0}:
    service.gui.NEW_GMAIL_FOOTER=o discuție necitită în plus în cutia dvs.
    @@ -494,7 +468,6 @@ service.gui.SECURITY_WARNING=Avertisment de securitate service.gui.SECURITY_ERROR=Eroare de securitate service.gui.SPEED=Viteza: service.gui.SILENT_MEMBER=membru tăcut -service.gui.UPDATE=Actualizează service.gui.MOBILE_PHONE=Mobil service.gui.VIDEO_PHONE=Video service.gui.WORK_PHONE=Serviciu @@ -523,12 +496,16 @@ service.gui.callinfo.AUDIO_INFO=Info audio service.gui.callinfo.MEDIA_STREAM_RTP=ZRTP service.gui.callinfo.MEDIA_STREAM_SRTP=ZRTP +#enum values from IceProcessingState + + service.gui.ALWAYS_TRUST=Încredere permanentă acestui certificat service.gui.CERT_DIALOG_TITLE=Verifică certificatul service.gui.CERT_DIALOG_DESCRIPTION_TXT={0} nu putem verifica identitatea serverului când ne conectăm
    la {1}:{2}.

    Certificatul nu este de încredere, ceea ce înseamnă că identitatea serverului nu poate
    fi automatic verificată. Doriţi să continuăm conectarea?

    Pentru mai multă informaţie apăsaţi "Vizualizaţi certificatul". service.gui.CERT_DIALOG_DESCRIPTION_TXT_NOHOST={0} nu putem verifica identitatea serverului când ne conectăm
    la {1}:{2}.

    Certificatul nu este de încredere, ceea ce înseamnă că identitatea serverului nu poate
    fi automatic verificată. Doriţi să continuăm conectarea?

    Pentru mai multă informaţie apăsaţi "Vizualizaţi certificatul". -service.gui.CERT_DIALOG_CLIENT_DESCRIPTION_TXT={0} nu putem verifica identitatea serverului când ne conectăm
    la {1}:{2}.

    Certificatul nu este de încredere, ceea ce înseamnă că identitatea serverului nu poate
    fi automatic verificată. Doriţi să continuăm conectarea?

    Pentru mai multă informaţie apăsaţi "Vizualizaţi certificatul". service.gui.CERT_DIALOG_PEER_DESCRIPTION_TXT={0} nu putem verifica identitatea serverului când ne conectăm
    la {1}:{2}.

    Certificatul nu este de încredere, ceea ce înseamnă că identitatea serverului nu poate
    fi automatic verificată. Doriţi să continuăm conectarea?

    Pentru mai multă informaţie apăsaţi "Vizualizaţi certificatul". + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=Nume general: service.gui.CERT_INFO_O=Organizația: service.gui.CERT_INFO_C=Denumirea țării: @@ -537,24 +514,21 @@ service.gui.CERT_INFO_L=Denumirea localității: service.gui.CERT_INFO_OU=Unitatea organizațională: service.gui.CERT_INFO_ISSUED_ON=Eliberat pe: service.gui.CERT_INFO_EXPIRES_ON=Expiră pe: +service.gui.CERT_INFO_FINGERPRINTS=Amprenta service.gui.CERT_INFO_SER_NUM=Numărul de serie: service.gui.CERT_INFO_VER=Versiunea: service.gui.CERT_INFO_SIGN_ALG=Algoritmul semnăturii: service.gui.CERT_INFO_ALG=Algoritmul: service.gui.CERT_INFO_PUB_KEY=Cheia publică: -service.gui.CERT_INFO_KEY_BYTES_PRINT={0} octeți: {1} service.gui.CERT_INFO_KEY_BITS_PRINT={0} biți service.gui.CERT_INFO_EXP=Exponentul: service.gui.CERT_INFO_KEY_SIZE=Mărimea cheii: service.gui.CERT_INFO_SIGN=Semnătura: -service.gui.CONTINUE=Continuă service.gui.SHOW_CERT=Vizualizează certificatul service.gui.HIDE_CERT=Ascunde certificatul service.gui.AUTO_ANSWER_VIDEO=Video -service.gui.security.NO_VIDEO=Video HD -service.gui.security.COMPARE_WITH_PARTNER=Comparați cu partenerul și apăsați lăcata pentru a confirma. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Comparaţi cu partenerul: {0} @@ -568,18 +542,12 @@ service.gui.avatar.imagepicker.CLICK=Apasă și Zâmbește service.gui.avatar.imagepicker.IMAGE_FILES=Fișierele imaginilor service.gui.avatar.imagepicker.IMAGE_PICKER=Poză service.gui.avatar.imagepicker.IMAGE_SIZE=Dimensiunile imaginii -service.gui.avatar.imagepicker.INITIALIZING=Inițializare service.gui.avatar.imagepicker.RESET=Resetează service.gui.avatar.imagepicker.SET=Setează service.gui.avatar.imagepicker.TAKE_PHOTO=Ia-o fotografie -service.gui.avatar.imagepicker.WEBCAM_ERROR=Eroarea webcamerei -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ # systray @@ -598,9 +566,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=selectați rețea # LDAP impl.ldap.GENERAL=General -impl.ldap.NEW=Nou impl.ldap.EDIT=&Editare -impl.ldap.REMOVE=Şterge impl.ldap.ENABLED=Activează impl.ldap.SERVER_HOSTNAME=Nume gazdă: impl.ldap.AUTH_NONE=Nimic @@ -610,12 +576,14 @@ impl.ldap.SERVER_PORT=Portul impl.ldap.PASSWORD=Parola impl.ldap.MAIL_FIELD_EXAMPLE=Poşta electronică: +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts -impl.googlecontacts.NEW=Nou impl.googlecontacts.EDIT=&Editare -impl.googlecontacts.REMOVE=Şterge impl.googlecontacts.ENABLED=Activează impl.googlecontacts.SAVE=&Salvează impl.googlecontacts.CANCEL=Renunță @@ -639,9 +607,6 @@ plugin.accountinfo.COUNTRY=Țară plugin.accountinfo.EMAIL=Email: plugin.accountinfo.PHONE=Numărul de telefon: plugin.accountinfo.JOB_TITLE=Funcție -plugin.accountinfo.USER_PICTURES=Imagini de utilizator -plugin.accountinfo.CHANGE=Modifică -plugin.accountinfo.ONLY_MESSAGE=Numai mesaje # connection info @@ -659,49 +624,12 @@ plugin.aimaccregwizz.USERNAME=Pseudonimul AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=Pseudonimul și parola plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Înregistrează un cont nou plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=În cazul în care nu aveți un cont AIM apăsați acest buton pentru a crea unul nou. -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Rescrie setările standarde ale serverului # branding plugin.branding.ABOUT_WINDOW_TITLE=Despre {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Mesagerie Instantanee -plugin.branding.LOADING=Încărcăm plugin.branding.ABOUT_MENU_ENTRY=&Despre -plugin.branding.WELCOME_MESSAGE=
    {1} la moment curent se află în activă dezvoltare. Versiunea pe care o folosiți este una experimentală și POATE SĂ NU lucreze cum se așteaptă. Vă rugăm să vă referiți la {2} pentru mai multă informație.
    -plugin.branding.COPYRIGHT=
    (c)2003-2009 Copyright sip-communicator.org. Toate drepturile sunt rezervate. Vizitaţi http://sip-communicator.org.
    -plugin.branding.LICENSE=
    SIP Communicator este distribuit sub termenii LGPL (http://www.gnu.org).
    - -# Dict protocol -service.protocol.DICTIONARIES=Dicționare -plugin.dictaccregwizz.ANY_DICTIONARY=Orice dicționar -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=Orice dicționar din {0} -plugin.dictaccregwizz.FIRST_MATCH=Prima coincidență -plugin.dictaccregwizz.NO_MATCH=Nici o coincidență -plugin.dictaccregwizz.MATCH_RESULT=Nici o definiție pentru "{0}" nu a fost găsită, posibil că aveți în vedere:\n -plugin.dictaccregwizz.INVALID_DATABASE=Dicționarul curent "{0}" nu mai există pe serverul dat. -plugin.dictaccregwizz.INVALID_STRATEGY=Strategia curentă nu este disponibilă pe server. -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=Protocolul de serviciu Dict -plugin.dictaccregwizz.HOST=Gazdă -plugin.dictaccregwizz.SERVER_INFO=Informații despre server -plugin.dictaccregwizz.STRATEGY_SELECTION=Selectarea strategiei -plugin.dictaccregwizz.STRATEGY_LIST=Lista strategiilor: -plugin.dictaccregwizz.SEARCH_STRATEGIES=Caută strategii -plugin.dictaccregwizz.STRATEGY_DESCRIPTION=Strategia este folosită pentru a căuta cuvinte asemănătoare în caz dacă traducerea nu a fost găsită, mulțumesc diferitelor abordări. Spre exemplu, strategia Prefix va căuta cuvinte care încep asemenea cuvântului pe care îl dorim să traducem. -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=Informație despre contul Dict -plugin.dictaccregwizz.FIRST_ACCOUNT=Acest asistent va crea pentru dvs primul vostru cont Dict pentru dict.org.\n\nDvs puteți adăuga un dicționar nou recurgând la Asistent de înregistrare a contului. Completați câmpul Gazdă cu dicționarul pe care l-ați dori să adăugați. -plugin.dictaccregwizz.THREAD_CONNECT=Încercăm să ne conectăm la server -plugin.dictaccregwizz.THREAD_CONNECT_FAILED=Încercare de conexiune a eșuat, acesta nu este server dict sau serverul este deconectat -plugin.dictaccregwizz.RETRIEVING_STRATEGIES=Recepționăm strategiile -plugin.dictaccregwizz.NO_STRATEGIES_FOUND=Nici o strategie nu a fost găsită pe server -plugin.dictaccregwizz.POPULATE_LIST=Completăm lista -plugin.dictaccregwizz.CLOSING_CONNECTION=Închidem conexiunea - -# facebookaccregwizz -plugin.facebookaccregwizz.DESCRIPTION=
    Pentru a folosi Facebook discuții dvs trebuie să creați un "Nume utilizator"
    din pagina dvs "Setările contului" pe Facebook.


    Notă: Când creați numele vostru de utilizator, dvs trebuie să vă deconectați de la web-pagină
    și posibil să fie nevoie de timp anumit înainte ca dvs să aveți posibilitatea de a vă conecta cu numele vostru nou de utilizator!
    -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=Protocolul de discuții Facebook -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=Nume utilizator: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=Nume utilizator și Parola + # generalconfig plugin.generalconfig.AUTO_START=Porneşte automat {0} când calculatorul restartează @@ -711,9 +639,6 @@ plugin.generalconfig.SHOW_HISTORY=Vizualizează plugin.generalconfig.HISTORY_SIZE=mesaje recente în discuțiile noi plugin.generalconfig.SEND_MESSAGES_WITH=Trimite mesaje cu: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Adu fereastra cu discuții în față -plugin.generalconfig.ERROR_PERMISSION=Dvs nu aveți privilegii necesare pentru a elimina pornirea automatică -plugin.generalconfig.TRANSPARENCY=Transparența -plugin.generalconfig.ENABLE_TRANSPARENCY=Activează transparența plugin.generalconfig.DEFAULT_LANGUAGE=Limbajul interfeței plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Modificările dvs vor acționa după următoare restartare. plugin.generalconfig.SIP_CLIENT_PORT=Portul clientului SIP @@ -741,6 +666,7 @@ plugin.icqaccregwizz.REGISTER_NEW_ACCOUNT=Înregistrează un cont nou plugin.ircaccregwizz.PROTOCOL_NAME=IRC plugin.ircaccregwizz.PROTOCOL_DESCRIPTION=Protocolul IRC. plugin.ircaccregwizz.USERNAME_AND_PASSWORD=UIN și parola +plugin.ircaccregwizz.USERNAME=Porecla: plugin.ircaccregwizz.INFO_PASSWORD=Majoritatea serverelor IRC nu necesită parola. plugin.ircaccregwizz.AUTO_NICK_CHANGE=Schimbă porecla automatic dacă este deja utilizată plugin.ircaccregwizz.USE_DEFAULT_PORT=Folosește portul standard @@ -751,7 +677,6 @@ plugin.ircaccregwizz.IRC_SERVER=Serverul # jabber accregwizz plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Protocolul SIP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmați parola -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=Identificatorul și Parola plugin.jabberaccregwizz.CSERVER=Serverul plugin.jabberaccregwizz.SERVER=Serverul de conexiune plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Activează păstrarea în "activ" @@ -765,10 +690,7 @@ plugin.jabberaccregwizz.SERVER_COLUMN=Serverul plugin.jabberaccregwizz.COMMENT_COLUMN=Comentariul plugin.jabberaccregwizz.RESOURCE=Resursa plugin.jabberaccregwizz.PRIORITY=Prioritatea -plugin.jabberaccregwizz.XMPP_ERROR=Eroarea XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Eroarea XMPP necunoscută. Verificați dacă numele serverului este corect. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Rescrie setările standard a serverului -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Setările avansate plugin.jabberaccregwizz.USE_ICE=Folosește ICE plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Detectează serverele STUN/TURN automatic plugin.jabberaccregwizz.SUPPORT_TURN=Suportă TURN @@ -781,31 +703,14 @@ plugin.jabberaccregwizz.NO_STUN_USERNAME=Vă rugăm să introduceți o adresă v plugin.jabberaccregwizz.STUN_ALREADY_EXIST=Serverul STUN specificat deja există. plugin.jabberaccregwizz.JID_ADDRESS=Adresa IP plugin.jabberaccregwizz.EXISTING_ACCOUNT=Cont SIP existent -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Confirmaţi parola plugin.jabberaccregwizz.ENCODINGS=&Codificări: plugin.jabberaccregwizz.AUDIO=Audio plugin.jabberaccregwizz.VIDEO=Video plugin.jabberaccregwizz.RESET=Resetează -# mailbox -plugin.mailbox.OUTGOING=Mesajul de trimis: -plugin.mailbox.INCOMING=Mesajele de intrare: -plugin.mailbox.WAIT_TIME=Întârziere până apelul este trimis la poșta vocală -plugin.mailbox.MAX_MESSAGE_TIME=Durata maximă a mesajului de intrare -plugin.mailbox.CONFIRM=Confirmă -plugin.mailbox.DEFAULTS=Standarde -plugin.mailbox.MAILBOX=Cutia poștală - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=Protocol pentru conectare și discutare în serviciul MSN. -plugin.msnaccregwizz.USERNAME=Poșta electronică: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=Identificatorul și Parola - # plugin manager plugin.pluginmanager.INSTALL=Instalează plugin.pluginmanager.UNINSTALL=Dezinstalează -plugin.pluginmanager.UPDATE=Actualizează plugin.pluginmanager.PLUGINS=Plug-in-urile plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Selectați fișier @@ -829,7 +734,6 @@ plugin.sipaccregwizz.SERVER_PORT=Portul serverului plugin.sipaccregwizz.PROXY=Proxy plugin.sipaccregwizz.PROXY_PORT=Portul proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=Transportul preferat -plugin.sipaccregwizz.ADVANCED_OPTIONS=Setări avansate plugin.sipaccregwizz.PROXY_OPTIONS=Opțiuni proxy plugin.sipaccregwizz.PROXY_AUTO=Configurare automată proxy plugin.sipaccregwizz.ENABLE_PRESENCE=Activează prezența (SIMPLE) @@ -841,8 +745,6 @@ plugin.sipaccregwizz.KEEP_ALIVE=Păstrează "activ" plugin.sipaccregwizz.KEEP_ALIVE_METHOD=Metoda de păstrare în "activ" plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL=Intervalul de păstrare în "activ" plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=Între 1 și 3600 secunde -plugin.sipaccregwizz.REGISTER=REGISTER -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Rescrie setările standarde a serverului plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Activează suportul apelurilor criptate plugin.sipaccregwizz.AUTH_NAME=Nume de autorizare plugin.sipaccregwizz.DISPLAY_NAME=Nume de afişare @@ -853,6 +755,7 @@ plugin.sipaccregwizz.CLIST_TYPE=Tipul plugin.sipaccregwizz.XCAP_USE_SIP_CREDENTIALS=Folosește acreditive SIP plugin.sipaccregwizz.XCAP_USER=Utilizatorul plugin.sipaccregwizz.XCAP_PASSWORD=Parola +#used from SecurityPanel # skin manager plugin.skinmanager.SKINS=Skinuri @@ -860,15 +763,6 @@ plugin.skinmanager.DEFAULT_SKIN=Skin principal plugin.skinmanager.ADD_NEW_SKIN=Adaugă skin... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=Skinul principal al aplicației. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=Protocolul pentru conectare la calculatoare prin SSH. -plugin.sshaccregwizz.USERNAME=Identificatorul contului: -plugin.sshaccregwizz.IDENTITY_FILE=Fișierul de identitate: -plugin.sshaccregwizz.KNOWN_HOSTS=Gazde cunoscute: -plugin.sshaccregwizz.OPTIONAL=Opțional -plugin.sshaccregwizz.ACCOUNT_DETAILS=Detaliile contului - # status update plugin.autoaway.AUTO_STATUS=Absent automatic plugin.autoaway.ENABLE_CHANGE_STATUS=Schimbă statutul în timpul absenței @@ -913,21 +807,6 @@ plugin.whiteboard.DESELECT=Deselectează plugin.whiteboard.DELETE=Șterge plugin.whiteboard.PROPERTIES=Proprietăți -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=Protocol pentru conectare şi discuţii pe serviciul Yahoo. -plugin.yahooaccregwizz.USERNAME=Nume utilizator: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=Identificatorul și Parola - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=Protocolul de serviciu Zeroconf (Bonjour). -plugin.zeroaccregwizz.FIRST_NAME=Nume: -plugin.zeroaccregwizz.LAST_NAME=Prenume: -plugin.zeroaccregwizz.EMAIL=Poșta electronică: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=Să țin minte contactele Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=Identificatorul și Parola -plugin.zeroaccregwizz.USERID=Identificatorul utilizatorului - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=Protocolul Google Talk plugin.googletalkaccregwizz.USERNAME=Nume utilizator Google Talk @@ -940,25 +819,18 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=iptel.org, portalul IP telecomunica plugin.iptelaccregwizz.USERNAME=Nume utilizator plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=Subscrie la iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=VoIP și discuții +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=Nume de utilizator plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Repetați parola plugin.sip2sipaccregwizz.EMAIL=Poșta electronică -plugin.sip2sipaccregwizz.NEW_ACCOUNT_TITLE=Pentru ajutor despre acest serviciu vizitați
    http://wiki.sip2sip.info plugin.sip2sipaccregwizz.EMAIL_NOTE=Poșta electronică se folosește pentru a trimite mesaje vocale,
    notificări despre apeluri ratate și pentru a recupera parola pierdută -plugin.sip2sipaccregwizz.INFO_NOTE=Pentru ajutor despre acest serviciu vizitați http://wiki.sip2sip.info -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=Cont sip2sip.info existent -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Creează un cont sip2sip.info gratis - -# ippi accregwizz plugin.ippiaccregwizz.NEW_ACCOUNT_TITLE=Pentru ajutor despre acest serviciu vizitați
    http://ippi.fr plugin.ippiaccregwizz.INFO_NOTE=Pentru ajutor despre acest serviciu vizitaţi http://wiki.sip2sip.info plugin.ippiaccregwizz.EXISTING_ACCOUNT=Cont SIP existent plugin.ippiaccregwizz.CREATE_ACCOUNT=Creează un cont SIP gratis # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Închide fereastra de discuții plugin.keybindings.CHAT_COPY=Copiază plugin.keybindings.CHAT_CUT=Taie @@ -974,9 +846,11 @@ plugin.keybindings.OPEN_HISTORY=Vizualizează istoria plugin.keybindings.OPEN_SMILIES=Vizualizează smile-urile plugin.keybindings.globalchooser.SHORTCUT_NAME=Nume plugin.keybindings.PLUGIN_NAME=Taste pentru acces rapid +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Discuţie # Notification Configuration Form +plugin.notificationconfig.ENABLE_NOTIF=Activează plugin.notificationconfig.DESCRIPTION=Descriere plugin.notificationconfig.TURN_ON_ALL=Activează toate plugin.notificationconfig.TURN_OFF_ALL=Dezactivează toate @@ -988,6 +862,7 @@ plugin.notificationconfig.EXEC_PROG=Îndeplinește o aplicație: plugin.notificationconfig.DISPLAY_POPUP=Vizualizează un mesaj în pop-up fereastră plugin.notificationconfig.POPUP_NOTIF_HANDLER=Tipul notificărilor pop-up: plugin.notificationconfig.tableheader.EXECUTE=Îndeplineşte o aplicaţie: +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Apel primit plugin.notificationconfig.event.IncomingFile=Apel primit plugin.notificationconfig.event.IncomingMessage=Mesajele de intrare: @@ -1040,6 +915,7 @@ impl.media.configform.VIDEO_RESET=Restabileşte standarde impl.neomedia.configform.AUDIO=Audio impl.neomedia.configform.VIDEO=Video +#in JNIEncoder impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=ZRTP # The callrecordingconfig plugin was never really committed into trunk and its @@ -1063,7 +939,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=Parola curentă: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Introduceți noua parolă: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Reintroduceţi parola: plugin.securityconfig.masterpassword.MP_TITLE=Parola principală -plugin.securityconfig.masterpassword.MP_NOT_SET=(nu este setat) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=Dvs nu ați introdus Parola principală curentă corect. Vă rugăm să încercați din nou. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=Parola principală nu este corectă! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=Schimbarea parolei a eșuat @@ -1078,7 +953,6 @@ plugin.securityconfig.masterpassword.COL_NAME=Nume plugin.securityconfig.masterpassword.COL_PASSWORD=Parola plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(necunoscut) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(nu pot decripta) -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Şterge plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Șterge toate plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Sunteți sigur(ă) că doriți să ștergeți toate parole? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Șterge toate parole @@ -1137,7 +1011,6 @@ plugin.globalproxy.PROXY_PORT=Portul proxy plugin.globalproxy.PROXY_USERNAME=Nume utilizator proxy plugin.globalproxy.PROXY_PASSWORD=Parola proxy plugin.globalproxy.DESCRIPTION={0} din acest moment va folosi setările proxy de mai jos pentru toate rețelele pe care dvs le conectați sau reconectați. \nSuportul proxy este la moment experimental și lucrează doar cu unele protocoale. Verificați tabela de mai jos pentru mai multe detalii: -plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    Yahoo!++--
    MSN++--
    JABBER++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT # plugin reconnect @@ -1150,6 +1023,8 @@ plugin.reconnectplugin.NETWORK_DOWN=Conectivitatea la rețea este pierdută! plugin.chatconfig.TITLE=Discuție plugin.chatconfig.replacement.TITLE=Imagine/Video: plugin.chatconfig.replacement.ENABLE_SMILEY_STATUS=Activează înlocuirea smile-urilor +plugin.chatconfig.replacement.REPLACEMENT_TITLE=Activează înlocuirea Imagine/Video +plugin.chatconfig.replacement.ENABLE_REPLACEMENT_STATUS=Activează plugin.chatconfig.replacement.REPLACEMENT_SOURCES=Surse: #provisioning plugin @@ -1173,7 +1048,6 @@ net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=&Ignoră net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=&Refuză #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=&Editare plugin.spellcheck.UNINSTALL_DICTIONARY=Dezinstalează -- cgit v1.1 From fcc6af676b880895cf19b00b88c1db3ae0eda4e9 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:16 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 14 of 1505 strings translated (3 fuzzy). --- resources/languages/resources_mk.properties | 51 +++++++++++++++-------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/resources/languages/resources_mk.properties b/resources/languages/resources_mk.properties index cd47b3d..57dff6d 100644 --- a/resources/languages/resources_mk.properties +++ b/resources/languages/resources_mk.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,23 +43,24 @@ service.gui.ACCOUNT_ME=Јас service.gui.ACCOUNT_REGISTRATION_WIZARD=Волшебник за регистрирање на сметка service.gui.ACCOUNTS=Сметки service.gui.ADD=Додај -service.gui.ADD_ACCOUNT=Додај сметка service.gui.ADD_CONTACT=Додај service.gui.ADD_CONTACT_TO=Додади контакт во service.gui.ADD_CONTACT_ERROR=Неуспешно додавање на контактот: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Грешка при додавање на контакт service.gui.ADD_CONTACT_EXIST_ERROR=Контактот {0} веќе постои во твојата контакт листа. -service.gui.ADD_CONTACT_IDENTIFIER=Во даденото поле внеси го контактот кој сакаш да го додадеш во твојата контакт листа -service.gui.ADD_CONTACT_WIZARD=Волшебник за додавање на контакт service.gui.ADD_GROUP_LOCAL_ERROR=Грешка при креирањето на група со име {0} . Проблемот се јави на локалена IO операција. service.gui.ADD_GROUP_EXIST_ERROR=Групата {0} веќе постои во твојата контакт листа. Ве молиме одберете друго име. -service.gui.ADD_SUBCONTACT=Додај service.gui.ALL_CONTACTS=Додај service.gui.CALL_CONTACT=Додај +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names # keep the following string short @@ -57,9 +69,6 @@ service.gui.CALL_CONTACT=Додај -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -68,6 +77,10 @@ service.gui.CALL_CONTACT=Додај # LDAP +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -83,9 +96,6 @@ service.gui.CALL_CONTACT=Додај # branding plugin.branding.ABOUT_MENU_ENTRY=&За програмот -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -97,20 +107,15 @@ plugin.branding.ABOUT_MENU_ENTRY=&За програмот # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -119,21 +124,18 @@ plugin.branding.ABOUT_MENU_ENTRY=&За програмот # whiteboard -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +#Enum KeybindingSet.Category # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -145,6 +147,7 @@ plugin.branding.ABOUT_MENU_ENTRY=&За програмот +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. -- cgit v1.1 From 4800a10b50b9c193567959089e539bdf1c530cb0 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:22 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 221 of 1505 strings translated (38 fuzzy). --- resources/languages/resources_lv.properties | 72 +++++++++++------------------ 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/resources/languages/resources_lv.properties b/resources/languages/resources_lv.properties index df516a6..df76ce1 100644 --- a/resources/languages/resources_lv.properties +++ b/resources/languages/resources_lv.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Es service.gui.ACCOUNT_REGISTRATION_WIZARD=Konta reģistrācijas vednis service.gui.ACCOUNTS=Konti service.gui.ADD=&Pievienot -service.gui.ADD_ACCOUNT=Pievienot kontu service.gui.ADD_CONTACT=&Pievienot kontaktu service.gui.ADD_AUTHORIZED_CONTACT=Pievienot kontaktu {0} jūsu kontaktu sarakstam service.gui.ADD_CONTACT_TO=&Pievienot kontaktu @@ -41,26 +51,20 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Kontaktu pievienošanas kļūda service.gui.ADD_CONTACT_EXIST_ERROR=Persona {0} jau eksistē jūsu kontaktu sarakstā. service.gui.ADD_CONTACT_NETWORK_ERROR=Serveris neatbildēja uz personas pievienošanas pieprasījumu ar id: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Neizdevās pievienot kontaktu ar id: {0}. Operācija netiek atbalstīta. -service.gui.ADD_CONTACT_IDENTIFIER=Lauciņā zemāk ievadiet pievienojamā kontakta identifikatoru. -service.gui.ADD_CONTACT_WIZARD=Kontakta pievienošanas vednis service.gui.ADD_CONTACT_NOT_CONNECTED=Lai pievienotu kontaktu jābūt izveidotam savienojumam. Lūdzu pieslēdzaties izvēlētajam provaiderim un mēģiniet vēl. service.gui.ADD_GROUP_LOCAL_ERROR=Neizdevās pievienot grupu ar nosaukumu: {0}. Gadijās kļūme IO operācijas laikā. service.gui.ADD_GROUP_EXIST_ERROR=Grupa {0} jau eksistē jūsu kontaktu sarakstā. Lūdzu izvēlaties citu nosaukumu. service.gui.ADD_GROUP_NET_ERROR=Neizdevās pievienot grupu ar nosaukumu: {0}. Gadijās tīkla problēma. Lūdzu pārbaudiet tīkla savienojumu un atkārtojiet darbību. service.gui.ADD_GROUP_ERROR=Neizdevās pievienot grupu ar nosaukumu: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Jānorāda grupas nosaukums -service.gui.ADD_GROUP=Izveidot grupu -service.gui.ADD_SUBCONTACT=&Pievienot apakškontaktu service.gui.ADMINISTRATOR=administrators service.gui.ADVANCED=&Papildus -service.gui.ALL=&Visi service.gui.ALL_CONTACTS=&Visi kontakti service.gui.APPLY=&Pielietot service.gui.ARE_NOW=Jūs esat {0} service.gui.AT=uz service.gui.AUTHORIZE=&Autorizēt service.gui.AUTHENTICATION_FAILED=Autentifikācija neizdevās {0}. Ievadītā parole nebija derīga. -service.gui.AUTHENTICATION_REQUESTED=Pieprasīta autentifikācija service.gui.AUTHENTICATION_REQUESTED_SERVER=Serveris {0} pieprasīja autentifikāciju. service.gui.AUTHENTICATION_WINDOW_TITLE={0} autentifikācija service.gui.AUTHORIZATION_REQUESTED=Pieprasīta autorizācija @@ -103,13 +107,11 @@ service.gui.CHAT_ROOM_USER_KICKED=izmests no {0} service.gui.CHAT_ROOM_USER_QUIT={0} pameta service.gui.CHAT_ROOM_NAME=Tērzēšanas istabas nosaukums service.gui.ROOM_NAME=Tērzēšanas istaba -service.gui.AUTOJOIN=Autopievienoties service.gui.CHANGE_PASSWORD=Mainīt paroli service.gui.CHAT_ROOM_NAME_INFO=Lauciņā zemāk ievadiet izveidojamās tērzēšanas istabas nosaukumu. service.gui.CHAT_ROOM_NOT_EXIST=Serverī {1} nav atrasta Istaba {0}. Lūdzu pārbaudiet vai ievadījāt istabas nosaukumu pareizi. service.gui.CHAT_ROOM_NOT_CONNECTED=Jums jābūt pieslēgtam, lai pievienotos {0} tērzēšanas istabai. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Lai pamestu tērzēšanas istabu jums jābūt pieslēgtam. -service.gui.CHAT_ROOM_NOT_JOINED=Jums jābūt pieslēgtam tērzēšanas istabai, lai veiktu kādas operācijas tajā. service.gui.CHAT_ROOM_OPTIONS=Tērzēšanas istabas opcijas service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Lai pievienotos tērzēšanas istabai {0} ir nepieciešama reģistrācija. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Tērzēšanas istaba {0} pieprasa paroli. @@ -122,22 +124,18 @@ service.gui.CLEAR=Attīrīt service.gui.CLOSE=Ai&zvērt service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Jūs saņēmāt jaunu ziņu 2 sekundes atpakaļ. Vai tiešām vēlaties aizvērt šo tērzēšanas logu? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Ir aktīvas failu piegādes. Vai piekrītat tās atcelt? -service.gui.CONFIRM=Apstiprināt service.gui.CONNECTED_STATUS=Savienots service.gui.CONNECTING=Savienojos... service.gui.CONNECTING_STATUS=Savienojas service.gui.CONNECTING_EARLY_MEDIA_STATUS=Savienojas* service.gui.CONNECTION=Savienojums -service.gui.CONNECTION_FAILED_MSG=Neizdevās savienoties ar sekojošu kontu: Lietotājs: {0}, Serveris: {1}. Lūdzu pārbaudiet tīkla savienojumu vai arī lūdziet palīdzību tīkla administratoram. service.gui.CONNECTION_EXPIRED_MSG=Patreiz esiet atslēgts no servera {0}. service.gui.CONTACT_NAME=ID vai Numurs -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Izvēlētais kontakts {0} neatbalsta zvanīšanu. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Izvēlētais kontakts {0} neatbalsta tērzēšanas konferences saraksti. service.gui.CONTACT_PAUSED_TYPING={0} pārstāja rakstīt ziņu service.gui.CONTACT_TYPING={0} raksta ziņu service.gui.CONTACT_TYPING_SEND_FAILED=uh-oh... mēs nevarējām nosakaidrot kad jūs rakstījāt {0} service.gui.CONTACT_INFO=&Kontakta info -service.gui.CONTACTLIST=Kontaktu lists service.gui.CONTACTS=Kontakti service.gui.COPY=&Kopēt service.gui.COPY_LINK=Kopēt &saiti @@ -147,15 +145,12 @@ service.gui.CREATE_CHAT_ROOM=&Izveidot tērzēšanas istabu... service.gui.CREATE_CHAT_ROOM_ERROR=Neizdevās izveidot {0} tērzēšanas istabu. service.gui.CREATE_CHAT_ROOM_WIZARD=Izveidot tērzēšanas istabas vedni service.gui.CREATE_CONFERENCE_CALL=&Izveidot konfrences izsaukumu... -service.gui.CREATE_CONFERENCE_CHAT=&Veidot konferences tērzēšanu service.gui.CREATE_GROUP=&Izveidot grupu... service.gui.CREATE_GROUP_NAME=Lauciņā zemāk norādiet veidojamās grupas nosaukumu. -service.gui.CREATE_FIRST_GROUP_WIZARD=Jūsu kontaktos nav nevienas grupas. Lūdzu vispirms izveidojiet grupu (Faili/Izveidot grupu). service.gui.CREATE_VIDEO_BRIDGE=Izveidot &video tiltu... service.gui.CREATE_VIDEO_BRIDGE_MENU=Izveidot &video tiltu... service.gui.CONTACT_INFO_NOT_SUPPORTED=Šis kontakts neatbalsta web kontaktu info service.gui.CUT=&Izgriezt -service.gui.DATE=Datums service.gui.DELETE=Dzēst service.gui.DENY=&Aizliegt service.gui.DESKTOP_SHARING_WARNING=Vai vēlaties sākt ekrāna kopīgošanu?
    Ja noklikšķināsiet OK, citi cilvēki redzēs jūsu ekrānu. @@ -165,7 +160,6 @@ service.gui.DISCONNECTED_STATUS=Atvienots service.gui.DND_STATUS=Lūdzu netraucēt service.gui.DO_NOT_ASK_AGAIN=Vairs nejautāt service.gui.DO_NOT_SHOW_AGAIN=Nerādīt vairāk šo paziņojumu. -service.gui.DOWNLOAD_NOW=&Lejuplādēt tagad service.gui.DRAG_FOR_SHARING=Velciet visu ko vēlaties kopīgot... service.gui.DURATION=ilgums service.gui.EDIT=&Labot @@ -180,7 +174,6 @@ service.gui.ERROR_WAS=Kļūda: {0} service.gui.ESTIMATED_TIME=Novērtētais laiks: service.gui.EVENTS=Notikumi service.gui.EXIT=I&ziet -service.gui.EXTENDED_CRITERIA=Paplašināt kritēriju service.gui.GENERAL_ERROR=Vispārīga kļūda service.gui.GROUP_NAME=Grupas nosaukums service.gui.FAILED_STATUS=Zvans neizdevās @@ -234,7 +227,6 @@ service.gui.HIDE_OFFLINE_CONTACTS=Paslēpt kontaktus bezsaistē service.gui.HIDE_MAIN_WINDOW=
    Klikšķinot X loga pogu, neizbeigs aplikācijas darbu, bet tikai
    to paslēps. Ja vēlaties beigt aplikācijas darbu izvēlaties Fails/Iziet
    service.gui.HISTORY=&Vēsture service.gui.HISTORY_CONTACT=Vēsture - {0} -service.gui.HOUR=Stunda service.gui.ICE=ICE service.gui.IDENTIFIER=Identifikators service.gui.IGNORE=&Ignorēt @@ -253,11 +245,8 @@ service.gui.INVITE_CONTACT_TO_CALL=Uzaicināt kontaktus zvanam service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=Uzaicināt kontaktus video tiltam service.gui.INVITE_REASON=Uzaicinājuma iemesls service.gui.IS_NOW={0} patreiz ir {1} -service.gui.JITSI_WARNING=SIP Communicator nesen tika pārsaukts par Jitsi.
    Ja vēlaties, lai jūsu versija būtu atjaunināta, lejuplādējiet Jitsi tagad.

    Mēs ļoti atvainojamies par sagādātajām neērtībām.

    Jitsi izstrādātāju komanda -service.gui.JITSI_WARNING_TITLE=SIP Communicator pārtop par Jitsi service.gui.JOIN=&Pievienoties service.gui.JOIN_AS=P&ievienoties kā -service.gui.CLOSE_CHAT_ROOM_DIALOG=A&izvērt service.gui.JOIN_CHAT_ROOM=&Pievienoties tērzēšanas istabai... service.gui.JOIN_CHAT_ROOM_TITLE=Pievienoties tērzēšanas istabai service.gui.JOIN_CHAT_ROOM_NAME=Lūdzu ievadiet tērzēšanas istabas nosaukumu, kurai vēlaties pievienoties. @@ -272,9 +261,13 @@ service.gui.SHOW_OFFLINE_CONTACTS=Paslēpt kontaktus bezsaistē +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names -service.gui.security.NO_VIDEO=HD video # keep the following string short # service.gui.avatar.imagepicker @@ -282,9 +275,6 @@ service.gui.avatar.imagepicker.CANCEL=&Atlikt -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -295,6 +285,10 @@ service.gui.avatar.imagepicker.CANCEL=&Atlikt impl.ldap.EDIT=&Labot impl.ldap.CANCEL=&Atlikt +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -312,9 +306,6 @@ impl.googlecontacts.CANCEL=&Atlikt # branding plugin.branding.ABOUT_MENU_ENTRY=&Par programmu -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -326,22 +317,16 @@ plugin.branding.ABOUT_MENU_ENTRY=&Par programmu # jabber accregwizz -# mailbox -plugin.mailbox.CONFIRM=Apstiprināt - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz plugin.sipaccregwizz.DISPLAY_NAME=Rādīt ar vārdu +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -353,24 +338,21 @@ plugin.updatechecker.BUTTON_CLOSE=Ai&zvērt plugin.whiteboard.COLOR=Krāsa plugin.whiteboard.DELETE=Dzēst -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=&Kopēt plugin.keybindings.CHAT_CUT=&Izgriezt +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Tērzēšana # Notification Configuration Form +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Ienākošais zvans plugin.notificationconfig.event.IncomingFile=Ienākošais zvans plugin.notificationconfig.event.HangUp=Nolikt klausuli @@ -386,6 +368,7 @@ impl.media.security.zrtp.TITLE=Zvanīt +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -418,7 +401,6 @@ net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=&Ignorēt net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult.Deny=&Aizliegt #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=&Labot #Certificate configuration plugin -- cgit v1.1 From c62772b1b06981acb605928d2827e41150b59894 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:29 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 163 of 1505 strings translated (21 fuzzy). --- resources/languages/resources_hr.properties | 66 ++++++++++++----------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/resources/languages/resources_hr.properties b/resources/languages/resources_hr.properties index 2ac99d9..5640f9f 100644 --- a/resources/languages/resources_hr.properties +++ b/resources/languages/resources_hr.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=Ja service.gui.ACCOUNT_REGISTRATION_WIZARD=Čarobnjak za registraciju kontakta service.gui.ACCOUNTS=Računi service.gui.ADD=&Dodaj -service.gui.ADD_ACCOUNT=Dodaj račun service.gui.ADD_CONTACT=&Dodaj kontakt service.gui.ADD_AUTHORIZED_CONTACT=Dodaj {0} u svoju listu kontakata service.gui.ADD_CONTACT_TO=&Dodaj kontakt u @@ -41,20 +51,15 @@ service.gui.ADD_CONTACT_ERROR_TITLE=Dodaj kontakt greška service.gui.ADD_CONTACT_EXIST_ERROR=Kontakt {0} se već nalazi u listi kontakata service.gui.ADD_CONTACT_NETWORK_ERROR=Poslužitelj nije odgovorio na zahtjev za dodavanjem kontakta sa idenfikatorom: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=Greška pri dodavanju kontakta sa identifikatorom: {0}. Operacija nije podržana. -service.gui.ADD_CONTACT_IDENTIFIER=U niže navedeno polje unesite identifikator kontakta kojeg želite dodati. -service.gui.ADD_CONTACT_WIZARD=Čarobnjak za dodavanje kontakata service.gui.ADD_CONTACT_NOT_CONNECTED=Morate biti spojeni da biste mogli dodati kontakt. Molimo prijavite se na odabranog davatelja i pokušajte ponovo. service.gui.ADD_GROUP_LOCAL_ERROR=Greška prilikom dodavanja grupe sa imenom: {0}. Problem se javio tijekom lokalne IO operacije. service.gui.ADD_GROUP_EXIST_ERROR=Grupa {0} već postoji u vašem popisu kontakata. Molimo odaberite drugo ime. service.gui.ADD_GROUP_NET_ERROR=Greška prilikom dodavanja grupa sa imenom: {0}. Problem se javio zbog pada mreže. Provjerite svoje mrežne veze i pokušajte ponovo. service.gui.ADD_GROUP_ERROR=Greška prilikom dodavanja grupe sa imenom: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Ime grupe ne smije biti prazno. -service.gui.ADD_GROUP=Kreiraj grupu -service.gui.ADD_SUBCONTACT=&Dodaj podkontakt service.gui.ADDRESS=Adresa service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Napredno -service.gui.ALL=&Sve service.gui.ALL_CONTACTS=&Svi kontakti service.gui.ALTERNATE_ADDRESS=Druga adresa service.gui.APPLY=&Primijeni @@ -64,7 +69,6 @@ service.gui.AT=na service.gui.AUTHORIZE=&Odobri service.gui.AUTHORIZATION_ACCEPTED={0} je prihvatio vaš zahtjev za autorizaciju. service.gui.AUTHENTICATION_FAILED=Autentikacija nije uspjela za {0}. Unešena lozinka nije ispravna. -service.gui.AUTHENTICATION_REQUESTED=Zatražena autentikacija service.gui.AUTHENTICATION_REJECTED={0} je odbio zahtjev za autorizaciju. service.gui.AUTHENTICATION_WINDOW_TITLE={0} provjera autentičnosti service.gui.AUTHORIZATION_REQUESTED=Zahtjev za autorizaciju @@ -96,23 +100,18 @@ service.gui.CHANGE_NICKNAME_LABEL=Možete unijeti nadimak u polje ispod. service.gui.CHANGE_NICKNAME_ERROR=Greška pri promjeni nadimka service.gui.CHANGE_NICKNAME_CONFLICT_ERROR=Nadimak već postoji service.gui.CHANGE_VIDEO_QUALITY=Promijeni kvalitet prikaza udaljenog videa. -service.gui.CHAT_CONFERENCE_LABEL=Konferencije service.gui.CHAT_CONFERENCE_ITEM_LABEL={0} konferencija service.gui.CHAT_ROOM_ALREADY_JOINED=Soba {0} je već uključena. service.gui.CHAT_ROOM_CONFIGURATION=Konfiguracija sobe {0} service.gui.CHAT_ROOM_SEND_MSG_FORBIDDEN=Slanje poruka je zabranjeno (glasovno opozvano) -service.gui.CHAT_ROOM_SAVE_BUTTON_TOOLTIP=Spremi sobu za buduću uporabu -service.gui.CHAT_ROOM_REMOVE_BUTTON_TOOLTIP=Briše označenu sobu iz popisa spremljenih soba service.gui.CHAT_ROOM_NAME=Ime sobe service.gui.CLEAR_CUSTOM_MESSAGES=Obriši korisnički definirane poruke service.gui.ROOM_NAME=Soba za razgovor -service.gui.AUTOJOIN=Automatsko pridruživanje service.gui.CHANGE_PASSWORD=Promijeni lozinku service.gui.CHAT_ROOM_NAME_INFO=Unesite ime sobe za razgovor koju želite kreirati u polje ispod. service.gui.CHAT_ROOM_NOT_EXIST=Na poslužitelju {1} ne postoji soba {0}. Provjerite jeste li upisali ispravno ime. service.gui.CHAT_ROOM_NOT_CONNECTED=Morate biti spojeni da biste se pridružili sobi {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Morate biti spojeni da biste mogli izaći iz sobe. -service.gui.CHAT_ROOM_NOT_JOINED=Morate biti prijavljeni u sobi da biste radili dodatne operacije u njoj. service.gui.CHAT_ROOM_OPTIONS=Opcije sobe za razgovor service.gui.CHAT_ROOM=Soba za razgovor service.gui.CHAT_ROOM_SUBJECT_CHANGED={0} je promijenio temu u {1} @@ -124,20 +123,16 @@ service.gui.CITY=Grad service.gui.COUNTRY=Zemlja service.gui.SHOW_MORE_TOOLTIP=Kliki za prikaz više rezultata service.gui.CONNECTION=Veza -service.gui.CONNECTION_FAILED_MSG=Za sljedeći račun veza nije uspjela: Korisničko ime: {0}, Poslužitelj: {1}. Provjerite mrežne veze ili kontaktirajte mrežnog administratora za više informacija. service.gui.CONNECTION_EXPIRED_MSG=Trenutno ste isključeni sa poslužitelja {0}. service.gui.CONTACT_NAME=ID ili Broj -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Odabrani kontakt {0} ne podržava telefoniranje. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Odabrani kontakt {0} ne podržava konferenciju. service.gui.CONTACT_PAUSED_TYPING={0} je prestao pisati service.gui.CONTACT_TYPING={0} piše poruku service.gui.CONTACT_TYPING_SEND_FAILED=uh... nismo mogli obavijestiti {0} da ste pisali service.gui.CREATE_CHAT_ROOM_WIZARD=Čarobnjak za kreiranje soba za razgovor service.gui.CREATE_CONFERENCE_CALL=&Kreiraj konferencijski poziv -service.gui.CREATE_CONFERENCE_CHAT=&Kreiraj konferenciju service.gui.CREATE_GROUP=&Kreiraj grupu... service.gui.CREATE_GROUP_NAME=Unesite ime grupe koju želite kreirati u polje ispod -service.gui.CREATE_FIRST_GROUP_WIZARD=Vaš popis kontakata ne sadrži niti jednu grupu. Prvo kreirajte grupu (Datoteka/Kreiraj grupu). service.gui.CREATE_VIDEO_BRIDGE=Kreiraj &video most... service.gui.CREATE_VIDEO_BRIDGE_MENU=Kreiraj &video most service.gui.CREATE_JOIN_VIDEO_CONFERENCE=Kreiraj / priključi se video konferenciji @@ -145,7 +140,6 @@ service.gui.DISCONNECTED_STATUS=Isključen service.gui.DND_STATUS=Ne smetaj service.gui.DO_NOT_ASK_AGAIN=Ne pitaj ponovno service.gui.DO_NOT_SHOW_AGAIN=Ne prikazuj više ovu poruku -service.gui.DOWNLOAD_NOW=&Preuzmi sada service.gui.DRAG_FOR_SHARING=Povucite ovdje sve što želite dijeliti... service.gui.DURATION=trajanje service.gui.DESTROY_CHATROOM=Izbriši sobu za razgovor @@ -157,7 +151,6 @@ service.gui.ERROR_RECEIVED_FROM=Greška primljena od {0} service.gui.ESTIMATED_TIME=Očekivano vrijeme: service.gui.EVENTS=Događaji service.gui.EXIT=I&zlaz -service.gui.EXTENDED_CRITERIA=Proširi uvjet service.gui.GENERAL=Općenito service.gui.FILE_RECEIVE_FAILED=Greška prilikom prebacivanja datoteke od {0}. service.gui.FILE_SENDING_TO=Šaljem datoteku prema {0}. @@ -189,7 +182,6 @@ service.gui.HISTORY=&Povijest service.gui.HISTORY_REMOVE_ERROR=Greška prilikom brisanja lokalno spremljenih poruka. service.gui.HOME=Početak service.gui.HOME_PAGE=Početna stranica -service.gui.HOUR=Sat service.gui.IDENTIFIER=Identifikator service.gui.IGNORE=&Zanemari service.gui.INSERT_SMILEY=Ubaci smješka @@ -205,6 +197,11 @@ service.gui.IS_NOW={0} je sada {1} +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names # keep the following string short @@ -213,9 +210,6 @@ service.gui.IS_NOW={0} je sada {1} -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -224,6 +218,10 @@ service.gui.IS_NOW={0} je sada {1} # LDAP +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts @@ -238,9 +236,6 @@ service.gui.IS_NOW={0} je sada {1} # branding -# Dict protocol - -# facebookaccregwizz # generalconfig @@ -252,20 +247,15 @@ service.gui.IS_NOW={0} je sada {1} # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -274,21 +264,18 @@ service.gui.IS_NOW={0} je sada {1} # whiteboard -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated +#Enum KeybindingSet.Category # Notification Configuration Form +#NotificationsTable constants # ZRTP Securing @@ -300,6 +287,7 @@ service.gui.IS_NOW={0} je sada {1} +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. -- cgit v1.1 From 4f789314de9291b068688da5f7560792d4a8be37 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:36 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 268 of 1505 strings translated (46 fuzzy). --- resources/languages/resources_ga.properties | 89 +++++++++-------------------- 1 file changed, 28 insertions(+), 61 deletions(-) diff --git a/resources/languages/resources_ga.properties b/resources/languages/resources_ga.properties index 92bd41c..da083f3 100644 --- a/resources/languages/resources_ga.properties +++ b/resources/languages/resources_ga.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -31,14 +42,11 @@ service.gui.ACCOUNT=Cuntas service.gui.ACCOUNT_ME=Mise service.gui.ACCOUNTS=Cuntais service.gui.ADD=&Cuir leis -service.gui.ADD_ACCOUNT=Cuir cuntas leis service.gui.ADD_CONTACT=&Cuir teagmhálaí leis service.gui.ADD_CONTACT_TO=&Cuir an teagmhálaí le -service.gui.ADD_GROUP=Cruthaigh baicle service.gui.ADDRESS=Seoladh service.gui.ADMINISTRATOR=riarthóir service.gui.ADVANCED=&Ardroghanna -service.gui.ALL=&Uile service.gui.ALL_CONTACTS=&Gach teagmhálaí service.gui.ALTERNATE_ADDRESS=Seoladh malartach service.gui.APPLY=&Cuir i bhfeidhm @@ -46,7 +54,6 @@ service.gui.ARE_CALLING=Tá {0} ag glaoch... service.gui.ARE_NOW=Tá tú {0} anois service.gui.AT=ag service.gui.AUTHORIZE=&Ceadaigh -service.gui.AUTHENTICATION_REQUESTED=Fíordheimhniú iarrtha service.gui.AUTHORIZATION_REQUESTED=Fíordheimhniú iarrtha service.gui.BUSY_MESSAGE=Is dona liom ach tá mé gnóthach faoi láthair. service.gui.BUSY_STATUS=Gnóthach @@ -58,7 +65,6 @@ service.gui.CANCEL=&Cealaigh service.gui.CHAT=Comhrá service.gui.CHANGE_FONT=Athraigh an chlófhoireann service.gui.CHANGE_ROOM_SUBJECT=Athraigh ábhar an tseomra... -service.gui.CHAT_CONFERENCE_LABEL=Comhdhálacha service.gui.CHAT_CONFERENCE_ITEM_LABEL=Comhdháil {0} service.gui.CHAT_ROOM_USER_LEFT=d'fhág {0} service.gui.CHANGE_PASSWORD=Athraigh an focal faire @@ -71,7 +77,6 @@ service.gui.COUNTRY=Tír service.gui.SHOW_MORE_TOOLTIP=Brúigh anseo chun tuilleadh torthaí a thaispeáint service.gui.CLEAR=Glan service.gui.CLOSE=Dún -service.gui.CONFIRM=Deimhnigh service.gui.CONNECTED_STATUS=Nasctha service.gui.CONNECTING=Ag nascadh... service.gui.CONNECTING_STATUS=Ag nascadh @@ -103,7 +108,6 @@ service.gui.FONT_ITALIC=Iodálach service.gui.FONT_SIZE=Méid service.gui.FONT_STYLE=Nós service.gui.FONT_UNDERLINE=Cuir líne faoi -service.gui.FROM={0} ó {1} service.gui.GUEST=cuairteoir service.gui.HANG_UP=Críochnaigh service.gui.HD_QUALITY=Físeán ardghléine @@ -112,7 +116,6 @@ service.gui.HIDE=Folaigh service.gui.HIDE_OFFLINE_CONTACTS=Cuir teagmhálacha nach bhfuil ceangailte i bhfolach service.gui.HOME=Baile service.gui.HOME_PAGE=Leathanach baile -service.gui.HOUR=Uair service.gui.ICE=ICE service.gui.IDENTIFIER=Aitheantóir service.gui.IGNORE=&Déan neamhaird de @@ -126,6 +129,11 @@ service.gui.NO_MESSAGE=Níl teachtaireacht ann +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names # keep the following string short @@ -134,9 +142,6 @@ service.gui.NO_MESSAGE=Níl teachtaireacht ann -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -149,9 +154,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=roghnaigh líonra # LDAP impl.ldap.FIELDS=Réimsí impl.ldap.QUERY=Iarrtas -impl.ldap.NEW=Nua impl.ldap.EDIT=eagar -impl.ldap.REMOVE=Bain impl.ldap.ENABLED=Cumasaithe impl.ldap.AUTH_NONE=Dada impl.ldap.AUTH_SIMPLE=Diúid @@ -165,14 +168,16 @@ impl.ldap.SCOPE=Cuimse impl.ldap.MAIL_FIELD_EXAMPLE=post impl.ldap.PHONE_PREFIX_EXAMPLE=M.sh.: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.PREFIX_EXAMPLE=M.sh.: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=Teagmhálacha Google -impl.googlecontacts.NEW=Nua impl.googlecontacts.EDIT=eagar -impl.googlecontacts.REMOVE=Bain impl.googlecontacts.ENABLED=Cumasaithe impl.googlecontacts.ACCOUNT_NAME=Ainm an chuntais impl.googlecontacts.SAVE=Taisc @@ -196,8 +201,6 @@ plugin.accountinfo.PHONE=Uimhir ghutháin: plugin.accountinfo.ABOUT_ME=Maidir Liomsa: plugin.accountinfo.ABOUT_ME_MAX_CHARACTERS=200 plugin.accountinfo.LOCAL_ICON=Bain feidhm as an deilbhín seo: -plugin.accountinfo.CHANGE=Athraigh -plugin.accountinfo.ONLY_MESSAGE=Teachtaireachtaí amháin # connection info @@ -212,26 +215,14 @@ plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=Cláraigh cuntas nua # branding plugin.branding.ABOUT_WINDOW_TITLE=Maidir le {0} plugin.branding.LOGO_MESSAGE=Cur teachtaireachtaí meandracha && VoIP Foinse Oscailte -plugin.branding.LOADING=Ag luchtú plugin.branding.ABOUT_MENU_ENTRY=&Maidir le -# Dict protocol -service.protocol.DICTIONARIES=Foclóirí -plugin.dictaccregwizz.ANY_DICTIONARY=Foclóir ar bith -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.HOST=Óstach -plugin.dictaccregwizz.CLOSING_CONNECTION=Ag dúnadh an naisc - -# facebookaccregwizz -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook # generalconfig plugin.generalconfig.SHOW_HISTORY=Taispeáin plugin.generalconfig.HISTORY_SIZE=teachtaireachtaí le gairid i gcomhráite nua plugin.generalconfig.SEND_MESSAGES_WITH=Seol teachtaireachtaí le: plugin.generalconfig.BRING_WINDOW_TO_FRONT=Tabhair fuinneog an chomhrá chun tosaigh -plugin.generalconfig.TRANSPARENCY=Trédhearcacht -plugin.generalconfig.ENABLE_TRANSPARENCY=Cumasaigh trédhearcacht plugin.generalconfig.DEFAULT_LANGUAGE=Teanga an chomhéadain plugin.generalconfig.DEFAULT_LANGUAGE_RESTART_WARN=Cuirfear na hathruithe a rinne tú i bhfeidhm an chéad uair eile a tosófar é. plugin.generalconfig.DEFAULT_LANGUAGE_TRANSLATED={0}% aistrithe @@ -249,30 +240,16 @@ plugin.generalconfig.SILK_CONFIG=Síoda # irc accregwizz # jabber accregwizz -plugin.jabberaccregwizz.ADVANCED_OPTIONS=Ardroghanna plugin.jabberaccregwizz.USE_ICE=Bain feidhm as ICE plugin.jabberaccregwizz.SERVER_OPTIONS=Roghanna an fhreastalaithe plugin.jabberaccregwizz.CHANGE_PASSWORD=Athraigh focal faire an chuntais -plugin.jabberaccregwizz.NEW_PASSWORD=Focal faire nua -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=Deimhnigh an focal faire nua -plugin.jabberaccregwizz.PASSWORD_EMPTY=Tá an focal faire folamh. plugin.jabberaccregwizz.PASSWORD_CHANGED=Athraíodh an focal faire go rathúil. plugin.jabberaccregwizz.AUDIO=Fuaim plugin.jabberaccregwizz.VIDEO=Físeán -# mailbox -plugin.mailbox.INCOMING=Teachtaireachtaí isteach: -plugin.mailbox.CONFIRM=Deimhnigh -plugin.mailbox.DEFAULTS=Réamhshocruithe - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.USERNAME=Seoladh ríomhphoist: - # plugin manager plugin.pluginmanager.INSTALL=Suiteáil plugin.pluginmanager.UNINSTALL=Díshuiteáil -plugin.pluginmanager.UPDATE=Nuashonrú plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=Roghnaigh comhad plugin.pluginmanager.SYSTEM=Córas @@ -282,11 +259,10 @@ plugin.pluginmanager.NEW=Nua plugin.simpleaccregwizz.SIGNUP=Nach bhfuil tú cláraithe fós? # sipaccregwizz +#used from SecurityPanel # skin manager -# ssh accregwizz - # status update # updatechecker @@ -310,26 +286,17 @@ plugin.whiteboard.MODIFICATION=Mionathrú plugin.whiteboard.THICKNESS=Tiús: plugin.whiteboard.GRID=Mogallra -# yahoo accregwizz - -# zero accregwizz -plugin.zeroaccregwizz.FIRST_NAME=Ainm: -plugin.zeroaccregwizz.LAST_NAME=Sloinne: -plugin.zeroaccregwizz.EMAIL=Seoladh ríomhphoist: - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk # iptel accregwizz -# sip2sip accregwizz +# ippi accregwizz plugin.sip2sipaccregwizz.RETYPE_PASSWORD=Clóscríobh arís an focal faire plugin.sip2sipaccregwizz.EMAIL=Seoladh ríomhphoist -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=Cruthaigh cuntas sip2sip.info saor in aisce - -# ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=Macasamhlaigh plugin.keybindings.CHAT_CUT=Gearr plugin.keybindings.CHAT_NEXT_TAB=Cluaisín ar aghaidh @@ -339,6 +306,7 @@ plugin.keybindings.MAIN_RENAME=Athainmnigh an teagmhálaí plugin.keybindings.globalchooser.ANSWER_CALL=Freagair an glao plugin.keybindings.globalchooser.HANGUP_CALL=Críochnaigh an glao plugin.keybindings.globalchooser.PUSH_TO_TALK=Brúigh chun labhairt +#Enum KeybindingSet.Category plugin.keybindings.GLOBAL=Aicearraí coiteanna # Notification Configuration Form @@ -352,6 +320,7 @@ plugin.notificationconfig.BROWSE_SOUND=Roghnaigh comhad fuaime plugin.notificationconfig.BROWSE_PROGRAM=Roghnaigh ríomhchlár plugin.notificationconfig.tableheader.ENABLE=Cumasaigh nó díchumasaigh an ghné seo plugin.notificationconfig.tableheader.DESCRIPTION=Cur síos ar imeacht +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Glao isteach plugin.notificationconfig.event.SecurityMessage=Teachtaireacht Slándála plugin.notificationconfig.event.IncomingFile=Comhad isteach @@ -367,6 +336,7 @@ plugin.notificationconfig.event.NetworkNotifications=Fógraí an líonra +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -375,7 +345,6 @@ plugin.notificationconfig.event.NetworkNotifications=Fógraí an líonra plugin.securityconfig.masterpassword.CURRENT_PASSWORD=An focal faire reatha: plugin.securityconfig.masterpassword.ENTER_PASSWORD=Cuir isteach focal faire nua: plugin.securityconfig.masterpassword.REENTER_PASSWORD=Cuir isteach arís an focal faire nua: -plugin.securityconfig.masterpassword.MP_NOT_SET=(gan socrú) # otr plugin @@ -409,8 +378,6 @@ net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult #plugin spellcheck plugin.spellcheck.TITLE=Litriú agus Gramadach plugin.spellcheck.MENU=Taispeáin Litriú agus Gramadach -plugin.spellcheck.LANG=Teanga -plugin.spellcheck.EDIT_PERSONAL_DICT=Eagar plugin.spellcheck.ENABLE_SPELL_CHECK=Cumasaigh an litreoir plugin.spellcheck.dialog.FIND=Aimsigh ar aghaidh plugin.spellcheck.dialog.REPLACE=Ionadaigh -- cgit v1.1 From 880afd0bc115f0aa53216bf6862a5c1077050279 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:42 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 889 of 1505 strings translated (37 fuzzy). --- resources/languages/resources_he.properties | 165 +++++----------------------- 1 file changed, 28 insertions(+), 137 deletions(-) diff --git a/resources/languages/resources_he.properties b/resources/languages/resources_he.properties index 8dc5f1e..5199796 100644 --- a/resources/languages/resources_he.properties +++ b/resources/languages/resources_he.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,7 +43,6 @@ service.gui.ACCOUNT_ME=אני service.gui.ACCOUNT_REGISTRATION_WIZARD=אשף הרשמת חשבון service.gui.ACCOUNTS=חשבונות service.gui.ADD=&הוסף -service.gui.ADD_ACCOUNT=הוסף חשבון service.gui.ADD_CONTACT=&הוסף איש קשר service.gui.ADD_AUTHORIZED_CONTACT=הוסף את {0} אל רשימת אישי הקשרים שלך service.gui.ADD_CONTACT_TO=&הוסף אנשי קשר אל @@ -41,17 +51,12 @@ service.gui.ADD_CONTACT_ERROR_TITLE=שגיאת הוספת איש קשר service.gui.ADD_CONTACT_EXIST_ERROR=איש הקשר {0} כבר מצוי ברשימת אישי הקשרים שלך. service.gui.ADD_CONTACT_NETWORK_ERROR=שרת לא הגיב לבקשתנו להוספת איש קשר עם מזהה: {0}. service.gui.ADD_CONTACT_NOT_SUPPORTED=כשל בהוספת איש קשר עם מזהה: {0}. פעולה לא נתמכת. -service.gui.ADD_CONTACT_IDENTIFIER=בשדה להלן, הזן המזהה של איש הקשר אשר ברצונך להוסיף. -service.gui.ADD_CONTACT_WIZARD=אשף הוספת איש קשר service.gui.ADD_GROUP_EXIST_ERROR=הקבוצה {0} כבר מצויה ברשימת הקשרים שלך. אנא בחר שם אחר. service.gui.ADD_GROUP_ERROR=כשל בהוספת קבוצה בשם: {0}. service.gui.ADD_GROUP_EMPTY_NAME=שם הקבוצה לא יכול להיות ריק. -service.gui.ADD_GROUP=צור קבוצה -service.gui.ADD_SUBCONTACT=&הוסף איש קשר משני service.gui.ADDRESS=כתובת service.gui.ADMINISTRATOR=מנהלן service.gui.ADVANCED=&מתקדם -service.gui.ALL=&הכל service.gui.ALL_CONTACTS=&כל אנשי הקשר service.gui.APPLY=&החל service.gui.ARE_CALLING=מתקשרים כעת... @@ -59,7 +64,6 @@ service.gui.ARE_NOW=הינך {0} כעת service.gui.AUTHORIZE=&הרשאה service.gui.AUTHORIZATION_ACCEPTED=איש הקשר קיבל את בקשת הרשאתך. service.gui.AUTHENTICATION_FAILED=אימות עבור {0} נכשל. הסיסמה שהזנת הינה שגויה. -service.gui.AUTHENTICATION_REQUESTED=התבקש אישור service.gui.AUTHENTICATION_REQUESTED_SERVER=השרת {0} ביקש את אישורך. service.gui.AUTHENTICATION_REJECTED=איש הקשר דחה את בקשת הרשאתך. service.gui.AUTHENTICATION_WINDOW_TITLE=‫{0} אימות @@ -101,7 +105,6 @@ service.gui.CHAT_ROOM_USER_QUIT={0} יצא/ה service.gui.CHAT_ROOM_NAME=שם חדר שיחה service.gui.CLEAR_CUSTOM_MESSAGES=טהר הודעות מותאמות service.gui.ROOM_NAME=חדר שיחה -service.gui.AUTOJOIN=הצטרף אוטומטית service.gui.CHANGE_PASSWORD=שנה סיסמה service.gui.CHAT_ROOM_NAME_INFO=בשדה להלן, הזן את השם של חדר השיחה אשר ברצונך ליצור. service.gui.CHAT_ROOM_NOT_EXIST=החדר {0} לא נמצא בתוך השרת {1}. אנא ודא אם השם שהקלדת הינו מדויק. @@ -120,7 +123,6 @@ service.gui.CLEAR=טהר service.gui.CLOSE=&סגור service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=קיבלת הודעה חדשה מלפני פחות משתי שניות. האם אתה בטוח כי ברצונך לסגור את שיחה זו? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=יש לך העברות קובץ פעילות. האם אתה בטוח כי ברצונך לבטלן? -service.gui.CONFIRM=אמת service.gui.CONNECTED_STATUS=מחובר service.gui.CONNECTING=מתחבר כעת... service.gui.CONNECTING_STATUS=מתחבר כעת @@ -128,12 +130,10 @@ service.gui.CONNECTING_EARLY_MEDIA_STATUS=מתחבר כעת* service.gui.CONNECTION=חיבור service.gui.CONNECTION_EXPIRED_MSG=אתה מנותק כעת מהשרת {0}. service.gui.CONTACT_NAME=מזהה או מספר -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=איש קשר נבחר {0} לא תומך בטלפוניה. service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=איש קשר נבחר {0} לא תומך בשיחת ועידה. service.gui.CONTACT_PAUSED_TYPING=‏{0} פסק מלהקליד את ההודעה service.gui.CONTACT_TYPING=‏{0} מקליד כעת הודעה service.gui.CONTACT_INFO=&מידע איש קשר -service.gui.CONTACTLIST=רשימת קשר service.gui.CONTACTS=ה&עתק service.gui.COPY=ה&עתק service.gui.COPY_LINK=העתק &קישור @@ -143,14 +143,11 @@ service.gui.CREATE_CHAT_ROOM=&צור חדר שיחה... service.gui.CREATE_CHAT_ROOM_ERROR=נכשל ליצור חדר שיחה {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=אשף יצירת חדר שיחה service.gui.CREATE_CONFERENCE_CALL=&צור קריאת ועידה... -service.gui.CREATE_CONFERENCE_CHAT=&צור שיחת ועידה... service.gui.CREATE_GROUP=&צור קבוצה... service.gui.CREATE_GROUP_NAME=בשדה להלן, הזן את השם של הקבוצה אשר ברצונך ליצור. -service.gui.CREATE_FIRST_GROUP_WIZARD=רשימת הקשרים של לא מכילה אף קבוצה. אנא צור קבוצה צחילה (קובץ/צור קבוצה). service.gui.CREATE_VIDEO_BRIDGE=יצירת &גשר וידאו... service.gui.CREATE_VIDEO_BRIDGE_MENU=צור &גשר וידאו service.gui.CUT=&גזור -service.gui.DATE=תאריך service.gui.DELETE=מחק service.gui.DENY=&אסור service.gui.DESKTOP_SHARING_WARNING=האם אתה בטוח כי ברצונך להתחיל שיתוף מסך?
    לחיצה על אישור תתיר לאנשים בשיחה זה לראות את המסך שלך. @@ -159,7 +156,6 @@ service.gui.DISPLAY_NAME=שם צג service.gui.DND_STATUS=נא לא להפריע service.gui.DO_NOT_ASK_AGAIN=אל תשאל שוב service.gui.DO_NOT_SHOW_AGAIN=אל תציג את הודעה זו שוב -service.gui.DOWNLOAD_NOW=&הורד כעת service.gui.DRAG_FOR_SHARING=גרור לכאן כל דבר אשר ברצונך לשתף... service.gui.DURATION=משך service.gui.EDIT=&ערוך @@ -173,7 +169,6 @@ service.gui.ERROR_WAS=השגיאה היתה: {0} service.gui.ESTIMATED_TIME=אומדן זמן: service.gui.EVENTS=אירועים service.gui.EXIT=י&ציאה -service.gui.EXTENDED_CRITERIA=קריטריון מורחב service.gui.GENERAL=כללי service.gui.GENERAL_ERROR=שגיאה גנרית service.gui.GROUP_NAME=שם קבוצה @@ -227,7 +222,6 @@ service.gui.HIDE_OFFLINE_CONTACTS=התר אנשי קשר לא מקוונים service.gui.HISTORY=&היסטוריה service.gui.HISTORY_CONTACT=היסטוריה - {0} service.gui.HOME=בית -service.gui.HOUR=שעה service.gui.IDENTIFIER=מזהה service.gui.IGNORE=&התעלם service.gui.INSERT_SMILEY=שבץ סמיילי @@ -241,10 +235,8 @@ service.gui.INVITE_CONTACT_TO_VIDEO_BRIDGE=הזמן אנשי קשר לגשר ו service.gui.INVITE_REASON=סיבת הזמנה service.gui.IS_CALLING=מתקשר/ת כעת... service.gui.IS_NOW=‏{0} כעת {1} -service.gui.JITSI_WARNING_TITLE=‏SIP Communicator נהיה Jitsi service.gui.JOIN=ה&צטרף service.gui.JOIN_AS=הצטרף &בתור -service.gui.CLOSE_CHAT_ROOM_DIALOG=ס&גור service.gui.JOIN_CHAT_ROOM_NAME=אנא הזן את השם של חדר השיחה אליו ברצונך להצטרף. service.gui.KICK=&בעט service.gui.KICK_FAILED=בעיטה נכשלה @@ -258,19 +250,16 @@ service.gui.MESSAGE=הודעה service.gui.MISSED_CALLS_TOOL_TIP=שיחה אשר לא נענתה מן: service.gui.MISSED_CALLS_MORE_TOOL_TIP= ועוד {0} נוספות service.gui.MODERATOR=אחראי -service.gui.MORE=ראה עוד service.gui.MORE_LABEL=הזז service.gui.MOVE=הזז service.gui.MOVE_SUBCONTACT=ה&זז איש קשר service.gui.MOVE_SUBCONTACT_QUESTION=האם אתה בטוח כי ברצונך להעביר את {0} אל {1}? service.gui.MOVE_TO_GROUP=&העבר אל קבוצה service.gui.MOVE_CONTACT=הזז איש קשר -service.gui.MOVE_CONTACT_ERROR=&איש קשר לא ניתן להזזה service.gui.MSG_DELIVERY_FAILURE=ההודעה לעיל לא היתה יכולה להימסר service.gui.MSG_DELIVERY_ERROR=נכשל למסור הודעה. service.gui.MSG_DELIVERY_UNKNOWN_ERROR=אירעה שגיאה לא מוכרת בעת מסירת הודעתך. service.gui.MSG_RECEIVED={0} כתב/ה -service.gui.MUTE=השתק service.gui.NAME=שם service.gui.NETWORK=רשת עבודה service.gui.NETWORK_FAILURE=כשל רשת עבודה @@ -297,7 +286,6 @@ service.gui.OPEN_FILE_FROM_IMAGE=קליק כפול כדי לפתוח קובץ. service.gui.OPEN_FOLDER=פתח תיקייה service.gui.OPEN_IN_BROWSER=פתח בתוך &דפדפן service.gui.OPTIONS=אפשרויות -service.gui.OR_ENTER_PHONE_NUMBER=או הזן מספר טלפון כאן... service.gui.ORGANIZATION=ארגון: service.gui.OTHER=אחר service.gui.PASSWORD=סיסמה @@ -310,7 +298,6 @@ service.gui.PREFERENCES=העדפות service.gui.PREFIX=קידומת service.gui.PRESS_FOR_CALL_INFO=לחץ למידע שיחה service.gui.PREVIOUS=קודם -service.gui.PREVIOUS_TOOLTIP=עיון בשיחות ישנות service.gui.PRINT=&הדפס service.gui.PROTOCOL=פרוטוקול service.gui.QUIT=י&ציאה @@ -318,7 +305,6 @@ service.gui.READY=מוכן service.gui.REASON=סיבה service.gui.RE_REQUEST_AUTHORIZATION=בקש שוב הרשאה service.gui.REJECT=&סרב -service.gui.REMIND_ME_LATER=הזכר לי מאוחר יותר service.gui.REMEMBER_PASSWORD=זכור סיסמה service.gui.REMOVE=&הסר service.gui.REMOVE_ACCOUNT=&הסר חשבון @@ -339,22 +325,15 @@ service.gui.REVOKE_ADMIN=שלול מנהלן service.gui.REVOKE_MODERATOR=שלול אחראי service.gui.REVOKE_MEMBERSHIP=שלול חברות service.gui.REVOKE_VOICE=שלול ביטוי -service.gui.ROOT_GROUP=קבוצת שורש service.gui.SAVE=&שמור -service.gui.SAVE_AS_DEFAULT=שמור כברירת מחדל service.gui.SEARCH=&חפש service.gui.SECURITY=אבטחה -service.gui.SELECT_ACCOUNT=בחירת חשבון service.gui.SELECT_COLOR=בחירת צבע service.gui.SELECT_GROUP=בחירת קבוצה service.gui.SELECT_NO_GROUP=אין קבוצה -service.gui.SELECT_GROUP_WIZARD=ציין קבוצה -service.gui.SELECT_PROVIDERS_WIZARD=בחירת חשבון service.gui.SEND=&שלח service.gui.SEND_FILE=שלח &קובץ -service.gui.SELECT_CONTACT_SUPPORTING_INFO=אין מידע עבור איש קשר זה. service.gui.SEND_MESSAGE=&שלח הודעה -service.gui.SEND_AS_SMS=שלח בצורה של SMS service.gui.SEND_SMS=&שלח SMS service.gui.SEND_SMS_DETAILS=זכור כי עליך להזין את המספר בפורמט בינלאומי למשל ‎+44 עבור הממלכה המאוחדת לדוגמא, ‎+447777000000 service.gui.SEND_SMS_NOT_SUPPORTED=הפרוטוקול בו בחרת לא תומך בהודעות SMS. @@ -383,7 +362,6 @@ service.gui.STREET=רחוב service.gui.SUBJECT=נושא service.gui.SUMMARY=תמצית service.gui.TELEPHONY=טלפוניה -service.gui.TODAY=היום service.gui.TOOLS=&כלים service.gui.TRANSFER=&העבר service.gui.TO=&אל: @@ -391,7 +369,6 @@ service.gui.TRANSFER_CALL_MSG=בחר את שם של איש הקשר אשר בר service.gui.TRANSFER_CALL_TITLE=העבר קריאה service.gui.TRANSFER_CALL_TO=העבר אל: service.gui.TYPE_YOUR_REQUEST=הקלד את בקשתך כאן -service.gui.UNMUTE=איין השתקה service.gui.USER_IDENTIFIER=מזהה משתמש: service.gui.USER_EXISTS_ERROR=משתמש זה כבר קיים בשת הנבחרת. נא לבחור משתמש או רשת אחרים. service.gui.USERNAME_NULL=נא למלא שם משתמש וסיסמה. @@ -401,7 +378,6 @@ service.gui.UNKNOWN_STATUS=מצב לא מוכר service.gui.UNREGISTERED_MESSAGE=לא ניתן להתקשר עם החשבון הבא: שם משתמש: {0}, שם שרת: {1}. הינך כעת לא מקוון. service.gui.VALUE=ערך: service.gui.VIDEO_CALL=&שיחת וידאו -service.gui.VIA_SMS=באמצעות SMS service.gui.VIEW=&תצוגה service.gui.VIEW_HISTORY=הצג &היסטוריה service.gui.VIEW_SMILEYS=הצג &סמיילים @@ -419,8 +395,6 @@ service.gui.VOLUME_CONTROL_TOOL_TIP=התאם עוצמה service.gui.WAITING_AUTHORIZATION=ממתין להרשאה service.gui.WARNING=אזהרה service.gui.YES=כן -service.gui.YESTERDAY=אתמול -service.gui.EXISTING_ACCOUNT_ERROR=החשבון שהזנת כבר קיים. service.gui.NEW=חדש service.gui.ENTER_FULL_SCREEN_TOOL_TIP=הפעל מסך מלא service.gui.EXIT_FULL_SCREEN_TOOL_TIP=נטרל מסך מלא @@ -436,7 +410,6 @@ service.gui.SECURITY_WARNING=אזהרת אבטחה service.gui.SECURITY_ERROR=שגיאת אבטחה service.gui.SPEED=מהירות: service.gui.SILENT_MEMBER=השתק חבר -service.gui.UPDATE=עדכון service.gui.MOBILE_PHONE=נייד service.gui.VIDEO_PHONE=וידאו service.gui.WORK_PHONE=עבודה @@ -465,7 +438,6 @@ service.gui.DECEMBER=דצמבר service.gui.callinfo.TECHNICAL_CALL_INFO=מידע שיחה טכני service.gui.callinfo.CALL_INFORMATION=מידע שיחה service.gui.callinfo.CALL_IDENTITY=זהות -service.gui.callinfo.IS_DEFAULT_ENCRYPTED=הצפנה מאופשרת service.gui.callinfo.CALL_DURATION=משך שיחה service.gui.callinfo.VIEW_CERTIFICATE=הצג תעודה service.gui.callinfo.CODEC=קודק / תדירות @@ -475,15 +447,19 @@ service.gui.callinfo.AUDIO_INFO=מידע אודיו service.gui.callinfo.VIDEO_INFO=מידע וידאו service.gui.callinfo.LOCAL_IP=‏IP מקומי / פורט service.gui.callinfo.REMOTE_IP=‏IP מרוחק / פורט -service.gui.callinfo.BANDWITH=Bandwith service.gui.callinfo.RTT=RTT service.gui.callinfo.MEDIA_STREAM_RTP=RTP service.gui.callinfo.MEDIA_STREAM_SRTP=SRTP + +#enum values from IceProcessingState + service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=‏IP מארח מקומי / פורט service.gui.callinfo.ICE_REMOTE_HOST_ADDRESS=‏IP מארח מרוחק / פורט service.gui.CERT_DIALOG_TITLE=אמת תעודה service.gui.CONTINUE_ANYWAY=המשך בכל אופן + +#service.gui.CERT_INFO_ are combined from Rdn names service.gui.CERT_INFO_CN=שם כללי: service.gui.CERT_INFO_O=ארגון: service.gui.CERT_INFO_C=שם ארץ: @@ -498,7 +474,6 @@ service.gui.CERT_INFO_SIGN_ALG=אלגוריתם חתימה: service.gui.CERT_INFO_ALG=אלגוריתם: service.gui.CERT_INFO_PUB_KEY=מפתח פומבי: service.gui.CERT_INFO_SIGN=חתימה: -service.gui.CONTINUE=המשך service.gui.SHOW_CERT=הצג תעודה service.gui.HIDE_CERT=הסתר תעודה @@ -511,8 +486,6 @@ service.gui.security.SECURE_AUDIO=אודיו מאובטח service.gui.security.AUDIO_NOT_SECURED=אודיו לא מאובטח service.gui.security.SECURE_VIDEO=וידאו מאובטח service.gui.security.VIDEO_NOT_SECURED=וידאו לא מאובטח -service.gui.security.NO_VIDEO=אין וידאו -service.gui.security.CIPHER=צופן: {0} service.gui.security.CALL_NOT_SECURED_TOOLTIP=שיחה לא מאובטחת. # keep the following string short @@ -526,15 +499,10 @@ service.gui.avatar.imagepicker.IMAGE_PICKER=תמונה service.gui.avatar.imagepicker.IMAGE_SIZE=מידת תמונה service.gui.avatar.imagepicker.RESET=איפוס service.gui.avatar.imagepicker.TAKE_PHOTO=לקיחת תמונה -service.gui.avatar.imagepicker.WEBCAM_ERROR=שגיאת מצלמת רשת service.gui.security.encryption.required=נדרשת הצפנה! -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) -impl.protocol.ssh.DETAILS_SEPARATOR=~ # systray @@ -550,9 +518,7 @@ impl.gui.main.account.DUMMY_PROTOCOL_DESCRIPTION=בחר רשת עבודה # LDAP impl.ldap.CONFIG_FORM_TITLE=תצורת LDAP impl.ldap.GENERAL=כללי -impl.ldap.NEW=חדש impl.ldap.EDIT=ערוך -impl.ldap.REMOVE=הסר impl.ldap.ENABLED=מאופשרת impl.ldap.SERVER_NAME=שם שרת impl.ldap.SERVER_NAME_EXAMPLE=שרת LDAP @@ -568,6 +534,10 @@ impl.ldap.MAILSUFFIX_FIELD_EXAMPLE=‏‎@domain.org (לא לשכוח להוסי impl.ldap.PHONE_PREFIX=קידומת טלפון impl.ldap.PHONE_PREFIX_EXAMPLE=דוגמא: 00 +# SIP Protocol + +#Jabber Protocol + # Address book plugin plugin.addrbook.ADDRESS_BOOKS=ספר כתובות plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=אפשר חיפוש ספר טלפונים MacOSX @@ -576,9 +546,7 @@ plugin.addrbook.PREFIX_EXAMPLE=דוגמא: 00 # Google Contacts impl.googlecontacts.CONFIG_FORM_TITLE=אנשי קשר של Google -impl.googlecontacts.NEW=חדש impl.googlecontacts.EDIT=ערוך -impl.googlecontacts.REMOVE=הסר impl.googlecontacts.ENABLED=מאופשרת impl.googlecontacts.ACCOUNT_NAME=שם חשבון impl.googlecontacts.SAVE=שמור @@ -601,9 +569,6 @@ plugin.accountinfo.GENDER=מין: plugin.accountinfo.COUNTRY=ארץ plugin.accountinfo.EMAIL=דוא״ל: plugin.accountinfo.PHONE=טלפון: -plugin.accountinfo.USER_PICTURES=תמונת משתמש -plugin.accountinfo.CHANGE=שנה -plugin.accountinfo.ONLY_MESSAGE=הודעות בלבד # connection info @@ -619,34 +584,16 @@ plugin.aimaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול השירות AIM plugin.aimaccregwizz.USERNAME=שם תצוגה AIM: plugin.aimaccregwizz.USERNAME_AND_PASSWORD=שם תצוגה וסיסמה plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT=רישום חשבון חדש -plugin.aimaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=עקוף הגדרות שרת משתמטות # branding plugin.branding.ABOUT_WINDOW_TITLE=אודות {0} plugin.branding.ABOUT_MENU_ENTRY=&אודות -# Dict protocol -service.protocol.DICTIONARIES=מילונים -plugin.dictaccregwizz.ANY_DICTIONARY=הוסף מילון -plugin.dictaccregwizz.ANY_DICTIONARY_FORM=הוסף מילון מן {0} -plugin.dictaccregwizz.PROTOCOL_NAME=Dict -plugin.dictaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול השירות Dict -plugin.dictaccregwizz.HOST=מארח -plugin.dictaccregwizz.SERVER_INFO=מידע שרת -plugin.dictaccregwizz.ACCOUNT_INFO_TITLE=מידע חשבון Dict - -# facebookaccregwizz -plugin.facebookaccregwizz.PROTOCOL_DESCRIPTION=הפרוטוקול Facebook Chat -plugin.facebookaccregwizz.PROTOCOL_NAME=Facebook -plugin.facebookaccregwizz.USERNAME=שם משתמש: -plugin.facebookaccregwizz.USERNAME_AND_PASSWORD=שם משתמש וסיסמה # generalconfig plugin.generalconfig.SHOW_HISTORY=הצג plugin.generalconfig.HISTORY_SIZE=הודעות חדשות בשיחה חדשה plugin.generalconfig.SEND_MESSAGES_WITH=שלח הודעות עם: -plugin.generalconfig.TRANSPARENCY=שקיפות -plugin.generalconfig.ENABLE_TRANSPARENCY=אפשר שקיפות plugin.generalconfig.DEFAULT_LANGUAGE=שפת ממשק plugin.generalconfig.SIP_CLIENT_PORT=פורט לקוח SIP plugin.generalconfig.SIP_CLIENT_SECURE_PORT=פורט לקוח SIP מאובטח @@ -680,11 +627,9 @@ plugin.ircaccregwizz.HOST=שם מארח: plugin.ircaccregwizz.IRC_SERVER=שרת # jabber accregwizz -plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=הפרוטוקול XMPP plugin.jabberaccregwizz.USERNAME=שם משתמש XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=אמת סיסמה -plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=מזהה וסיסמה plugin.jabberaccregwizz.CSERVER=שרת plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=אפשר keep alive plugin.jabberaccregwizz.NEW_ACCOUNT_TITLE=רישום חשבון חדש XMPP @@ -695,13 +640,9 @@ plugin.jabberaccregwizz.SERVER_COLUMN=שרת plugin.jabberaccregwizz.RESOURCE=משאב plugin.jabberaccregwizz.AUTORESOURCE=חולל משאב אוטומטית plugin.jabberaccregwizz.PRIORITY=עדיפות -plugin.jabberaccregwizz.XMPP_ERROR=שגיאת XMPP plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=שגיאת XMPP לא מוכרת. ודא ששם השרת מדויק. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=סיסמתך לא תאמה. -plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=עקוף הגדרות שרת משתמטות -plugin.jabberaccregwizz.ADVANCED_OPTIONS=אפשרויות מתקדמות plugin.jabberaccregwizz.USE_ICE=השתמש ב־ICE -plugin.jabberaccregwizz.USE_GOOGLE_ICE=נצל Google's Jingle/ICE (ניסיוני) plugin.jabberaccregwizz.TURN_USERNAME=שם משתמש TURN plugin.jabberaccregwizz.IP_ADDRESS=כתובת IP plugin.jabberaccregwizz.ADD_STUN_SERVER=הוסף שרת STUN @@ -717,9 +658,6 @@ plugin.jabberaccregwizz.USE_UPNP=השתמש ב־UPnP plugin.jabberaccregwizz.EXISTING_ACCOUNT=חשבון XMPP קיים plugin.jabberaccregwizz.SERVER_OPTIONS=אפשרויות שרת plugin.jabberaccregwizz.CHANGE_PASSWORD=שנה סיסמת חשבון -plugin.jabberaccregwizz.NEW_PASSWORD=סיסמה חדשה -plugin.jabberaccregwizz.NEW_PASSWORD_CONFIRM=אמת סיסמה חדשה -plugin.jabberaccregwizz.PASSWORD_EMPTY=הסיסמה ריקה. plugin.jabberaccregwizz.PASSWORD_CHANGED=הסיסמה שונתה בהצלחה plugin.jabberaccregwizz.SERVER_NOT_SUPPORT_PASSWORD_CHANGE=שרת jabber זה לא תומך בשינוי סיסמה. plugin.jabberaccregwizz.PASSWORD_NOT_STORED=הסיסמה שונתה בתוך השרת, אך תצורה מקומית לא עודכנה @@ -731,23 +669,9 @@ plugin.jabberaccregwizz.VIDEO=וידאו plugin.jabberaccregwizz.RESET=איפוס plugin.jabberaccregwizz.RESET_DESCRIPTION=אפס אל ההגדרות הגלובליות -# mailbox -plugin.mailbox.OUTGOING=הודעות יוצאות: -plugin.mailbox.INCOMING=הודעות נכנסות: -plugin.mailbox.CONFIRM=אמת -plugin.mailbox.DEFAULTS=ברירות מחדל -plugin.mailbox.MAILBOX=תיבת דואר - -# msn accregwizz -plugin.msnaccregwizz.PROTOCOL_NAME=MSN -plugin.msnaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול להתחברות ולשיחה בשירות MSN. -plugin.msnaccregwizz.USERNAME=דוא״ל: -plugin.msnaccregwizz.USERNAME_AND_PASSWORD=מזהה וסיסמה - # plugin manager plugin.pluginmanager.INSTALL=התקנה plugin.pluginmanager.UNINSTALL=הסרה -plugin.pluginmanager.UPDATE=עדכון plugin.pluginmanager.PLUGINS=תוספות plugin.pluginmanager.URL=Url plugin.pluginmanager.CHOOSE_FILE=בחר קובץ @@ -767,7 +691,6 @@ plugin.sipaccregwizz.REGISTRAR=רשם plugin.sipaccregwizz.SERVER_PORT=פורט שרת plugin.sipaccregwizz.PROXY_PORT=פורט Proxy plugin.sipaccregwizz.PREFERRED_TRANSPORT=מוביל מועדף -plugin.sipaccregwizz.ADVANCED_OPTIONS=אפשרויות מתקדמות plugin.sipaccregwizz.PROXY_OPTIONS=אפשרויות Proxy plugin.sipaccregwizz.PROXY_AUTO=הגדר Proxy אוטומטית plugin.sipaccregwizz.KEEP_ALIVE_METHOD=שיטת Keep alive @@ -776,7 +699,6 @@ plugin.sipaccregwizz.KEEP_ALIVE_INTERVAL_INFO=בין 1 לבין 3600 שניות plugin.sipaccregwizz.DTMF_METHOD=שיטת טזמ״ת (DTMF) plugin.sipaccregwizz.DTMF_RTP=RTP ( RFC2833 / RFC 4733 ) plugin.sipaccregwizz.DTMF_SIP_INFO=מידע SIP -plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=עקוף הגדרות שרת משתמטות plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=אפשר תמיכה להצפנת קריאות plugin.sipaccregwizz.AUTH_NAME=שם הרשאה plugin.sipaccregwizz.DISPLAY_NAME=שם צג @@ -792,6 +714,7 @@ plugin.sipaccregwizz.XCAP_SERVER_URI=‏URI/כתובת שרת plugin.sipaccregwizz.VOICEMAIL=דואר קולי plugin.sipaccregwizz.NOT_SAME_PASSWORD=הסיסמה שלך לא תואמת. plugin.sipaccregwizz.SAVP_OPTION=התוויית RTP/SAVP +#used from SecurityPanel plugin.sipaccregwizz.SAVP_OPTION_0=כבוי (התווה על RTP/AVP בלבד) plugin.sipaccregwizz.SAVP_OPTION_1=מחייב (הצע וקבל רק RTP/SAVP) plugin.sipaccregwizz.SAVP_OPTION_2=רשות (הצע RTP/SAVP ראשית, אחרי כן RTP/AVP) @@ -805,15 +728,6 @@ plugin.skinmanager.DEFAULT_SKIN=סקין משתמט plugin.skinmanager.ADD_NEW_SKIN=הוסף סקין חדש... plugin.skinmanager.DEFAULT_SKIN_DESCRIPTION=הסקין משתמט של היישום. -# ssh accregwizz -plugin.sshaccregwizz.PROTOCOL_NAME=SSH -plugin.sshaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול להתחברות אל מכונות מרוחקות על פני SSH. -plugin.sshaccregwizz.USERNAME=מזהה חשבון: -plugin.sshaccregwizz.IDENTITY_FILE=קובץ זהות: -plugin.sshaccregwizz.KNOWN_HOSTS=מארחים מוכרים: -plugin.sshaccregwizz.OPTIONAL=רשות -plugin.sshaccregwizz.ACCOUNT_DETAILS=פרטי חשבון - # status update plugin.autoaway.ENABLE_CHANGE_STATUS=שנה מצב בזמן נעדרות @@ -841,22 +755,6 @@ plugin.whiteboard.THICKNESS=עובי: plugin.whiteboard.DELETE=מחק plugin.whiteboard.PROPERTIES=מאפיינים -# yahoo accregwizz -plugin.yahooaccregwizz.PROTOCOL_NAME=Yahoo! -plugin.yahooaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול להתחברות ולשיחה בשירות Yahoo‪!‬. -plugin.yahooaccregwizz.USERNAME=שם משתמש: -plugin.yahooaccregwizz.USERID_AND_PASSWORD=מזהה וסיסמה - -# zero accregwizz -plugin.zeroaccregwizz.PROTOCOL_NAME=Zeroconf -plugin.zeroaccregwizz.PROTOCOL_DESCRIPTION=פרוטוקול השירות Zeroconf (‫Bonjour) -plugin.zeroaccregwizz.FIRST_NAME=שם פרטי: -plugin.zeroaccregwizz.LAST_NAME=שם משפחה: -plugin.zeroaccregwizz.EMAIL=דוא״ל: -plugin.zeroaccregwizz.REMEMBER_CONTACTS=לזכור אנשי קשר Bonjour? -plugin.zeroaccregwizz.USERID_AND_PASSWORD=מזהה וסיסמה -plugin.zeroaccregwizz.USERID=מזהה משתמש - # gtalk accregwizz plugin.googletalkaccregwizz.PROTOCOL_NAME=Google Talk plugin.googletalkaccregwizz.PROTOCOL_DESCRIPTION=הפרוטוקול Google Talk @@ -869,21 +767,16 @@ plugin.iptelaccregwizz.PROTOCOL_DESCRIPTION=‏iptel.org, פורטל טלקומ plugin.iptelaccregwizz.USERNAME=שם משתמש plugin.iptelaccregwizz.NEW_ACCOUNT_TITLE=הרשמה אל iptel.org -# sip2sip accregwizz -plugin.sip2sipaccregwizz.PROTOCOL_NAME=sip2sip.info -plugin.sip2sipaccregwizz.PROTOCOL_DESCRIPTION=‏VoIP ושיחה +# ippi accregwizz plugin.sip2sipaccregwizz.USERNAME=שם משתמש plugin.sip2sipaccregwizz.RETYPE_PASSWORD=הקלד מחדש סיסמה plugin.sip2sipaccregwizz.EMAIL=כתובת דוא״ל -plugin.sip2sipaccregwizz.EXISTING_ACCOUNT=חשבון sip2sip.info קיים -plugin.sip2sipaccregwizz.CREATE_ACCOUNT=צור חשבון sip2sip.info חינמי - -# ippi accregwizz plugin.ippiaccregwizz.PROTOCOL_NAME=ippi plugin.ippiaccregwizz.EXISTING_ACCOUNT=חשבון ippi קיים plugin.ippiaccregwizz.CREATE_ACCOUNT=צור חשבון ippi חינמי # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=סגור חלון שיחה plugin.keybindings.CHAT_COPY=העתק plugin.keybindings.CHAT_CUT=גזור @@ -904,6 +797,7 @@ plugin.keybindings.globalchooser.SHOW_CONTACTLIST=הצג רשימת קשרים plugin.keybindings.globalchooser.SHORTCUT_NAME=שם plugin.keybindings.globalchooser.SHORTCUT_PRIMARY=קיצור דרך עיקרי plugin.keybindings.globalchooser.SHORTCUT_SECOND=קיצור דרך שני +#Enum KeybindingSet.Category plugin.keybindings.CHAT=שיחה plugin.keybindings.MAIN=ראשי plugin.keybindings.GLOBAL=קיצורי דרך גלובליים @@ -918,6 +812,7 @@ plugin.notificationconfig.PROGRAM_FILE=קובץ תוכנית: plugin.notificationconfig.BROWSE_SOUND=בחר קובץ צליל plugin.notificationconfig.BROWSE_PROGRAM=בחר תוכנית plugin.notificationconfig.tableheader.DESCRIPTION=תיאור של אירוע +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=קריאה נכנסת plugin.notificationconfig.event.SecurityMessage=הודעת אבטחה plugin.notificationconfig.event.IncomingFile=קובץ נכנס @@ -986,6 +881,7 @@ impl.neomedia.configform.AUDIO=שמע impl.neomedia.configform.VIDEO=וידאו impl.neomedia.configform.H264=H.264 +#in JNIEncoder impl.neomedia.configform.H264.defaultProfile.main=ראשי impl.neomedia.configform.H264.preferredKeyFrameRequester.rtcp=RTCP @@ -1006,7 +902,6 @@ plugin.securityconfig.masterpassword.CURRENT_PASSWORD=סיסמה נוכחית: plugin.securityconfig.masterpassword.ENTER_PASSWORD=הזן סיסמה חדשה: plugin.securityconfig.masterpassword.REENTER_PASSWORD=הזן סיסמה שוב: plugin.securityconfig.masterpassword.MP_TITLE=סיסמה ראשית -plugin.securityconfig.masterpassword.MP_NOT_SET=(לא נקבע) plugin.securityconfig.masterpassword.MP_CURRENT_EMPTY=לא בזנת את הסיסמה הראשית המדויקצ. נא לנסות שוב. plugin.securityconfig.masterpassword.MP_VERIFICATION_FAILURE_MSG=סיסמה ראשית אינה מדויקת! plugin.securityconfig.masterpassword.MP_CHANGE_FAILURE=שינוי סיסמה נכשל @@ -1021,7 +916,6 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=סיסמה plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(לא ידוע) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(לא ניתן לפענח) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=סיסמאות מאוחסנות -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=הסר plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=הסר הכל plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=האם אתה בטוח כי ברצונך להסיר את כל הסיסמאות? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=הסר את כל הסיסמאות @@ -1106,7 +1000,6 @@ plugin.provisioning.RESTART_WARNING=שים לב שהשינויים שלך יכנ plugin.provisioning.UUID=UUID plugin.provisioning.COPYTOCLIPBOARD=העתק UUID אל לוח גזירה plugin.provisioning.CLIPBOARD_FAILED=כשל בהעתקת UUID אל לוח גזירה -plugin.provisioning.EXIT_ON_FAIL=צא מהיישום במידה והאספקה נכשלת plugin.provisioning.CREDENTIALS=נתוני התחברות של אספקה שאוחסנו לאחרונה plugin.provisioning.REMOVE_CREDENTIALS_MESSAGE=האם אתה בטוח כי ברצונך להסיר סיסמת אספקה? plugin.provisioning.PROV_FAILED=אספקה נכשלה @@ -1141,8 +1034,6 @@ net.java.sip.communicator.util.dns.ConfigurableDnssecResolver$DnssecDialogResult #plugin spellcheck plugin.spellcheck.TITLE=איות ודקדוק plugin.spellcheck.MENU=הצג איות ודקדוק -plugin.spellcheck.LANG=שפה -plugin.spellcheck.EDIT_PERSONAL_DICT=ערוך plugin.spellcheck.ENABLE_SPELL_CHECK=אפשר בדיקת איות plugin.spellcheck.dialog.FIND=מצא את הבא plugin.spellcheck.dialog.REPLACE=החלף -- cgit v1.1 From 40c1b40a8f4cbcaf7c79a7c4a6d0c13a2e403566 Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Thu, 19 Jan 2017 00:00:49 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 321 of 1505 strings translated (70 fuzzy). --- resources/languages/resources_sq.properties | 86 +++++++++-------------------- 1 file changed, 27 insertions(+), 59 deletions(-) diff --git a/resources/languages/resources_sq.properties b/resources/languages/resources_sq.properties index 51ca64d..b1bdff8 100644 --- a/resources/languages/resources_sq.properties +++ b/resources/languages/resources_sq.properties @@ -1,7 +1,18 @@ # Jitsi, the OpenSource Java VoIP and Instant Messaging client. # -# Distributable under LGPL license. -# See terms of license at gnu.org. +# Copyright @ 2015 Atlassian Pty Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # Translation files are automatically generated from: # @@ -32,30 +43,23 @@ service.gui.ACCOUNT_ME=Unë service.gui.ACCOUNT_REGISTRATION_WIZARD=Rexhistrimi i llogarisë service.gui.ACCOUNTS=Llogaritë service.gui.ADD=&Shto -service.gui.ADD_ACCOUNT=Shto llogari service.gui.ADD_CONTACT=&Shto kontakt service.gui.ADD_CONTACT_TO=&Shto kontakt service.gui.ADD_CONTACT_ERROR=Dështoj në shtimin e kontaktit me id: {0} service.gui.ADD_CONTACT_ERROR_TITLE=Gabim gjatë shtimit të kontaktit service.gui.ADD_CONTACT_EXIST_ERROR=Kontakti {0} ekziston në listën tuaj të kontakteve -service.gui.ADD_CONTACT_IDENTIFIER=Futni në fushën e mëposhtme informacionet e kontaktit të cilin ju dëshironi të shtoni. -service.gui.ADD_CONTACT_WIZARD=Ndihmesa për shtimin e kontaktit service.gui.ADD_GROUP_LOCAL_ERROR=Dështoj për të shtuar grupin me emrin: {0}. Problemi ka ndodhur gjatë një l/O (disku i plotë? Mungesa e të drejtave?). service.gui.ADD_GROUP_EXIST_ERROR=Grupi {0} ekziston në listën tuaj të kontaktit. Ju lutem zgjidhni një tjetër emër. service.gui.ADD_GROUP_NET_ERROR=Dështoj për të shtuar grupin me emrin: {0}. Problemi ka ndodhur për shkak të dështimit të rrjetit. Ju lutem kontrolloni lidhjen e rrjetit dhe provoni përsëri. service.gui.ADD_GROUP_ERROR=Dështoj për të shtuar grupin me emrin: {0}. service.gui.ADD_GROUP_EMPTY_NAME=Grupit duhet patjetër t´´i ipet një emër. -service.gui.ADD_GROUP=Krijo grup -service.gui.ADD_SUBCONTACT=&Shto subkontakt service.gui.ADMINISTRATOR=Administrator service.gui.ADVANCED=&Përparuar -service.gui.ALL=&Të gjitha service.gui.ALL_CONTACTS=&Të gjitha kontaktet service.gui.APPLY=&Apliko service.gui.ARE_NOW=Ju jeni tani {0} service.gui.AT=në service.gui.AUTHENTICATION_FAILED=Identifikimi ka dështuar. Fjalëkalimi që futët nuk është i vlefshëm -service.gui.AUTHENTICATION_REQUESTED=Kërkohet identifikimi service.gui.AUTHENTICATION_REQUESTED_SERVER=Serveri {0} ka kërkuar identifikimin tuaj. service.gui.AUTHENTICATION_WINDOW_TITLE={0} identifikimi service.gui.AUTHORIZATION_REQUESTED=Kërkohet autorizimi @@ -95,12 +99,10 @@ service.gui.CHAT_ROOM_USER_KICKED=është përjashtuar nga {0} service.gui.CHAT_ROOM_USER_QUIT=ka lënë {0} service.gui.CHAT_ROOM_NAME=Emri i dhomës së chat-it service.gui.ROOM_NAME=Dhoma e chat-it -service.gui.AUTOJOIN=Vetbashkim service.gui.CHAT_ROOM_NAME_INFO=Shkruani në fushën e mëposhtme emrin e dhomës chat, të cilën ju dëshironi për të krijuar. service.gui.CHAT_ROOM_NOT_EXIST=Dhoma {0} nuk u gjet në server {1}. Ju lutem verifikoni nëse emri që keni shtypur është i saktë. service.gui.CHAT_ROOM_NOT_CONNECTED=Ju duhet të hyni brenda (log in), në mënyrë që t''i bashkangjiteni dhomës së chat-it {0}. service.gui.CHAT_ROOM_LEAVE_NOT_CONNECTED=Ju duhet të hyni brenda (log in), për të lënë një chat-dhomë -service.gui.CHAT_ROOM_NOT_JOINED=Ju duhet t''i bashkangjiteni chat-dhomës, në mënyrë që të bëni operacione të mëtejshme në të. service.gui.CHAT_ROOM_OPTIONS=Mundësitë e chat-dhomës service.gui.CHAT_ROOM_REGISTRATION_REQUIRED=Chat-dhoma {0} kërkon që të regjistroheni, nëse doni t''i bashkangjiteni. service.gui.CHAT_ROOM_REQUIRES_PASSWORD=Chat-dhoma {0} kërkon një fjalkalim. @@ -114,9 +116,7 @@ service.gui.CONNECTING=Lidh... service.gui.CONNECTING_STATUS=Lidh service.gui.CONNECTING_EARLY_MEDIA_STATUS=Lidh* service.gui.CONNECTION=Lidhje -service.gui.CONNECTION_FAILED_MSG=Lidhja SSL dështoi për këtë llogari: Emri i përdoruesit: {0}, emri i Server: {1}. Ju lutem kontrolloni lidhjen e rrjetit ose kontaktoni administratorin e rrjetit për më shumë informacion. service.gui.CONNECTION_EXPIRED_MSG=Ju jeni shkyçur aktualisht nga server {0}. -service.gui.CONTACT_NOT_SUPPORTING_TELEPHONY=Kontakti i zgjedhur {0} nuk mbështetë telefoninë service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Kontakti i zgjedhur {0} nuk përkrah chat konferenca. service.gui.CONTACT_PAUSED_TYPING={0} ka ndaluar së shkruari mesazhin. service.gui.CONTACT_TYPING={0} është duke shkruar mesazh @@ -129,13 +129,10 @@ service.gui.CREATE_CHAT_ROOM=&Krijo chat-dhomë... service.gui.CREATE_CHAT_ROOM_ERROR=Nuk arriti të krijoj chat-dhomën {0}. service.gui.CREATE_CHAT_ROOM_WIZARD=Krijo chat-dhomë service.gui.CREATE_CONFERENCE_CALL=&Krijo një thirrje-konferencë... -service.gui.CREATE_CONFERENCE_CHAT=&Krijo një chat-konferencë... service.gui.CREATE_GROUP=&Krijo grup... service.gui.CREATE_GROUP_NAME=Në fushën e mëposhtme, shkruani emrin e grupit që doni të krijoni. -service.gui.CREATE_FIRST_GROUP_WIZARD=Lista juaj e kontakteve nuk përmban asnjë grup. Ju lutem krijoni një grup të parë (Skedar/Krijo grup). service.gui.CONTACT_INFO_NOT_SUPPORTED=Ky kontakt nuk mbështet informacionet e web-kontaktit service.gui.CUT=&Prerje -service.gui.DATE=Data service.gui.DELETE=Fshij service.gui.DESKTOP_SHARING_WARNING= Jeni i sigurt se doni te filloni ndarjen e ekranit?
    Duke klikuar OK, ju do lejoni të njerëzit e kësaj thirrjeje që të shohin ekranin tuaj. service.gui.DIALPAD=Tastiera për thirrje @@ -154,7 +151,6 @@ service.gui.ERROR_WAS=Gabimi ishte: {0} service.gui.ESTIMATED_TIME=koha e parashikuar: service.gui.EVENTS=Ndodhi service.gui.EXIT=D&alje -service.gui.EXTENDED_CRITERIA=Kritere të zgjëruara service.gui.GENERAL_ERROR=Gabim i përgjithshëm service.gui.GROUP_NAME=Emri i grupit service.gui.FAILED_STATUS=Thirrja dështoi @@ -207,7 +203,6 @@ service.gui.HIDE_OFFLINE_CONTACTS=Fshih kontaktet jashtë linje service.gui.HIDE_MAIN_WINDOW=
    Duke klikuar butonin X, nuk do të dilni nga programi, por vetëm
    fshehni atë. Nëse ju dëshironi të dilni nga programi zgjidhni Skedë/Dalje. service.gui.HISTORY=&Kronologjia service.gui.HISTORY_CONTACT=Kronologjia - {0} -service.gui.HOUR=Ora service.gui.IDENTIFIER=Identifikues service.gui.IGNORE=&Injorim service.gui.INSERT_SMILEY=Fut "smiley" @@ -225,7 +220,6 @@ service.gui.INVITE_REASON=Arsyeja e ftesës service.gui.IS_NOW={0} është tani {1} service.gui.JOIN=&Bashkangjitem service.gui.JOIN_AS=B&ashkangjitu si... -service.gui.CLOSE_CHAT_ROOM_DIALOG=M&byll service.gui.JOIN_CHAT_ROOM=&Bashkohu në chat-dhomë... service.gui.JOIN_CHAT_ROOM_TITLE=Bashkohu në chat-dhomë service.gui.JOIN_CHAT_ROOM_NAME=Ju lutem shkruani emrin e chat-dhomës ku ju doni për t''u bashkuar. @@ -235,7 +229,6 @@ service.gui.KICK_FAILED=Përjashtimi dështoi service.gui.KICK_FAILED_GENERAL_ERROR=Nuk arriti të përjashtoi {0}. Ka ndodhur një gabim i përgjithshëm në server. service.gui.KICK_FAILED_NOT_ALLOWED=Nuk arriti të përjashtoi {0}. Pronari dhe administratori i dhomës nuk mund të përjashtohen. service.gui.KICK_FAILED_NOT_ENOUGH_PERMISSIONS=Nuk arriti të përjashtoi {0}. Ju nuk posedoni të drejtat për të bërë këtë. -service.gui.LAST=I fundit service.gui.LEAVE=&Lë service.gui.LIMIT_REACHED_FOR_IP=Ju keni shumë regjistrime ekzistuese nga IP-adresa lokale dhe serveri {0} nuk lejon për të hapur më shumë prej tyre. service.gui.LOADING_ROOMS=Ngarkimi i dhomave... @@ -250,7 +243,6 @@ service.gui.MESSAGE=Mesazh service.gui.MISSED_CALLS_TOOL_TIP=Thirrjet e humbura nga: service.gui.MISSED_CALLS_MORE_TOOL_TIP= dhe {0} më shumë service.gui.MODERATOR=moderator -service.gui.MORE=Më shumë service.gui.MOVE=Çvendos service.gui.MOVE_SUBCONTACT=Çv&endos kontaktin service.gui.MOVE_SUBCONTACT_MSG=Zgjidhni kontaktin ose grupin, ku ju doni të çvendosni kontaktin e zgjedhur. @@ -258,7 +250,6 @@ service.gui.MOVE_SUBCONTACT_FAILED=Kontakti që ju keni zgjedhur është e njëj service.gui.MOVE_SUBCONTACT_QUESTION=Jeni i sigurt se doni të çvendosni {0} në {1}? service.gui.MOVE_TO_GROUP=Ç&vendose në grup service.gui.MOVE_CONTACT=Çvendos kontaktin -service.gui.MOVE_CONTACT_ERROR=&Kontakti nuk mund të çvendoset service.gui.MSG_DELIVERY_FAILURE=Mesazhi i mësipërm nuk u dorëzua service.gui.MSG_DELIVERY_NOT_SUPPORTED=Protokolli që ju jeni duke përdorur, nuk mbështet mesazhe offline. Ju mund të përpiqeni të dërgoni mesazhin me një tjetër protokoll ose prisni deri sa ai/ajo të vijë online. service.gui.MSG_DELIVERY_INTERNAL_ERROR=Ka ndodhur një gabim intern. Kjo është me siguri një difekt. Ju lutem raportoni ketu: http://www.sip-communicator.org/index.php/Development/BugsAndIssues. @@ -269,7 +260,6 @@ service.gui.MSG_NOT_POSSIBLE=Mesazhimi nuk është i mundur për këtë kontakt service.gui.MSG_RECEIVED={0} shkroi service.gui.MSG_SEND_CONNECTION_PROBLEM=Ju duhet të jeni i lidhur, për të qenë në gjendje që të dërgoni mesazhe. service.gui.MULTIPLE_LOGINS=Ju keni hyrë më shumë se një herë me të njëjtën llogari. Llogaria: Emri i përdoruesit: {0}, emri i server: {1} është shkëputur për momentin. -service.gui.MUTE=Pa zë service.gui.MUTUALLY_ON_HOLD_STATUS=Reciprokisht në pritje service.gui.NETWORK=Rrjeti service.gui.NETWORK_FAILURE=Gabim në rrjet @@ -289,7 +279,6 @@ service.gui.NON_EMPTY_CHAT_WINDOW_CLOSE=Ju doni të mbyllni bisedën dhe një me service.gui.NON_EXISTING_USER_ID=Serveri {0} nuk njeh përdoruesin e specifikuar. service.gui.OFFLINE=Jashtë linje service.gui.OK=&OK -service.gui.OLDER_CALLS=Thirrjet e vjetra service.gui.ONLINE=Në linjë service.gui.OPEN=Hap service.gui.OPEN_FILE_FROM_IMAGE=Klikody herë për të hap skedarin. @@ -297,7 +286,6 @@ service.gui.OPEN_FOLDER=Hap dosjen service.gui.OPEN_IN_BROWSER=Hape në &shfletues service.gui.OPTIONS=Mundësitë service.gui.OR=ose -service.gui.OR_ENTER_PHONE_NUMBER=Ose shkruani numrin e telefonit këtu ... service.gui.OWNER=Pronar i dhomës service.gui.PASSWORD=Fjalëkalimi service.gui.PASTE=&Ngjit @@ -305,7 +293,6 @@ service.gui.PORT=Porti service.gui.PRESENCE=Prania service.gui.PRESS_ENTER_FOR_SUGGESTIONS='Enter' për sygjerime service.gui.PREVIOUS=I mëparshëm -service.gui.PREVIOUS_TOOLTIP=Shfleto biseda të vjetra service.gui.PRINT=&Shtyp service.gui.PROACTIVE_NOTIFICATION=është duke shkruar mesath service.gui.PROTOCOL=Protokolli @@ -341,24 +328,16 @@ service.gui.REVOKE_ADMIN=Heqja e administratorit service.gui.REVOKE_MODERATOR=Heqja e moderatorit service.gui.REVOKE_MEMBERSHIP=Heqja e anëtarësimit service.gui.REVOKE_VOICE=Heqja e zërit -service.gui.ROOT_GROUP=Grupi bazë service.gui.SAVE=&Ruaj service.gui.SEARCH=&Kërko service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Klikoni butonin më poshtë për të treguar të gjithë chat-dhomat ekzistuese në serverin e përzgjedhur. Atëherë zgjidhni atë që ju doni t''i bashkoheni dhe klikoni butonin "Bashkangjitu". -service.gui.SELECT_ACCOUNT=Përzgjedh llogarinë service.gui.SELECT_COLOR=Përzgjedh ngjyrën service.gui.SELECT_GROUP=Përzgjedh grupin -service.gui.SELECT_GROUP_WIZARD_MSG=Lista e mëposhtme përmban të gjitha grupet në listën tuaj të kontaktit. Përzgjidhni një, ku ju dëshironi të shtoni kontakt të ri. service.gui.SELECT_NO_GROUP=S''ka grup -service.gui.SELECT_GROUP_WIZARD=Specifikoni grupin service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Lista e mëposhtme përmban të gjitha llogaritë që mbështesin funksionin e chat-iti për shumë përdorues. Përzgjedh llogarinë me të cilin ju dëshironi t''a krijoni chat-dhomën tuaj. -service.gui.SELECT_PROVIDERS_WIZARD_MSG=Lista e mëposhtme përmban të gjitha llogaritë e regjistruar. Përzgjedh llogarinë të cilën dëshironi t''a përdorni për të komunikuar me kontakt të ri. -service.gui.SELECT_PROVIDERS_WIZARD=Përzgjedh llogarinë service.gui.SEND=&Dërgo service.gui.SEND_FILE=Dërgo &skedar -service.gui.SELECT_CONTACT_SUPPORTING_INFO=Nuk ka asnjë informacion për këtë kontakt. service.gui.SEND_MESSAGE=&Dërgo një mesazh -service.gui.SEND_AS_SMS=Dërgo si SMS service.gui.SEND_SMS=Dë&rgo SMS service.gui.SEND_SMS_DETAILS=Mos harroni se ju duhet të shkruani numrin në format ndërkombëtare p.sh. duke filluar me 355 për Shqipëri për shembull, 35577000000 service.gui.SEND_SMS_NOT_SUPPORTED=Protokolli i përzgjedhur nuk mbështet dërgimin e mesazheve SMS. @@ -390,15 +369,18 @@ service.gui.STATUS_MESSAGE_INFO=Në fushën e mëposhtme ju mund të specifikoni service.gui.STOP_SHARING=Ndal ndarjen service.gui.SUBJECT=Subjekti service.gui.SUMMARY=Përmbledhje -service.gui.TODAY=Sot service.gui.VOICEMAIL_NO_MESSAGES=Asnjë mesazh +#enum values from IceProcessingState + + + +#service.gui.CERT_INFO_ are combined from Rdn names -service.gui.security.COMPARE_WITH_PARTNER=Krahaso me partnerin dhe klikoni dryrin për të konfirmuar. # keep the following string short service.gui.security.COMPARE_WITH_PARTNER_SHORT=Krahaso me partnerin: {0} @@ -407,9 +389,6 @@ service.gui.avatar.imagepicker.CANCEL=&Anulo -# impl.protocol.ssh -#Contact Details Seperator(must not be part of contact data stored as persistent -# data) # systray @@ -418,17 +397,19 @@ service.gui.avatar.imagepicker.CANCEL=&Anulo # LDAP impl.ldap.EDIT=&Redakto -impl.ldap.REMOVE=&Largo impl.ldap.SAVE=&Ruaj impl.ldap.CANCEL=&Anulo impl.ldap.SERVER_PORT=Porti impl.ldap.PASSWORD=Fjalëkalimi +# SIP Protocol + +#Jabber Protocol + # Address book plugin # Google Contacts impl.googlecontacts.EDIT=&Redakto -impl.googlecontacts.REMOVE=&Largo impl.googlecontacts.SAVE=&Ruaj impl.googlecontacts.CANCEL=&Anulo impl.googlecontacts.PASSWORD=Fjalëkalimi @@ -444,9 +425,6 @@ impl.googlecontacts.PASSWORD=Fjalëkalimi # branding plugin.branding.ABOUT_MENU_ENTRY=&Rreth -# Dict protocol - -# facebookaccregwizz # generalconfig plugin.generalconfig.SHOW_HISTORY=Shfaq @@ -459,22 +437,16 @@ plugin.generalconfig.SHOW_HISTORY=Shfaq # jabber accregwizz -# mailbox - -# msn accregwizz - # plugin manager # simple accregwizz # sipaccregwizz plugin.sipaccregwizz.XCAP_PASSWORD=Fjalëkalimi +#used from SecurityPanel # skin manager -# ssh accregwizz -plugin.sshaccregwizz.OPTIONAL=Mundësitë - # status update # updatechecker @@ -487,26 +459,23 @@ plugin.whiteboard.OPEN=Hap plugin.whiteboard.COLOR=Me ngjyra plugin.whiteboard.DELETE=Fshij -# yahoo accregwizz - -# zero accregwizz - # gtalk accregwizz # iptel accregwizz -# sip2sip accregwizz - # ippi accregwizz # key binding chooser +#in new ChatWindow() -> manipulated plugin.keybindings.CHAT_COPY=&Kopjo plugin.keybindings.CHAT_CUT=&Prerje plugin.keybindings.CHAT_PASTE=&Ngjit plugin.keybindings.MAIN_RENAME=Rie&mërto kontaktin +#Enum KeybindingSet.Category plugin.keybindings.CHAT=Chat # Notification Configuration Form +#NotificationsTable constants plugin.notificationconfig.event.IncomingCall=Thirrje e ardhur plugin.notificationconfig.event.IncomingFile=Thirrje e ardhur plugin.notificationconfig.event.HangUp=Ul receptorin e telefonit @@ -522,6 +491,7 @@ impl.media.security.zrtp.TITLE=Thirrje +#in JNIEncoder # The callrecordingconfig plugin was never really committed into trunk and its # ConfigurationForm was actually put in the neomedia bundle. @@ -530,7 +500,6 @@ impl.media.security.zrtp.TITLE=Thirrje plugin.securityconfig.masterpassword.TITLE=Fjalëkalimi plugin.securityconfig.masterpassword.REENTER_PASSWORD=Mbaj mend fjalëkalimin plugin.securityconfig.masterpassword.COL_PASSWORD=Fjalëkalimi -plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=&Largo # otr plugin plugin.otr.authbuddydialog.CANCEL=&Anulo @@ -559,7 +528,6 @@ plugin.dnsconfig.lblBackupPort.text=Porti net.java.sip.communicator.util.dns.SecureResolveMode.IgnoreDnssec=&Injorim #plugin spellcheck -plugin.spellcheck.EDIT_PERSONAL_DICT=&Redakto #Certificate configuration plugin -- cgit v1.1 From cf6951b80e0ef9fe04fcd91f946c464145de683f Mon Sep 17 00:00:00 2001 From: acastroy Date: Thu, 19 Jan 2017 02:17:34 +0000 Subject: Commit from translate.jitsi.org by user acastroy.: 1655 of 1655 strings translated (0 fuzzy). --- resources/languages/resources_es.properties | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/resources/languages/resources_es.properties b/resources/languages/resources_es.properties index 28b5083..d8a746e 100644 --- a/resources/languages/resources_es.properties +++ b/resources/languages/resources_es.properties @@ -150,6 +150,7 @@ service.gui.CLEAR=Vaciar service.gui.CLOSE=Cerra&r service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Recibió un nuevo mensaje hace menos de 2 segundos. ¿Está seguro de querer abandonar esta sala de chat? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=Tiene transferencias de archivos activas. ¿Está seguro que desea cancelarlas? +service.gui.CONFIRM=Confirmar service.gui.CONNECTED_STATUS=Conectado service.gui.CONNECTING=Conectando... service.gui.CONNECTING_STATUS=Conectando @@ -470,6 +471,7 @@ service.gui.SEARCH=&Buscar service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Presione el botón para mostrar todas las salas de conversación existentes en el servidor seleccionado. Después seleccione aquella a la que desea conectarse y presione el botón Entrar. service.gui.SEARCH_STRING_CONTACT_SOURCE=Contacto buscado service.gui.SECURITY=Seguridad +service.gui.SELECT_ACCOUNT=Seleccionar cuenta de usuario service.gui.SELECT_ACCOUNT_INFO=¿Cual cuenta desea utilizar para comunicarse con este contacto? service.gui.SELECT_COLOR=Seleccionar color service.gui.SELECT_GROUP=Seleccione un grupo @@ -648,6 +650,7 @@ service.gui.callinfo.ICE_STATE.WAITING=Reuniendo candidatos service.gui.callinfo.ICE_STATE.RUNNING=Revise conectividad service.gui.callinfo.ICE_STATE.COMPLETED=Terminado service.gui.callinfo.ICE_STATE.FAILED=Falló +service.gui.callinfo.ICE_STATE.TERMINATED=Finalizado service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=IP local / Puerto service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=IP Local reflexiva / Puerto @@ -747,6 +750,12 @@ service.gui.security.encryption.required=¡Cifrado requerido! service.protocol.ICE_FAILED=No se pudo establecer una conexión (falló ICE y no se encontró relé) +service.systray.MODE=Modo bandeja +service.systray.mode.NATIVE=Predeterminado +service.systray.mode.DISABLED=Desactivado +service.systray.mode.APPINDICATOR=AppIndicator (Unity, KDE, not plain Gnome 3; puede fallar en Debian) +service.systray.mode.APPINDICATOR_STATIC=AppIndicator Estático (sin menú de estado de la cuenta) +service.systray.CLI_NOTE=Si su elección no funciona, puede iniciar {0} con la opción "--notray". Esta opción va a forzar el modo de bandeja como "Desactivado" y muestra la Interfaz gráfica. Cambiar la implementación de la bandeja requiere reiniciar. impl.protocol.sip.XCAP_ERROR_TITLE=Error en almacenamiento de lista de contactos SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=No se pueden leer los recusros {0}. De {1} @@ -898,6 +907,7 @@ plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=En el caso de no disponer de una plugin.branding.ABOUT_WINDOW_TITLE=Acerca de {0} plugin.branding.LOGO_MESSAGE=VoIP && Mensajería Instantánea. plugin.branding.ABOUT_MENU_ENTRY=&Acerca de +plugin.branding.COPYRIGHT_LICENSE=
    Copyright 2003-{1} {3}, Todos los derechos reservados.

    {4} es distribuido bajo los términos de {6}.
    plugin.busylampfield.PICKUP=Tomar llamada @@ -940,6 +950,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Suponer siempre la pérdida plugin.generalconfig.SILK_SAT=Umbral de actividad de voz (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Anunciar soporte a FEC en SDP: plugin.generalconfig.RESTORE=Restaurar opciones predeterminadas +plugin.generalconfig.MINIMIZE_NOT_HIDE=Minimizar la ventana principal en lugar cerrarla o esconderla # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish @@ -982,6 +993,7 @@ plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=El protocolo XMPP plugin.jabberaccregwizz.USERNAME=Nombre de usuario XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Confirmar contraseña +plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID y Contraseña plugin.jabberaccregwizz.CSERVER=Servidor plugin.jabberaccregwizz.SERVER=Conectar al servidor plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Activar mantener vivo @@ -999,6 +1011,7 @@ plugin.jabberaccregwizz.AUTORESOURCE=Auto generar recurso plugin.jabberaccregwizz.PRIORITY=Prioridad plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Error desconocido de XMPP ({0}). Verifique que el nombre del servidor es correcto. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Sus contraseñas no coinciden. +plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Modificar las opciones predeterminadas del servidor plugin.jabberaccregwizz.USE_ICE=Usar ICE plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Auto descubrir servidores STUN/TURN plugin.jabberaccregwizz.SUPPORT_TURN=Soporte TURN @@ -1045,6 +1058,7 @@ plugin.jabberaccregwizz.DISABLE_JINGLE=Desactivar Jingle (llamadas de audio y v # plugin manager plugin.pluginmanager.INSTALL=Instalar plugin.pluginmanager.UNINSTALL=Desinstalar +plugin.pluginmanager.UPDATE=Actualizar plugin.pluginmanager.PLUGINS=Módulos plugin.pluginmanager.URL=URL plugin.pluginmanager.CHOOSE_FILE=Seleccionar archivo @@ -1199,6 +1213,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Cuenta ippi existente plugin.ippiaccregwizz.CREATE_ACCOUNT=Crear una cuenta ippi gratuita # key binding chooser +plugin.keybindings.WAITING=Pulsar acceso rápido... #in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Cerrar ventana de charla plugin.keybindings.CHAT_COPY=Copiar @@ -1401,6 +1416,7 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Contraseña plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(desconocido) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(no puede descifrarse) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Contraseñas almacenadas +plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Eliminar plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Eliminar todo plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=¿Está seguro que desea eliminar todas las contraseñas? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Eliminar todas las contraseñas @@ -1496,6 +1512,7 @@ plugin.globalproxy.PROXY_PORT=Puerto del proxy plugin.globalproxy.PROXY_USERNAME=Usuario del Proxy plugin.globalproxy.PROXY_PASSWORD=Contraseña del Proxy plugin.globalproxy.DESCRIPTION={0} usará la configuración del proxy para todas las redes a las que está conectado o se conecte de ahora en adelante. \nEl soporte de proxy es experimental y solo funciona con algunos protocolos. Revise la siguiente tabla para más detalles: +plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Auth HTTP HTTP+Auth
    XMPP++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Proxy también de DNS plugin.globalproxy.FWD_DNS_NOTE=Es útil con Tor. Ayuda a evitar las fuga de DNS mediante el envío de todo el tráfico de DNS al proxy de Tor. Requiere reiniciar. -- cgit v1.1 From 7d66da61b316c9480b63000f831b6de723b87315 Mon Sep 17 00:00:00 2001 From: damencho Date: Thu, 26 Jan 2017 17:00:46 -0600 Subject: Checks from for received carbon messages, should be bare jid. --- .../jabber/OperationSetBasicInstantMessagingJabberImpl.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java index f055613..2f35fef 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java @@ -815,6 +815,17 @@ public class OperationSetBasicInstantMessagingJabberImpl ForwardedPacketExtension.class); if(extensions.isEmpty()) return; + + // according to xep-0280 all carbons should come from + // our bare jid + if (!msg.getFrom().equals( + StringUtils.parseBareAddress( + jabberProvider.getOurJID()))) + { + logger.info("Received a carbon copy with wrong from!"); + return; + } + ForwardedPacketExtension forwardedExt = extensions.get(0); msg = forwardedExt.getMessage(); if(msg == null || msg.getBody() == null) -- cgit v1.1 From 589bd9ffd7f27e1ac8cba2f14c55fd94ccc95a66 Mon Sep 17 00:00:00 2001 From: damencho Date: Thu, 26 Jan 2017 17:22:22 -0600 Subject: Updates jre to 1.8.0_121. --- resources/install/installers.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/install/installers.properties b/resources/install/installers.properties index 309597e..05701e5 100644 --- a/resources/install/installers.properties +++ b/resources/install/installers.properties @@ -13,7 +13,7 @@ windows.jre64.file=C:\\Install\\jre-7u17-windows-x64.exe # Paths to the ZIP files of private extracted Windows JRE setups to be deployed # as part of the respective setups of SIP Communicator. -windows.jre.zip=C:\\Install\\jre-8u101-windows-i586.zip -windows.jre64.zip=C:\\Install\\jre-8u101-windows-x64.zip +windows.jre.zip=C:\\Install\\jre-8u121-windows-i586.zip +windows.jre64.zip=C:\\Install\\jre-8u121-windows-x64.zip -macosx.jre=${user.home}/bin/jre1.8.0_101.jre +macosx.jre=${user.home}/bin/jre1.8.0_121.jre -- cgit v1.1 From 695cc916086284c23626b11657f8271a96cf46ab Mon Sep 17 00:00:00 2001 From: damencho Date: Mon, 30 Jan 2017 18:05:02 -0600 Subject: Updates developer id that is used to sign dmg. --- resources/install/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/install/build.xml b/resources/install/build.xml index 41624fa..98202f8 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -1758,7 +1758,7 @@ - + -- cgit v1.1 From bc3f0942854004a228ecb8aa7678496ec0b3e14e Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 31 Jan 2017 10:17:07 -0600 Subject: Splits jitsi-lgpl-dependencies into two jars. --- build.xml | 1 + lib/felix.client.run.properties | 3 ++- lib/felix.unit.test.properties | 3 ++- .../jitsi-gpl-dependencies-1.0-SNAPSHOT.jar | Bin 0 -> 7862639 bytes .../jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar | Bin 7903428 -> 46467 bytes 5 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 lib/installer-exclude/jitsi-gpl-dependencies-1.0-SNAPSHOT.jar diff --git a/build.xml b/build.xml index b7e8efb..0f9cb92 100644 --- a/build.xml +++ b/build.xml @@ -981,6 +981,7 @@ + diff --git a/lib/felix.client.run.properties b/lib/felix.client.run.properties index d5d8889..c9cb60b 100644 --- a/lib/felix.client.run.properties +++ b/lib/felix.client.run.properties @@ -39,7 +39,8 @@ felix.auto.start.5=reference:file:sc-bundles/splash-screen.jar felix.auto.install.10= \ reference:file:sc-bundles/fmj.jar \ reference:file:sc-bundles/slf4j-jdk14.jar \ - reference:file:sc-bundles/jitsi-lgpl-dependencies.jar + reference:file:sc-bundles/jitsi-lgpl-dependencies.jar \ + reference:file:sc-bundles/jitsi-gpl-dependencies.jar felix.auto.start.10= \ reference:file:lib/bundle/org.apache.felix.bundlerepository-1.6.4.jar \ diff --git a/lib/felix.unit.test.properties b/lib/felix.unit.test.properties index e8df121..e97d3b1 100644 --- a/lib/felix.unit.test.properties +++ b/lib/felix.unit.test.properties @@ -51,7 +51,8 @@ org.osgi.framework.system.packages.extra= \ felix.auto.install.10= \ reference:file:sc-bundles/fmj.jar \ reference:file:sc-bundles/slf4j-jdk14.jar \ - reference:file:sc-bundles/jitsi-lgpl-dependencies.jar + reference:file:sc-bundles/jitsi-lgpl-dependencies.jar \ + reference:file:sc-bundles/jitsi-gpl-dependencies.jar felix.auto.start.10= \ reference:file:lib/bundle/junit.jar \ diff --git a/lib/installer-exclude/jitsi-gpl-dependencies-1.0-SNAPSHOT.jar b/lib/installer-exclude/jitsi-gpl-dependencies-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..39091c8 Binary files /dev/null and b/lib/installer-exclude/jitsi-gpl-dependencies-1.0-SNAPSHOT.jar differ diff --git a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar index 36202ae..07d4ec4 100644 Binary files a/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar and b/lib/installer-exclude/jitsi-lgpl-dependencies-1.0-SNAPSHOT.jar differ -- cgit v1.1 From 5f1e554873aad4659a636da9113ec2a254ce2c5a Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Thu, 2 Feb 2017 08:23:40 +0100 Subject: Update libjitsi Closes #314 jitsi/libjitsi@38a40f6557be8f1be63be446bf320bc3b4f0fe1c Jenkins build 925 --- .classpath | 2 +- build.xml | 2 +- .../libjitsi-1.0-20170110.164740-224.jar | Bin 9007861 -> 0 bytes .../libjitsi-1.0-20170201.212655-235.jar | Bin 0 -> 9011068 bytes m2/pom.xml | 2 +- nbproject/project.xml | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar diff --git a/.classpath b/.classpath index 0e8169c..dd72396 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index 0f9cb92..124c639 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar b/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar deleted file mode 100644 index 4c55d46..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar b/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar new file mode 100644 index 0000000..bbcf1c6 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar differ diff --git a/m2/pom.xml b/m2/pom.xml index b74b656..3cd9f0e 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -52,7 +52,7 @@ ${project.groupId} libjitsi - 1.0-20160707.163121-175 + 1.0-20170201.212655-235 ${project.groupId} diff --git a/nbproject/project.xml b/nbproject/project.xml index 979d765..719b909 100644 --- a/nbproject/project.xml +++ b/nbproject/project.xml @@ -116,7 +116,7 @@ src - lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170110.164740-224.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light-4.1.0-jitsi-1-SNAPSHOT.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar + lib/felix.jar:lib/bundle/commons-logging.jar:lib/bundle/junit.jar:lib/bundle/log4j.jar:lib/installer-exclude/apache-ant-1.7.0.jar:lib/installer-exclude/dhcp4java-1.00.jar:lib/installer-exclude/dict4j.jar:lib/installer-exclude/dnsjava.jar:lib/installer-exclude/fmj.jar:lib/installer-exclude/forms-1.2.1.jar:lib/installer-exclude/gdata-client-1.0.jar:lib/installer-exclude/gdata-client-meta-1.0.jar:lib/installer-exclude/gdata-contacts-3.0.jar:lib/installer-exclude/gdata-contacts-meta-3.0.jar:lib/installer-exclude/gdata-core-1.0.jar:lib/installer-exclude/google-collect-1.0-rc1.jar:lib/installer-exclude/hexdump-0.2.jar:lib/installer-exclude/httpclient-osgi-4.2.3.jar:lib/installer-exclude/httpcore-osgi-4.2.3.jar:lib/installer-exclude/ice4j-2.0-20170111.193659-7.jar:lib/installer-exclude/irc-api-1.0.jar:lib/installer-exclude/jain-sdp.jar:lib/installer-exclude/jain-sip-api.jar:lib/installer-exclude/jain-sip-ri.jar:lib/installer-exclude/jdic_misc.jar:lib/installer-exclude/jmdns.jar:lib/installer-exclude/jmyspell-core.jar:lib/installer-exclude/jna.jar:lib/installer-exclude/jnsapi.jar:lib/installer-exclude/joscar-client.jar:lib/installer-exclude/joscar-common.jar:lib/installer-exclude/joscar-protocol.jar:lib/installer-exclude/jsch-0.1.36.jar:lib/installer-exclude/jsocks-klea.jar:lib/installer-exclude/json-simple-1.1.1.jar:lib/installer-exclude/jspeex.jar:lib/installer-exclude/junit.jar:lib/installer-exclude/laf-widget.jar:lib/installer-exclude/lcrypto-jdk16-143.jar:lib/installer-exclude/libdbus-java-2.7.jar:lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar:lib/installer-exclude/log4j-1.2.8.jar:lib/installer-exclude/lti-civil-no_s_w_t.jar:lib/installer-exclude/mac_widgets-0.9.5.jar:lib/installer-exclude/nist-sdp-1.0.jar:lib/installer-exclude/otr4j.jar:lib/installer-exclude/pircbot.jar:lib/installer-exclude/profiler4j-1.0-beta3-SC.jar:lib/installer-exclude/sdes4j.jar:lib/installer-exclude/smack.jar:lib/installer-exclude/smackx.jar:lib/installer-exclude/swing-worker-1.2.jar:lib/installer-exclude/jna-platform.jar:lib/installer-exclude/unix-0.5.jar:lib/installer-exclude/weupnp-0.1.4.jar:lib/installer-exclude/zrtp4j-light-4.1.0-jitsi-1-SNAPSHOT.jar:lib/installer-exclude/jcalendar-1.4.jar:lib/installer-exclude/bcpkix-jdk15on-151.jar:lib/installer-exclude/bcprov-jdk15on-151.jar:lib/installer-exclude/guava-15.0.jar:lib/installer-exclude/libphonenumber-5.9.jar:lib/installer-exclude/commons-lang3-3.1.jar:lib/installer-exclude/jmork-1.0.5-SNAPSHOT.jar:lib/os-specific/mac/growl4j.jar:lib/os-specific/mac/OrangeExtensions.jar:lib/os-specific/mac/installer-exclude/dock.jar classes 1.5 -- cgit v1.1 From 4cadefa229614c208df9669fe11e0ef017a890f2 Mon Sep 17 00:00:00 2001 From: damencho Date: Sat, 4 Feb 2017 18:22:36 +0100 Subject: Changes version to 2.10. --- src/net/java/sip/communicator/impl/version/VersionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/version/VersionImpl.java b/src/net/java/sip/communicator/impl/version/VersionImpl.java index 8bed4ec..e9de87f 100644 --- a/src/net/java/sip/communicator/impl/version/VersionImpl.java +++ b/src/net/java/sip/communicator/impl/version/VersionImpl.java @@ -42,7 +42,7 @@ public class VersionImpl * number changes when a relatively extensive set of new features and * possibly rearchitecturing have been applied to the Jitsi. */ - public static final int VERSION_MINOR = 9; + public static final int VERSION_MINOR = 10; /** * Indicates whether this version represents a prerelease (i.e. a -- cgit v1.1 From 2b1dc3757081dd582049fb16a8421f486ae162df Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 7 Feb 2017 13:22:23 +0200 Subject: Changes version to 2.11. Closes #203. --- src/net/java/sip/communicator/impl/version/VersionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/java/sip/communicator/impl/version/VersionImpl.java b/src/net/java/sip/communicator/impl/version/VersionImpl.java index e9de87f..74e199c 100644 --- a/src/net/java/sip/communicator/impl/version/VersionImpl.java +++ b/src/net/java/sip/communicator/impl/version/VersionImpl.java @@ -42,7 +42,7 @@ public class VersionImpl * number changes when a relatively extensive set of new features and * possibly rearchitecturing have been applied to the Jitsi. */ - public static final int VERSION_MINOR = 10; + public static final int VERSION_MINOR = 11; /** * Indicates whether this version represents a prerelease (i.e. a -- cgit v1.1 From df85ae417f865bf392f92913fde858d777af7811 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 7 Feb 2017 22:27:54 +0200 Subject: Updates libjitsi and sends hole punch packets for audio. When sending hole punch packets, use as a content a generated rtp packet. --- .classpath | 2 +- build.xml | 2 +- .../libjitsi-1.0-20170201.212655-235.jar | Bin 9011068 -> 0 bytes .../libjitsi-1.0-20170207.194207-242.jar | Bin 0 -> 9014770 bytes .../protocol/media/CallPeerMediaHandler.java | 30 ++++++++++++++++++--- .../service/protocol/media/TransportManager.java | 21 ++++++++++++++- 6 files changed, 48 insertions(+), 7 deletions(-) delete mode 100644 lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar create mode 100644 lib/installer-exclude/libjitsi-1.0-20170207.194207-242.jar diff --git a/.classpath b/.classpath index dd72396..e368438 100755 --- a/.classpath +++ b/.classpath @@ -55,7 +55,7 @@ - + diff --git a/build.xml b/build.xml index 124c639..c43b7e8 100644 --- a/build.xml +++ b/build.xml @@ -978,7 +978,7 @@ - + diff --git a/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar b/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar deleted file mode 100644 index bbcf1c6..0000000 Binary files a/lib/installer-exclude/libjitsi-1.0-20170201.212655-235.jar and /dev/null differ diff --git a/lib/installer-exclude/libjitsi-1.0-20170207.194207-242.jar b/lib/installer-exclude/libjitsi-1.0-20170207.194207-242.jar new file mode 100644 index 0000000..a8ca832 Binary files /dev/null and b/lib/installer-exclude/libjitsi-1.0-20170207.194207-242.jar differ diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java index c8a3a12..ead01d1 100644 --- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java +++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java @@ -87,6 +87,16 @@ public abstract class CallPeerMediaHandler> public static final String VIDEO_REMOTE_SSRC = "VIDEO_REMOTE_SSRC"; /** + * The initial content of a hole punch packet. It has some fields pre-set. + * Like rtp verion, sequence number and timestamp. + */ + private static final byte[] HOLE_PUNCH_PACKET = + { + (byte)0x80, 0x00, 0x02, (byte)0x9E, 0x00, 0x09, + (byte)0xD0, (byte)0x80, 0x00, 0x00, 0x00, (byte)0x00, + }; + + /** * List of advertised encryption methods. Indicated before establishing the * call. */ @@ -1575,11 +1585,21 @@ public abstract class CallPeerMediaHandler> * to open port on NAT or RTP proxy if any. In order to be really efficient, * this method should be called after we send our offer or answer. * - * @param target MediaStreamTarget + * @param stream MediaStream non-null stream + * @param mediaType MediaType */ - protected void sendHolePunchPacket(MediaStreamTarget target) + protected void sendHolePunchPacket(MediaStream stream, MediaType mediaType) { - getTransportManager().sendHolePunchPacket(target, MediaType.VIDEO); + // send as a hole punch packet a constructed rtp packet + // has the correct payload type and ssrc + RawPacket packet = new RawPacket( + HOLE_PUNCH_PACKET, 0, RawPacket.FIXED_HEADER_SIZE); + packet.setPayloadType( + dynamicPayloadTypes.getPayloadType(stream.getFormat())); + packet.setSSRC((int)stream.getLocalSourceID()); + + getTransportManager().sendHolePunchPacket( + stream.getTarget(), mediaType, packet); } /** @@ -1936,6 +1956,8 @@ public abstract class CallPeerMediaHandler> stream.getTarget(), MediaType.AUDIO); stream.start(); + + sendHolePunchPacket(stream, MediaType.AUDIO); } stream = getStream(MediaType.VIDEO); @@ -1964,7 +1986,7 @@ public abstract class CallPeerMediaHandler> * send the hole-punch packet anyway to let the remote video * reach this local peer. */ - sendHolePunchPacket(stream.getTarget()); + sendHolePunchPacket(stream, MediaType.VIDEO); } } } diff --git a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java index a8222e0..051a302 100644 --- a/src/net/java/sip/communicator/service/protocol/media/TransportManager.java +++ b/src/net/java/sip/communicator/service/protocol/media/TransportManager.java @@ -516,6 +516,21 @@ public abstract class TransportManager> */ public void sendHolePunchPacket(MediaStreamTarget target, MediaType type) { + this.sendHolePunchPacket(target, type, null); + } + + /** + * Sends empty UDP packets to target destination data/control ports in order + * to open ports on NATs or and help RTP proxies latch onto our RTP ports. + * + * @param target MediaStreamTarget + * @param type the {@link MediaType} of the connector we'd like to send the + * hole punching packet through. + * @param packet (optional) use a pre-generated packet that will be sent + */ + public void sendHolePunchPacket( + MediaStreamTarget target, MediaType type, RawPacket packet) + { logger.info("Send NAT hole punch packets"); //check how many hole punch packets we would be supposed to send: @@ -536,7 +551,11 @@ public abstract class TransportManager> if(connector.getProtocol() == StreamConnector.Protocol.TCP) return; - byte[] buf = new byte[0]; + byte[] buf; + if (packet != null) + buf = packet.getBuffer(); + else + buf = new byte[0]; synchronized(connector) { -- cgit v1.1 From c60b2ef7b5a740c431fce8c82797e90480ad39b8 Mon Sep 17 00:00:00 2001 From: damencho Date: Tue, 7 Feb 2017 22:31:14 +0200 Subject: Updates libjitsi in pom. --- m2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m2/pom.xml b/m2/pom.xml index 3cd9f0e..931a7eb 100644 --- a/m2/pom.xml +++ b/m2/pom.xml @@ -52,7 +52,7 @@ ${project.groupId} libjitsi - 1.0-20170201.212655-235 + 1.0-20170207.194207-242 ${project.groupId} -- cgit v1.1 From 9369258b0ea73762ef643819a6e7d2a7bae4f90f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Wed, 8 Feb 2017 22:38:41 +0100 Subject: Register Jitsi for URL actions in Windows 10 --- resources/install/windows/SCRegistrySpec.wxi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/install/windows/SCRegistrySpec.wxi b/resources/install/windows/SCRegistrySpec.wxi index f891002..36069de 100644 --- a/resources/install/windows/SCRegistrySpec.wxi +++ b/resources/install/windows/SCRegistrySpec.wxi @@ -26,7 +26,10 @@ Guid="5798BE9D-AEA5-4DA8-992E-EEAD03D7E4CB" Win64="no"> - + + + + @@ -170,7 +173,10 @@ Guid="3de76b6b-90b9-403d-82ac-51d841ea95af" Win64="yes"> - + + + + -- cgit v1.1 From f6f8783930083e164893721066f4d7299caf8d7e Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Fri, 24 Feb 2017 07:56:13 +0100 Subject: Fix handling of sip: URIs Closes #315 --- .../communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java index a2a98b8..927c0a3 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java @@ -2465,6 +2465,8 @@ public class ProtocolProviderServiceSipImpl uriStr = uriStr.substring("callto:".length()); else if(uriStr.toLowerCase().startsWith("sips:")) uriStr = uriStr.substring("sips:".length()); + else if(uriStr.toLowerCase().startsWith("sip:")) + uriStr = uriStr.substring("sip:".length()); String user = uriStr; String remainder = ""; -- cgit v1.1 From 8aacaf46e1553269e8f19076a33072b148ceb051 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 27 Feb 2017 08:10:41 +0100 Subject: Add UI option to disable Outlook Calendar presence integration Closes #289 --- resources/languages/resources.properties | 1 + .../plugin/addrbook/AdvancedConfigForm.java | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 4897b99..bc39d06 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -860,6 +860,7 @@ impl.protocol.jabber.INVALID_ADDRESS=''{0}'' is not a valid XMPP JID. plugin.addrbook.ADDRESS_BOOKS=Address book plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK=Enable MacOSX Address Book search plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK=Enable Microsoft Outlook search +plugin.addrbook.ENABLE_OUTLOOK_CALENDAR=Disable setting presence using the Microsoft Outlook Calendar plugin.addrbook.DESCRIPTION=If enabled everything you type in the search field \ of the contact list will be also searched in your system address book and all \ matching contacts from your address book will appear in your contact list. diff --git a/src/net/java/sip/communicator/plugin/addrbook/AdvancedConfigForm.java b/src/net/java/sip/communicator/plugin/addrbook/AdvancedConfigForm.java index 402f549..85ccd76 100644 --- a/src/net/java/sip/communicator/plugin/addrbook/AdvancedConfigForm.java +++ b/src/net/java/sip/communicator/plugin/addrbook/AdvancedConfigForm.java @@ -25,6 +25,7 @@ import javax.swing.*; import net.java.sip.communicator.plugin.addrbook.macosx.*; import net.java.sip.communicator.plugin.addrbook.msoutlook.*; import net.java.sip.communicator.plugin.desktoputil.*; +import net.java.sip.communicator.service.calendar.CalendarService; import org.jitsi.util.*; @@ -67,13 +68,16 @@ public class AdvancedConfigForm if (OSUtils.IS_MAC) propertiesPanel.add(createEnableCheckBox( AddrBookActivator.PNAME_ENABLE_MACOSX_ADDRESS_BOOK_SEARCH, - "plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK")); + "plugin.addrbook.ENABLE_MACOSX_ADDRESSBOOK", true)); if (OSUtils.IS_WINDOWS) { propertiesPanel.add(createEnableCheckBox( AddrBookActivator.PNAME_ENABLE_MICROSOFT_OUTLOOK_SEARCH, - "plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK")); + "plugin.addrbook.ENABLE_MICROSOFT_OUTLOOK", true)); + propertiesPanel.add(createEnableCheckBox( + CalendarService.PNAME_FREE_BUSY_STATUS_DISABLED, + "plugin.addrbook.ENABLE_OUTLOOK_CALENDAR", false)); if(AddrBookActivator.getConfigService().getBoolean( AddrBookActivator.PNAME_ENABLE_DEFAULT_IM_APPLICATION_CHANGE, true)) @@ -95,13 +99,14 @@ public class AdvancedConfigForm * @return the created enable check box */ private Component createEnableCheckBox(final String configPropName, - String labelNameKey) + String labelNameKey, + boolean defaultValue) { final JCheckBox checkBox = new SIPCommCheckBox(AddrBookActivator .getResources().getI18NString( labelNameKey), AddrBookActivator.getConfigService().getBoolean(configPropName, - true)); + defaultValue)); checkBox.setAlignmentX(Component.LEFT_ALIGNMENT); checkBox.addActionListener(new ActionListener() @@ -113,9 +118,15 @@ public class AdvancedConfigForm new Boolean(checkBox.isSelected()).toString()); if (checkBox.isSelected()) + { AddrBookActivator.startService(); + AddrBookActivator.startCalendarService(); + } else + { AddrBookActivator.stopService(); + AddrBookActivator.stopCalendarService(); + } } }); return checkBox; -- cgit v1.1 From 7be70744f53b5a8f5b6388c9f14c34730f22a7f6 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Tue, 28 Feb 2017 08:22:25 +0100 Subject: Fix Voicemail URI editing in UI Closes #333 --- .../protocol/sip/SIPAccountRegistration.java | 38 +++++++++++++++------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/net/java/sip/communicator/service/protocol/sip/SIPAccountRegistration.java b/src/net/java/sip/communicator/service/protocol/sip/SIPAccountRegistration.java index 9719b8c..5355855 100644 --- a/src/net/java/sip/communicator/service/protocol/sip/SIPAccountRegistration.java +++ b/src/net/java/sip/communicator/service/protocol/sip/SIPAccountRegistration.java @@ -24,7 +24,7 @@ import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; import org.jitsi.service.neomedia.*; - +import org.jitsi.util.StringUtils; import org.osgi.framework.*; /** @@ -257,23 +257,37 @@ public class SIPAccountRegistration encodingsRegistration.storeProperties(this.accountProperties); - if (isModification) + if(isMessageWaitingIndicationsEnabled()) { - if (isMessageWaitingIndicationsEnabled()) + if(!StringUtils.isNullOrEmpty(getVoicemailURI(), true)) + accountProperties.put( + ProtocolProviderFactory.VOICEMAIL_URI, + getVoicemailURI()); + else if(isModification) + accountProperties.put(ProtocolProviderFactory.VOICEMAIL_URI, ""); + + if(!StringUtils.isNullOrEmpty( + getVoicemailCheckURI(), true)) + accountProperties.put( + ProtocolProviderFactory.VOICEMAIL_CHECK_URI, + getVoicemailCheckURI()); + else if(isModification) + accountProperties.put( + ProtocolProviderFactory.VOICEMAIL_CHECK_URI, ""); + + if(isModification) { - setVoicemailURI(""); - setVoicemailCheckURI(""); // remove the property as true is by default, // and null removes property - removeAccountProperty( - ProtocolProviderFactory.VOICEMAIL_ENABLED); - } else - { - accountProperties.put( - ProtocolProviderFactory.VOICEMAIL_ENABLED, - Boolean.FALSE.toString()); + accountProperties.put(ProtocolProviderFactory.VOICEMAIL_ENABLED, + null); } } + else if(isModification) + { + accountProperties.put(ProtocolProviderFactory.VOICEMAIL_ENABLED, + Boolean.FALSE.toString()); + } super.storeProperties( protocolIconPath, accountIconPath, accountProperties); -- cgit v1.1 From 90dd38a8f6a03a5ca43da14712f2c84f0f598d2b Mon Sep 17 00:00:00 2001 From: ibauersachs Date: Wed, 1 Mar 2017 21:06:28 +0000 Subject: Commit from translate.jitsi.org by user ibauersachs.: 1505 of 1505 strings translated (0 fuzzy). --- resources/languages/resources_ru.properties | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/resources/languages/resources_ru.properties b/resources/languages/resources_ru.properties index 16b1206..d58bc13 100644 --- a/resources/languages/resources_ru.properties +++ b/resources/languages/resources_ru.properties @@ -40,7 +40,7 @@ service.gui.ABOUT=&О программе service.gui.ACCEPT=&Принять service.gui.ACCOUNT=Аккаунт service.gui.ACCOUNT_ME=Я -service.gui.ACCOUNT_REGISTRATION_WIZARD=Мастер регистрации учетных записей +service.gui.ACCOUNT_REGISTRATION_WIZARD=Мастер регистрации учётных записей service.gui.ACCOUNTS=Учётные записи service.gui.ADD=&Добавить service.gui.ADD_CONTACT=&Добавить контакт @@ -150,6 +150,7 @@ service.gui.CLEAR=Очистить service.gui.CLOSE=За&крыть service.gui.CLOSE_CHAT_AFTER_NEW_MESSAGE=Вы получили новое сообщение менее, чем 2 секунды назад. Вы уверены, что желаете закрыть этот чат? service.gui.CLOSE_CHAT_ACTIVE_FILE_TRANSFER=У вас имеются активные передачи файлов. Вы уверенны, что желаете прервать их? +service.gui.CONFIRM=Подтвердить service.gui.CONNECTED_STATUS=Подключен service.gui.CONNECTING=Подключение... service.gui.CONNECTING_STATUS=Подключение @@ -157,6 +158,8 @@ service.gui.CONNECTING_EARLY_MEDIA_STATUS=Подключение* service.gui.CONNECTION=Соединение service.gui.CONNECTION_EXPIRED_MSG=В данный момент вы отключены от сервера {0}. service.gui.CONTACT_NAME=ID или номер +service.gui.CONTACT_NAME_PROMPT=jane.doe@example.com +service.gui.CONTACT_NAME_INFO=Добавить адрес для мгновенных сообщений (например: jane.doe@example.com) или номер IP-телефонии service.gui.CONTACT_NOT_SUPPORTING_CHAT_CONF=Выбранный контакт {0} не поддерживает чат в конференции. service.gui.CONTACT_PAUSED_TYPING={0} перестал печатать сообщение service.gui.CONTACT_TYPING={0} печатает сообщение @@ -185,6 +188,8 @@ service.gui.DESKTOP_SHARING_WARNING=Вы уверены, что хотите service.gui.DESKTOP_SHARING_DIALOG_INDICATE=Вы показыаете свой экран service.gui.DIALPAD=Номеронабиратель service.gui.DISPLAY_NAME=Отображаемое имя +service.gui.DISPLAY_NAME_PROMPT=Jane Doe +service.gui.DISPLAY_NAME_INFO=Добавить имя для этого контакта. Если оставить пустым, будет использован адрес IM или номер VoIP. (Необязательно) service.gui.DISCONNECTED_STATUS=Отключено service.gui.DND_STATUS=Не беспокоить service.gui.DO_NOT_ASK_AGAIN=Не спрашивать снова @@ -466,8 +471,11 @@ service.gui.SEARCH=&Поиск service.gui.SEARCH_FOR_CHAT_ROOMS_MSG=Нажмите кнопку ниже, чтобы показать все чаты, существующие на выбранном сервере. Затем выберите тот, в который хотите присоединиться и нажмите на кнопку соединения. service.gui.SEARCH_STRING_CONTACT_SOURCE=Поиск контактов service.gui.SECURITY=Безопасность +service.gui.SELECT_ACCOUNT=Выбрать аккаунт +service.gui.SELECT_ACCOUNT_INFO=Какую учётную запись вы хотите использовать для связи с этим контактом? service.gui.SELECT_COLOR=Выбрать цвет service.gui.SELECT_GROUP=Выбрать группу +service.gui.SELECT_GROUP_INFO=Под какой группой вы хотите отобразить этот контакт? (Необязательно) service.gui.SELECT_NO_GROUP=Без группы service.gui.SELECT_PROVIDERS_FOR_CHAT_ROOM=Представленный ниже список содержит все учетные записи, которые поддерживают многопользовательский чат. Выберите тот, который хотите использовать для создания конференции. service.gui.SELECT_VIDEO_CONFERENCE=Выбрать видеоконференцию @@ -626,6 +634,7 @@ service.gui.callinfo.AUDIO_INFO=Аудио поток service.gui.callinfo.VIDEO_INFO=Видео поток service.gui.callinfo.LOCAL_IP=Локальный IP / Порт service.gui.callinfo.REMOTE_IP=Удаленный IP / Порт +service.gui.callinfo.BANDWITH=Пропускная способность service.gui.callinfo.LOSS_RATE=Потеря пакетов service.gui.callinfo.RTT=RTT service.gui.callinfo.JITTER=Джиттер @@ -641,6 +650,7 @@ service.gui.callinfo.ICE_STATE.WAITING=Получение кандидатов service.gui.callinfo.ICE_STATE.RUNNING=Проверка подключения service.gui.callinfo.ICE_STATE.COMPLETED=Завершено service.gui.callinfo.ICE_STATE.FAILED=Ошибка +service.gui.callinfo.ICE_STATE.TERMINATED=Завершённый service.gui.callinfo.ICE_LOCAL_HOST_ADDRESS=Локальный IP / Порт service.gui.callinfo.ICE_LOCAL_REFLEXIVE_ADDRESS=Локальный входящий IP / Порт @@ -740,6 +750,12 @@ service.gui.security.encryption.required=Требуется шифрование service.protocol.ICE_FAILED=Невозможно установить подключение (сбой ICE, не найдено трансляции) +service.systray.MODE=Реализация лотка +service.systray.mode.NATIVE=Исходный +service.systray.mode.DISABLED=Деактивирован +service.systray.mode.APPINDICATOR=Индикатор приложения (Unity, KDE, неясно с Gnome 3; может упасть на Debian) +service.systray.mode.APPINDICATOR_STATIC=Статический индикатор приложения (нет меню состояния учётной записи) +service.systray.CLI_NOTE=Если ваш выбор не работает, вы можете выполнить {0} с опцией "--notray". Это принудительно переведёт статус в положение "Деактивирован" и покажет графический интерфейс. Изменение состояния лотка требует перезапуска. impl.protocol.sip.XCAP_ERROR_TITLE=Ошибка в адресной книге SIP impl.protocol.sip.XCAP_ERROR_RESOURCE_ERR=Ресурс не может быть прочитан {0}. Для {1} @@ -803,8 +819,10 @@ impl.ldap.PHONE_PREFIX=Телефонный префикс impl.ldap.PHONE_PREFIX_EXAMPLE=Например: +7 # SIP Protocol +impl.protocol.sip.INVALID_ADDRESS=''{0}'' не является действительным SIP адресом. #Jabber Protocol +impl.protocol.jabber.INVALID_ADDRESS=''{0}'' не является действительным XMPP JID. # Address book plugin plugin.addrbook.ADDRESS_BOOKS=Адресная книга @@ -829,6 +847,10 @@ impl.googlecontacts.USERNAME=Имя аккаунта impl.googlecontacts.PASSWORD=Пароль impl.googlecontacts.PREFIX=Телефонный префикс impl.googlecontacts.WRONG_CREDENTIALS=Неверные данные для аккаунта Google {0} +impl.googlecontacts.OAUTH_DIALOG_TITLE=Авторизация через Google Контакты +impl.googlecontacts.INSTRUCTIONS=

    Нажмите на ссылку ниже, чтобы утвердить плагину Google Контакты доступ к учётной записи.

    Нажав на ссылку, в вашем обозревателе откроется веб-страница. Войдите в требуемую учётную запись и подтвердите доступ. После утверждения, Google покажет вам код. Скопируйте этот код в текстовое поле ниже и нажмите 'Сохранить'

    Это одноразовая операция. Токен авторизации будет сохранён для последующего использования.

    +impl.googlecontacts.CODE=Код: +impl.googlecontacts.HYPERLINK_TEXT=Нажмите здесь, чтобы одобрить доступ к {0} # account info plugin.accountinfo.TITLE=Информация об аккаунте @@ -885,6 +907,7 @@ plugin.aimaccregwizz.REGISTER_NEW_ACCOUNT_TEXT=В случае, если вы н plugin.branding.ABOUT_WINDOW_TITLE=О нас {0} plugin.branding.LOGO_MESSAGE=Open Source VoIP && Обмен мгновенными сообщениями plugin.branding.ABOUT_MENU_ENTRY=&О программе +plugin.branding.COPYRIGHT_LICENSE=
    Авторские права 2003-{1} {3}, Все права защищены.

    {4} распространяется на условиях {6}.
    plugin.busylampfield.PICKUP=Поднять трубку @@ -912,6 +935,8 @@ plugin.generalconfig.REMOVE_SPECIAL_PHONE_SYMBOLS=Удалить специал plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS=Преобразовывать буквы в цифры телефонного номера plugin.generalconfig.ACCEPT_PHONE_NUMBER_WITH_ALPHA_CHARS_EXAMPLE=напр. +1-800-MYPHONE преобразуется в +1-800-694663 plugin.generalconfig.SIP_CALL_CONFIG=SIP +plugin.generalconfig.XMPP_CONFIG=XMPP +plugin.generalconfig.XMPP_USE_ALL_RESOURCES=Использовать все ресурсы при обнаружении возможностей контакта plugin.generalconfig.OPUS_CONFIG=Кодек Opus plugin.generalconfig.OPUS_AUDIO_BANDWIDTH=Частота выборки: plugin.generalconfig.OPUS_BITRATE=Средняя скорость кодировщика (кбит/с) @@ -925,6 +950,7 @@ plugin.generalconfig.SILK_ALWAYS_ASSUME_PACKET_LOSS=Всегда учитыва plugin.generalconfig.SILK_SAT=Порог голосовой активности (0-1): plugin.generalconfig.SILK_ADVERTISE_FEC=Объявлять поддержку FEC в SDP: plugin.generalconfig.RESTORE=Восстановить значения по умолчанию +plugin.generalconfig.MINIMIZE_NOT_HIDE=Минимизировать основное окно вместо закрытия или сворачивания # gibberish accregwizz plugin.gibberishaccregwizz.PROTOCOL_NAME=Gibberish @@ -963,9 +989,11 @@ plugin.ircaccregwizz.SASL_IRC_PASSWORD_USED=Вышеупомянутый IRC п plugin.ircaccregwizz.RESOLVE_DNS_THROUGH_PROXY=Всегда разрешать DNS имена через прокси # jabber accregwizz +plugin.jabberaccregwizz.PROTOCOL_NAME=XMPP plugin.jabberaccregwizz.PROTOCOL_DESCRIPTION=Протокол XMPP plugin.jabberaccregwizz.USERNAME=Имя пользователя XMPP plugin.jabberaccregwizz.PASSWORD_CONFIRM=Подтвердите пароль +plugin.jabberaccregwizz.USERNAME_AND_PASSWORD=ID и пароль plugin.jabberaccregwizz.CSERVER=Сервер plugin.jabberaccregwizz.SERVER=Подключение к серверу plugin.jabberaccregwizz.ENABLE_KEEP_ALIVE=Поддерживать подключение @@ -983,6 +1011,7 @@ plugin.jabberaccregwizz.AUTORESOURCE=Автоматическое создани plugin.jabberaccregwizz.PRIORITY=Приоритет plugin.jabberaccregwizz.UNKNOWN_XMPP_ERROR=Неизвестная ошибка XMPP ({0)}. Убедитесь, что имя сервера является правильным. plugin.jabberaccregwizz.NOT_SAME_PASSWORD=Пароли не совпадают. +plugin.jabberaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Переопределить параметры сервера по умолчанию plugin.jabberaccregwizz.USE_ICE=Использовать ICE plugin.jabberaccregwizz.AUTO_DISCOVER_STUN=Автоматически обнаруживать STUN/TURN сервера plugin.jabberaccregwizz.SUPPORT_TURN=Поддерживать TURN @@ -1029,6 +1058,7 @@ plugin.jabberaccregwizz.DISABLE_JINGLE=Отключить Jingle (аудио и # plugin manager plugin.pluginmanager.INSTALL=Установить plugin.pluginmanager.UNINSTALL=Удалить +plugin.pluginmanager.UPDATE=Обновить plugin.pluginmanager.PLUGINS=Плагины plugin.pluginmanager.URL=Ссылка plugin.pluginmanager.CHOOSE_FILE=Выбор файла @@ -1055,6 +1085,7 @@ plugin.sipaccregwizz.PROXY_PORT=Порт прокси plugin.sipaccregwizz.PREFERRED_TRANSPORT=Предпочтительный вид транспорта plugin.sipaccregwizz.PROXY_OPTIONS=Настройки прокси-сервера plugin.sipaccregwizz.PROXY_AUTO=Автоматическая настройка прокси-сервера +plugin.sipaccregwizz.PROXY_FORCE_BYPASS=Обход проверки безопасности прокси для сценариев HA (использовать только при необходимости) plugin.sipaccregwizz.ENABLE_PRESENCE=Включить присутствие (SIMPLE) plugin.sipaccregwizz.FORCE_P2P_PRESENCE=Принудительно включить режим присутствия peer-to-peer plugin.sipaccregwizz.OFFLINE_CONTACT_POLLING_PERIOD=Период опроса контактов не в сети (в сек.) @@ -1182,6 +1213,7 @@ plugin.ippiaccregwizz.EXISTING_ACCOUNT=Существующие ippi аккау plugin.ippiaccregwizz.CREATE_ACCOUNT=Создать бесплатную учетную запись ippi # key binding chooser +plugin.keybindings.WAITING=Нажмите ярлык... #in new ChatWindow() -> manipulated plugin.keybindings.CHAT_CLOSE=Закрыть окно чата plugin.keybindings.CHAT_COPY=Копировать @@ -1384,6 +1416,7 @@ plugin.securityconfig.masterpassword.COL_PASSWORD=Пароль plugin.securityconfig.masterpassword.PROTOCOL_UNKNOWN=(неизвестно) plugin.securityconfig.masterpassword.CANNOT_DECRYPT=(не могу расшифровать) plugin.securityconfig.masterpassword.STORED_ACCOUNT_PASSWORDS=Сохраненные пароли +plugin.securityconfig.masterpassword.REMOVE_PASSWORD_BUTTON=Удалить plugin.securityconfig.masterpassword.REMOVE_ALL_PASSWORDS_BUTTON=Удалить все plugin.securityconfig.masterpassword.REMOVE_ALL_CONFIRMATION=Вы уверены, что хотите удалить все пароли? plugin.securityconfig.masterpassword.REMOVE_ALL_TITLE=Удалить все пароли @@ -1479,6 +1512,7 @@ plugin.globalproxy.PROXY_PORT=Порт plugin.globalproxy.PROXY_USERNAME=Имя пользователя plugin.globalproxy.PROXY_PASSWORD=Пароль plugin.globalproxy.DESCRIPTION={0} будет использовать перечисленные параметры прокси-сервера для всех сетей при следующем подключении. \nПоддержка прокси в настоящее время экспериментальная и работает только с некоторыми протоколами. Смотрите таблицу ниже для более подробной информации: +plugin.globalproxy.PROTOCOL_SUPPORT=
    SOSCKS4/5 SOSCKS4/5+Аутентификация HTTP HTTP+Аутентификация
    XMPP (Джаббер)++++
    ICQ/AIM++++
    #plugin.globalproxy.PROTOCOL_SUPPORT plugin.globalproxy.FWD_DNS=Также проксифицировать DNS plugin.globalproxy.FWD_DNS_NOTE=Полезно с Тор. Помогает избежать утечки DNS, направляя весь DNS трафик через Тор прокси. Требуется перезагрузка. -- cgit v1.1 From cf5da997da8820b4050f5b87ee9440a0ede36d1f Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Thu, 2 Mar 2017 00:23:36 +0100 Subject: Strip native code not matching the installer platform Follow-up to bc3f0942854004a228ecb8aa7678496ec0b3e14e --- resources/install/build.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/resources/install/build.xml b/resources/install/build.xml index 98202f8..fa8e3d5 100644 --- a/resources/install/build.xml +++ b/resources/install/build.xml @@ -580,6 +580,10 @@ + + + + @@ -1200,6 +1204,10 @@ + + + + @@ -3243,6 +3251,10 @@ + + + Bundle-ClassPath: .,libjitsi-impl.jar,fmj.jar,jitsi-lgpl-dependencies.jar,libjitsi.jar,bcpkix.jar + fixlastline="true">Bundle-ClassPath: .,libjitsi-impl.jar,fmj.jar,jitsi-gpl-dependencies.jar,jitsi-lgpl-dependencies.jar,libjitsi.jar,bcpkix.jar reference:file:/usr/share/jitsi-common/libjitsi.jar -- cgit v1.1

  • In order to use Facebook Chat you need to create a "Username"
    from your "Account Settings" page on Facebook.


    Note: When you create username you must logout from the webpage
    and it can take a while before you are able to login with your new username!